Czy opcja „shouldOverrideUrlLoading” jest naprawdę przestarzała? Czego mogę zamiast tego użyć?

138

Czy „shouldOverrideUrlLoading” jest naprawdę przestarzały? Jeśli tak, czego mogę użyć zamiast tego?

Wygląda na to, że shouldOverrideUrlLoadingjest przestarzała dla systemu Android N i muszę sprawić, by aplikacja działała od API 19 do najnowszego, czyli Android N (beta). Używam niektórych funkcji, które są nowe w Androidzie N (np. Oszczędzanie danych), więc celowanie Marshmallow nie pomoże w rozwiązaniu problemu, ponieważ muszę użyć tych nowych funkcji, oto część kodu, którego używam:

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

A oto wiadomość, którą przekazał mi Android Studio:

Zastępuje przestarzałą metodę w „android.webkit.WebViewClient”. Ta inspekcja zgłasza przypadki użycia przestarzałego kodu w określonym zakresie inspekcji.

Google nic nie mówi o tym wycofaniu .

Zastanawiam się, czy używanie @SuppressWarnings("deprecation")pozwoli mi pracować na wszystkich urządzeniach od API 19 do najnowszego Androida N Beta (i jego ostatecznej wersji po premierze), sam nie mogę tego przetestować, nigdy tego nie używałem i muszę mieć pewność że to działa, więc każdy może powiedzieć?

Sługus
źródło
1
Istnieją dwie wersje tej metody wywołania zwrotnego. Stary jest przestarzały. W tym przypadku „przestarzałe” oznacza „hej, mamy coś innego, czego możesz chcieć wypróbować, jeśli jest to dla Ciebie odpowiednie”. Stare wywołanie zwrotne powinno nadal działać, ponieważ stare wywołanie zwrotne jest wymagane w przypadku wersji Androida wcześniejszych niż N.
CommonsWare
Po pierwsze, dziękuję za komentarz, uważam, że wersja, której używam, jest dobra, ponieważ jest dokładnie taka sama jak w dokumentacji programisty Androida, z wyjątkiem nazwy ciągu, użyli „widoku”, a ja użyłem „widoku internetowego” reszta jest taka sama, więc po co mam robić, żeby działało na wszystkich wersjach?
Minion

Odpowiedzi:

95

Wydaje mi się, że wersja, której używam, jest dobra, ponieważ jest dokładnie taka sama jak w Android Developer Docs, z wyjątkiem nazwy ciągu, używali „view”, a ja „webview”, reszta jest taka sama

Nie, nie jest.

Ten, który jest nowy w N Developer Preview, ma następującą sygnaturę metody:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

Ten, który jest obsługiwany przez wszystkie wersje Androida, w tym N, ma następujący podpis metody:

public boolean shouldOverrideUrlLoading(WebView view, String url)

Dlaczego więc mam to zrobić, aby działało we wszystkich wersjach?

Zastąp przestarzały parametr, który przyjmuje Stringjako drugi parametr.

CommonsWare
źródło
Witam i dziękuję za odpowiedź, że nadal nie jest kompatybilna od API 19, ponieważ aby uzyskać ciąg URL muszę użyć "url.getUrl (). ToString ()" i został dodany na API 21, jakikolwiek sposób działa od API 19?
Minion
3
@Minion: „to nadal nie jest kompatybilne od API 19” - tak, jest. "ponieważ aby uzyskać ciąg adresu URL muszę użyć" url.getUrl (). toString () "" - nie, adres URL jest podawany jako drugi parametr w postaci String. Na przykład ta przykładowa aplikacja , skompilowana na poziomie API 19, działa dobrze, na przykład na Nexusie 5 z systemem Android 6.0
CommonsWare
Witaj, użycie „żądania WebResourceRequest” nie ma parametru String
Minion,
2
@Minion: Dobrze. Działa to tylko na Androidzie N (i prawdopodobnie wyższym). Zapytałeś „więc dlaczego mam to zrobić, aby działało we wszystkich wersjach?”. Powiedziałem ci, aby zastąpić nieaktualny, ten, który przyjmuje a Stringjako drugi parametr. Na przykład przykładowa aplikacja, z którą
utworzyłem łącze
6
Jeśli chcesz być przyszłościowy, możesz faktycznie zastąpić OBIE metody. Dzięki temu Twoja aplikacja będzie nadal działać w wersji <21, ale będziesz gotowy do pracy, gdy całkowicie wycofają starą metodę. I nie będziesz musiał się o to martwić, getUrl()ponieważ nowa metoda będzie wywoływana tylko dla 24+
yuval
187

Szczegółowa dokumentacja dla przyszłych czytelników:

Krótka odpowiedź brzmi: musisz zastąpić obie metody. Ta shouldOverrideUrlLoading(WebView view, String url)metoda jest przestarzała w API 24, a shouldOverrideUrlLoading(WebView view, WebResourceRequest request)metoda została dodana w API 24. Jeśli kierujesz na starsze wersje Androida, potrzebujesz poprzedniej metody, a jeśli celujesz w 24 (lub nowszą, jeśli ktoś czyta to w odległej przyszłości) wskazane jest również zastąpienie tej drugiej metody.

Poniżej znajduje się szkielet tego, jak możesz to osiągnąć:

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;
        }
    }
}

Podobnie shouldOverrideUrlLoadingmożesz wymyślić podobne podejście do shouldInterceptRequestmetody.

Henz
źródło
6
@ webo80 Właściwie jest dodany w API24 / N developer.android.com/reference/android/webkit/…
Henry
3
Lepiej jest używać @RequiresApitutaj zamiast @TargetApi do użytku w przyszłości
Hibbem
1
Problem z zastąpieniem obu metod, przynajmniej w przypadku shouldInterceptRequest, polega na tym, że na urządzeniach z Androidem N + obie są wywoływane i będziesz obsługiwać każdy uri dwa razy! Aby temu zaradzić, dodałem Build.VERSION.SDK_INT < Build.VERSION_CODES.Nwarunek w wycofanej wersji.
Jonik,
8
@JohnLee Normalnie zostanie wywołana tylko jedna z metod. Ale jeśli miałbyś wstawić super. shouldOverrideUrlLoading(view,request)metodę, która nie jest przestarzała, to tak, zostanie wywołana zarówno metoda, która nie jest przestarzała, jak i ta, która nie jest przestarzała. Dzieje się tak, ponieważ domyślną implementacją metody, która nie jest przestarzała, jest wewnętrzne wywołanie metody, która nie jest przestarzała. Wystarczy spojrzeć na plik WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Więc upewnij się, że nie dzwonisz super.shouldOverrideUrlLoading().
Henry,
1
Zwracam tylko uwagę, że funkcjonalność wywołania obu metod nie jest udokumentowana. Nie polegałbym na tym, że zawsze tak jest, ponieważ nie jest to wymienione w dokumentacji.
Austyn Mahoney
15

Posługiwać się

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}
Saleem Kalro
źródło
2
to view.loadUrl (request.getUrl (). toString ());
Hibbem
jego praca, ale jeśli użyjemy wcześniej, zamknie aplikację
MRRaja
4
to nie obsługuje api mniejszych niż 21
mumair
-1

Zaimplementuj zarówno przestarzałe, jak i nie wycofane metody, jak poniżej. Pierwszy z nich to obsługa interfejsu API na poziomie 21 i wyższym, a drugi na poziomie niższym niż poziom API 21

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
        }
}
emre
źródło
1
Wydaje się, że jest to częściowa kopia odpowiedzi Henry'ego, ale powoduje to odrzucenie wartości zwróconej przez Uri.parsei parseUri. Nowe odpowiedzi powinny dostarczyć nowych przydatnych informacji i nowych spostrzeżeń na ten temat.
AdrianHHH
Sprawiło, że straciłem czas, ponieważ api jest przestarzałe tylko w API 24, a nie 21
Gustavo Baiocchi Costa