Чи дійсно `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.