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

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

Похоже, что shouldOverrideUrlLoading устарел с таргетингом на Android N, и мне нужно, чтобы приложение работало с 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 (и ее финальной версией, когда она будет выпущена), я не могу проверить это сам, я никогда этим не пользовался, и мне нужно уверен, что это работает, так что кто-нибудь может сказать?


person Minion    schedule 07.04.2016    source источник
comment
Есть две версии этого метода обратного вызова. Старая версия устарела. В этом случае слово «не рекомендуется» означает, что у нас есть кое-что еще, что вы можете попробовать, если оно вам подходит. Старый обратный вызов должен продолжать работать, поскольку старый обратный вызов требуется для версий Android до N.   -  person CommonsWare    schedule 07.04.2016
comment
Во-первых, спасибо за комментарий, версия, которую я использую, я считаю хорошей, поскольку она точно такая же, как и в документации для разработчиков Android, за исключением имени строки, они использовали представление, а я использовал веб-просмотр, для всего остального То же самое, так зачем мне это делать, чтобы он работал на всех версиях?   -  person Minion    schedule 07.04.2016


Ответы (4)


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

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

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

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

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

public boolean shouldOverrideUrlLoading(WebView view, String url)

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

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

person CommonsWare    schedule 07.04.2016
comment
Здравствуйте, и спасибо за ответ, который все еще несовместим с API 19, потому что для получения строки URL-адреса мне нужно использовать url.getUrl (). ToString (), и он был добавлен в API 21 любым способом, чтобы заставить его работать начиная с API 19? - person Minion; 07.04.2016
comment
@Minion: это все еще несовместимо с API 19 - да, это так. потому что для получения строки URL-адреса мне нужно использовать url.getUrl (). toString () - нет, URL-адрес предоставляется в качестве второго параметра в виде String. Например, этот образец приложения, скомпилированный с использованием API уровня 19. , работает нормально, например, на Nexus 5 под управлением Android 6.0. - person CommonsWare; 07.04.2016
comment
Здравствуйте, использование запроса WebResourceRequest не имеет параметра String - person Minion; 07.04.2016
comment
@ Миньон: Верно. Это работает только на Android N (и, предположительно, выше). Вы спросили, так зачем мне это делать, чтобы он работал на всех версиях ?. Я сказал вам переопределить устаревший, тот, который принимает String в качестве второго параметра. Например, пример приложения, с которым я связался, которое переопределяет устаревший обратный вызов, отлично работает на Nexus 6, на котором запущена N Developer Preview 1. - person CommonsWare; 07.04.2016
comment
Спасибо большое за вашу помощь :) - person Minion; 07.04.2016
comment
Если вы хотите быть ориентированными на будущее, вы можете переопределить ОБЕИХ методы. Таким образом, ваше приложение продолжит работать на ‹21, но вы будете готовы к работе, как только они полностью откажутся от старого метода. И вам не придется беспокоиться о getUrl(), потому что новый метод будет вызываться только для 24+ - person yuval; 08.10.2016
comment
@SuppressWarnings (прекращение поддержки) - person Michael; 06.07.2017
comment
@SuppressWarnings (устаревание) скорее - person Michael; 06.07.2017
comment
Как сказал @yuval, переопределите оба. Добавьте аннотации к новому с помощью TargetApi (androidN), а к старому с помощью SuppressWarnings, и ваши инструменты будут довольны. - person Snicolas; 19.10.2017

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

Короткий ответ: вам нужно переопределить оба метода. Метод 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.

person Henry    schedule 20.07.2016
comment
Здесь для будущее использование - person Hibbem; 02.11.2016
comment
@Henry getUrl () требуется минимальный уровень API 21, так что как нам работать с API более низкой версии - person Garg's; 20.12.2016
comment
@ Garg's Зачем тебе getUrl()? Для более низкой версии вы получите прямой URL-адрес в виде строки в методе shouldOverrideUrlLoading(WebView view, String url). Вы можете получить Uri по этому URL. - person Henry; 20.12.2016
comment
Или вы можете передать представление методу handleUri (), а затем получить из него контекст с помощью метода view.getContext () - person gonephishing; 18.03.2017
comment
Проблема с переопределением обоих методов, по крайней мере с shouldInterceptRequest, заключается в том, что на устройствах Android N + они вызываются оба, и вы будете обрабатывать каждый uri дважды! Чтобы исправить это, я добавил условие Build.VERSION.SDK_INT < Build.VERSION_CODES.N в устаревшую версию. - person Jonik; 07.06.2017
comment
может ли кто-нибудь подтвердить то, что сказал @Jonik, применимо к shouldOverrideUrlLoading? - person Maria; 09.07.2017
comment
@JohnLee Обычно будет вызван только один из методов. Но если вы поместите super. shouldOverrideUrlLoading(view,request) в нерекомендуемый метод, тогда будут вызываться как нерекомендуемый, так и устаревший метод. Это связано с тем, что реализация по умолчанию нерекомендуемого метода заключается в внутреннем вызове устаревшего метода. Просто взгляните на WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Поэтому убедитесь, что вы не звоните super.shouldOverrideUrlLoading(). - person Henry; 09.07.2017
comment
@ Генри Я не уверен, что мы хотим полагаться на эту функциональность. Это не задокументировано, поэтому может быть изменено в будущем выпуске. - person Austyn Mahoney; 13.07.2017
comment
@AustynMahoney Я не говорил, что мы должны зависеть от внутренней реализации. Ответ выше не зависит от внутренней реализации. Я процитировал это, чтобы объяснить, почему иногда в последней версии API вызываются как устаревшие, так и нерекомендуемые методы. Цель состоит в том, чтобы переопределить оба метода и обеспечить вызов только одного из них. Прошу прощения, если я вызвал недоразумение - person Henry; 13.07.2017
comment
Просто укажу, что функциональность вызова обоих методов не задокументирована. Я бы не стал полагаться на то, что так будет всегда, поскольку это не упоминается в документации. - person Austyn Mahoney; 19.07.2017
comment
Действительно предусмотрительный ответ. - person Kirill Starostin; 27.08.2018
comment
Чтобы добавить к обсуждению, я попробовал код на Pie, и был вызван только один из методов. - person Subhrajyoti Sen; 18.12.2018
comment
Это нормально работает, но когда ссылка открывается в браузере, веб-просмотр становится белым экраном, как я могу это исправить? - person Bouh; 17.11.2020

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

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}
person Saleem Kalro    schedule 09.07.2016
comment
это view.loadUrl (request.getUrl (). toString ()); - person Hibbem; 14.09.2016
comment
его работа, но если мы используем обратно, оно закроет приложение - person MRRaja; 20.12.2016
comment
это не будет поддерживать api меньше 21 - person mumair; 15.03.2017

Реализуйте как устаревшие, так и нерекомендуемые методы, как показано ниже. Первый - обрабатывать уровень 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
        }
}
person emre    schedule 25.07.2019
comment
Похоже, это частичная копия ответа Генри, но при этом отбрасывается значение, возвращаемое Uri.parse и parseUri. Новые ответы должны добавить новую полезную информацию и новое понимание темы. - person AdrianHHH; 25.07.2019
comment
Заставил меня потерять время, так как api устарел только на API 24, а не 21 - person Gustavo Baiocchi Costa; 12.09.2019