Действительно ли `shouldOverrideUrlLoading` устарело? Что я могу использовать вместо этого?

146

Действительно ли "shouldOverrideUrlLoading" устарело? Если да, то что я могу использовать вместо этого?

Похоже, таргетинг на Android NshouldOverrideUrlLoading устарел, и мне нужно, чтобы приложение работало с API 19 до последней версии, которая сейчас является Android N (бета), я использую некоторые функции, которые являются новыми в Android N (например, Data Saver), поэтому нацеливание Marshmallow не поможет с этой проблемой, поскольку мне нужно использовать эти новые функции, вот часть кода, который я использую:

public boolean shouldOverrideUrlLoading(WebView webview, String url) {
    if (url.startsWith("http:") || url.startsWith("https:")) {
        ...
    } else if (url.startsWith("sms:")) {
        ...
    }
    ...
}

И это сообщение, которое мне дала Android Studio:

Переопределяет устаревший метод в android.webkit.WebViewClient. В этом отчете о проверке используется устаревший код в указанной области проверки.

Google ничего не говорит об этом .

Интересно @SuppressWarnings("deprecation"), позволит ли использование мне работать на всех устройствах с API 19 до последней бета-версии Android N (и ее финальной версии, когда она будет выпущена), я не могу протестировать ее сам, я никогда не использовал это, и мне нужно быть уверенным что это работает, так что кто-нибудь может сказать?

Миньон
источник
2
Есть две версии этого метода обратного вызова. Старая версия устарела. В данном случае «устаревший» означает «эй, у нас есть кое-что еще, что вы можете попробовать, если оно вам подходит». Старый обратный вызов должен продолжать работать, поскольку старый обратный вызов требуется для версий Android до N.
CommonsWare
Во-первых, спасибо за комментарий, я считаю, что версия, которую я использую, является хорошей, поскольку она точно такая же, как и в документации для разработчиков Android, за исключением имени строки, они использовали «view», а я использовал «webview» , в остальном то же самое, так зачем мне делать, чтобы он работал на всех версиях?
Миньон

Ответы:

97

Версия, которую я использую, я считаю хорошей, так как она точно такая же, как и в документации для разработчиков Android, за исключением названия строки, они использовали "view", а я использовал "webview", в остальном все то же самое.

Нет это не так.

Тот, который является новым для N Developer Preview, имеет такую ​​сигнатуру метода:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

Тот, который поддерживается всеми версиями Android, включая N, имеет такую ​​сигнатуру метода:

public boolean shouldOverrideUrlLoading(WebView view, String url)

Так зачем мне это делать, чтобы он работал на всех версиях?

Замените устаревший, тот, который принимает в Stringкачестве второго параметра.

CommonsWare
источник
Здравствуйте, и спасибо за ответ, который все еще несовместим с API 19, потому что для получения строки URL-адреса мне нужно использовать url.getUrl (). ToString (), и он был добавлен в API 21, любой способ сделать он работает с API 19?
Миньон
3
@Minion: «это все еще несовместимо с API 19» - да, это так. "потому что для получения строки URL-адреса я должен использовать" url.getUrl (). toString () "" - нет, URL-адрес предоставляется в качестве второго параметра в форме String. Например, этот образец приложения , скомпилированный с использованием API уровня 19, отлично работает, например, на Nexus 5 под управлением Android 6.0
CommonsWare,
Здравствуйте, при использовании «запроса WebResourceRequest» параметр String отсутствует
Миньон,
2
@ Миньон: Верно. Это работает только на Android N (и, предположительно, выше). Вы спросили «так зачем мне это делать, чтобы он работал на всех версиях?». Я сказал вам переопределить устаревший, тот, который принимает в Stringкачестве второго параметра. Например, пример приложения, с которым я связался, которое переопределяет устаревший обратный вызов, отлично работает на Nexus 6, на котором запущена N Developer Preview 1.
CommonsWare,
6
Если вы хотите быть ориентированными на будущее, вы можете переопределить ОБЕИХ методы. Таким образом, ваше приложение будет продолжать работать на <21, но вы будете готовы к работе, как только они полностью откажутся от старого метода. И вам не о чем беспокоиться, getUrl()потому что новый метод будет вызываться только 24+
ювал 08
193

Подробное документирование для будущих читателей:

Короткий ответ: вам нужно переопределить оба метода. Этот shouldOverrideUrlLoading(WebView view, String url)метод устарел в API 24, а shouldOverrideUrlLoading(WebView view, WebResourceRequest request)метод добавлен в API 24. Если вы ориентируетесь на более старые версии Android, вам нужен первый метод, а если вы ориентируетесь на 24 (или более поздние версии , если кто-то читает это в отдаленном будущем) Желательно также переопределить последний метод.

Ниже приведен скелет того, как вы бы это сделали:

class CustomWebViewClient extends WebViewClient {

    @SuppressWarnings("deprecation")
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        final Uri uri = Uri.parse(url);
        return handleUri(uri);
    }

    @TargetApi(Build.VERSION_CODES.N)
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        final Uri uri = request.getUrl();
        return handleUri(uri);
    }

    private boolean handleUri(final Uri uri) {
        Log.i(TAG, "Uri =" + uri);
        final String host = uri.getHost();
        final String scheme = uri.getScheme();
        // Based on some condition you need to determine if you are going to load the url 
        // in your web view itself or in a browser. 
        // You can use `host` or `scheme` or any part of the `uri` to decide.
        if (/* any condition */) {
            // Returning false means that you are going to load this url in the webView itself
            return false;
        } else {
            // Returning true means that you need to handle what to do with the url
            // e.g. open web page in a Browser
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
            return true;
        }
    }
}

Точно так же shouldOverrideUrlLoadingвы можете придумать аналогичный подход для shouldInterceptRequestметода.

Генри
источник
6
@ webo80 На самом деле он добавлен в API24 / N developer.android.com/reference/android/webkit/…
Генри
3
Здесь лучше использовать @RequiresApiвместо @TargetApi для будущего использования
Hibbem
1
Проблема с переопределением обоих методов, по крайней мере shouldInterceptRequest, заключается в том, что на устройствах Android N + они оба вызываются, и вы будете обрабатывать каждый uri дважды! Чтобы исправить это, я добавил Build.VERSION.SDK_INT < Build.VERSION_CODES.Nусловие в устаревшую версию.
Jonik 07
9
@JohnLee Обычно будет вызван только один из методов. Но если вы super. shouldOverrideUrlLoading(view,request)добавите нерекомендуемый метод, то да, будут вызываться как нерекомендуемый, так и устаревший метод. Это связано с тем, что реализация нерекомендуемого метода по умолчанию заключается в внутреннем вызове устаревшего метода. Просто взгляните на файл WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Поэтому убедитесь, что вы не звоните super.shouldOverrideUrlLoading().
Генри
1
Просто укажите, что функциональность вызова обоих методов не задокументирована. Я бы не стал полагаться на то, что так будет всегда, поскольку об этом не упоминается в документации.
Остин Махони
16

Использовать

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}
Салим Калро
источник
2
это view.loadUrl (request.getUrl (). toString ());
Hibbem
его работа, но если мы воспользуемся назад, оно закроет приложение
MRRaja
4
это не будет поддерживать api менее 21
mumair
-1

Реализуйте устаревшие и нерекомендуемые методы, как показано ниже. Первый - обрабатывать уровень API 21 и выше, второй - обрабатывать уровень ниже 21 API.

webViewClient = object : WebViewClient() {
.
.
        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
            parseUri(request?.url)
            return true
        }

        @SuppressWarnings("deprecation")
        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
            parseUri(Uri.parse(url))
            return true
        }
}
Эмре
источник
1
Кажется, это частичная копия ответа Генри, но это отбрасывает значение, возвращаемое Uri.parseи parseUri. Новые ответы должны добавить новую полезную информацию и новое понимание темы.
AdrianHHH
Заставил меня потерять время, так как api устарел только на API 24, а не 21
Густаво Байокки Коста