Чи дійсно `deOverrideUrlLoading` застарілий? Що я можу використовувати замість цього?


138

Чи справді застаріле "mustOverrideUrlLoading" застаріле? Якщо так, то що я можу використовувати замість цього?

Схоже, shouldOverrideUrlLoadingце застаріле націлювання на Android N, і мені потрібно, щоб програма працювала з API 19 до останнього зараз - Android N (бета-версія), я використовую деякі функції, які є новими в Android N (наприклад, Data Saver), тому націлювання Зефір не допоможе вирішити цю проблему, оскільки мені потрібно використовувати ці нові функції, ось частина коду, який я використовую:

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 Beta (і її остаточної версії, коли вона вийде), я не можу перевірити її сам, я ніколи цього не використовував, і мені потрібно бути впевненим що це працює, тож, хто може сказати?


1
Існує дві версії цього методу зворотного виклику. Старий застарілий. У цьому випадку "застарілий" означає "ей, у нас є щось інше, що ви можете спробувати, якщо це підходить вам". Старий зворотний дзвінок повинен продовжувати працювати, оскільки старий зворотний дзвінок необхідний для попередніх N версій Android.
CommonsWare

По-перше, дякую за коментар, версія, яку я використовую, я вважаю гарною, оскільки точно така ж, як і Android Developer Docs, за винятком назви рядка, вони використовували "view", а я використовував "webview" , для решти це те саме, то чому я повинен робити це, щоб він працював на всіх версіях?
Міньйон

Відповіді:


95

Версія, яку я використовую, я вважаю хорошою, оскільки точно така ж, як і Android Developer Docs, за винятком назви рядка, вони використовували "view", а я використовував "webview", для решти те саме

Ні, це не так.

Той, що є новим для попереднього перегляду N Developer, має цей підпис:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

Ця версія, яка підтримується всіма версіями Android, включаючи N, має цей підпис:

public boolean shouldOverrideUrlLoading(WebView view, String url)

То чому я повинен робити це, щоб він працював на всіх версіях?

Замініть застарілий, той, який приймає Stringза другий параметр.


Привіт, і дякую за відповідь, що досі не сумісний з 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
Minion

2
@Minion: Правильно. Це працює лише на Android N (і, імовірно, вище). Ви запитали "так чому я повинен робити, щоб він працював на всіх версіях?". Я сказав вам перемогти застарілий, той, який приймає Stringза другий параметр. Наприклад, зразок додатка, до якого я посилався, який переосмислює застарілий зворотний виклик, працює чудово на Nexus 6, на якому працює попередній перегляд N Developer 1.
CommonsWare

6
Якщо ви хочете бути впевненими у майбутньому, ви можете насправді перебрати БОТИ методи. Таким чином ваша програма продовжуватиме працювати на <21, але ви будете готові розпочати роботу, як тільки вони повністю застарять старий метод. І вам не доведеться турбуватися про те, getUrl()тому що новий метод буде викликатися тільки для 24+
Юваль

187

Детально документуючи майбутні читачі:

Коротка відповідь - вам потрібно перекрити обидва методи. 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

8
@JohnLee Зазвичай буде використовуватися лише один із методів. Але якщо ви мали б застосувати super. shouldOverrideUrlLoading(view,request)метод, який не є застарілим, тоді так буде виведено і неактуальний, і застарілий метод. Це тому, що реалізація за замовчуванням методу, що не використовується, за замовчуванням полягає у внутрішньому виклику застарілого методу. Просто погляньте на WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Тому переконайтеся, що вам не дзвонити super.shouldOverrideUrlLoading().
Генрі

1
Тільки вказуючи, що функціональність використання обох методів не задокументована. Я б не покладався на те, що це завжди так, оскільки це не зазначено в документації.
Austyn Mahoney

15

Використовуйте

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}

2
це view.loadUrl (request.getUrl (). toString ());
Хіббем

його робота, але якщо ми повернемося назад, вона закриє додаток
MRRaja

4
це не підтримуватиме api менше 21
mumair

-1

Реалізуйте як застарілі, так і непридатні методи, як показано нижче. Перший - це обробка рівня 21 і вище API, другий - обробка нижче, ніж рівень 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
Gustavo Baiocchi Costa,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.