Ist `shouldOverrideUrlLoading` wirklich veraltet? Was kann ich stattdessen verwenden?

137

Ist "shouldOverrideUrlLoading" wirklich veraltet? Wenn ja, was kann ich stattdessen verwenden?

Es scheint, als wäre shouldOverrideUrlLoadingdas Targeting auf Android N veraltet und ich muss dafür sorgen, dass eine App seit API 19 funktioniert, bis zum neuesten Stand, Android N (Beta). Ich verwende einige Funktionen, die in Android N neu sind (wie Data Saver), also Targeting Marshmallow wird bei dem Problem nicht helfen, da ich diese neuen Funktionen verwenden muss. Hier ist der Teil des Codes, den ich verwende:

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

Und das ist die Nachricht, die Android Studio mir gegeben hat:

Überschreibt veraltete Methode in 'android.webkit.WebViewClient' Diese Überprüfung meldet, wo veralteter Code im angegebenen Überprüfungsbereich verwendet wird.

Google sagt nichts über diese Abwertung .

Ich frage mich, ob @SuppressWarnings("deprecation")ich mit der Funktion auf allen Geräten seit der API 19 bis zur neuesten Android N Beta (und der endgültigen Version, wenn sie veröffentlicht wird) arbeiten kann. Ich kann sie nicht selbst testen. Ich habe sie nie verwendet und muss sicher sein dass es funktioniert, kann also jeder sagen?

Günstling
quelle
1
Es gibt zwei Versionen dieser Rückrufmethode. Der alte ist veraltet. In diesem Fall bedeutet "veraltet" "Hey, wir haben noch etwas, das Sie ausprobieren möchten, wenn es für Sie angemessen ist". Der alte Rückruf sollte weiterhin funktionieren, da der alte Rückruf für Pre-N-Versionen von Android erforderlich ist.
CommonsWare
Erstens, danke für den Kommentar, die Version, die ich verwende, ist meiner Meinung nach die gute, da sie genau mit den Android Developer Docs identisch ist, außer dass der Name der Zeichenfolge "view" und "webview" verwendet wurde. Der Rest ist derselbe. Warum sollte ich also dafür sorgen, dass es auf allen Versionen funktioniert?
Minion

Antworten:

94

Die Version, die ich verwende, ist meiner Meinung nach die gute, da sie genau mit den Android Developer Docs identisch ist, außer dass der Name der Zeichenfolge "view" und ich "webview" verwendet haben, der Rest ist dieselbe

Nein ist es nicht.

Die neue Version in der N Developer Preview hat diese Methodensignatur:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

Diejenige, die von allen Android-Versionen, einschließlich N, unterstützt wird, hat diese Methodensignatur:

public boolean shouldOverrideUrlLoading(WebView view, String url)

Warum sollte ich also dafür sorgen, dass es auf allen Versionen funktioniert?

Überschreiben Sie den veralteten StringParameter , der a als zweiten Parameter verwendet.

CommonsWare
quelle
Hallo, und danke für die Antwort, die seit API 19 immer noch nicht kompatibel ist, denn um die URL-Zeichenfolge zu erhalten, muss ich "url.getUrl (). ToString ()" verwenden und sie wurde auf API 21 hinzugefügt funktioniert es seit API 19?
Minion
3
@Minion: "das ist seit API 19 immer noch nicht kompatibel" - ja, das ist es. "weil ich zum Abrufen der URL-Zeichenfolge" url.getUrl (). toString () "" verwenden muss - nein, die URL wird als zweiter Parameter in Form von a angegeben String. Zum Beispiel funktioniert diese Beispiel-App , die gegen API Level 19 kompiliert wurde,
einwandfrei
Hallo, die Verwendung der "WebResourceRequest-Anfrage" hat keinen String-Parameter
Minion
2
@Minion: Richtig. Das funktioniert nur unter Android N (und vermutlich höher). Sie fragten "Warum sollte ich das tun, damit es auf allen Versionen funktioniert?". Ich habe dir gesagt, du sollst den veralteten überschreiben, der a Stringals zweiten Parameter nimmt. Zum Beispiel funktioniert die Beispiel-App, mit der ich verlinkt habe und die den veralteten Rückruf überschreibt, auf einem Nexus 6, auf dem N Developer Preview 1 ausgeführt wird.
CommonsWare
6
Wenn Sie zukunftssicher sein möchten, können Sie BEIDE Methoden überschreiben. Auf diese Weise funktioniert Ihre App weiterhin mit <21, aber Sie können loslegen, sobald die alte Methode vollständig verworfen wurde. Und Sie müssen sich keine Sorgen machen, getUrl()denn die neue Methode wird nur für 24+
yuval
186

Detaillierte Dokumentation für zukünftige Leser:

Die kurze Antwort lautet, dass Sie beide Methoden überschreiben müssen. Die shouldOverrideUrlLoading(WebView view, String url)Methode ist in API 24 veraltet und die shouldOverrideUrlLoading(WebView view, WebResourceRequest request)Methode wurde in API 24 hinzugefügt. Wenn Sie auf ältere Android-Versionen abzielen, benötigen Sie die frühere Methode und wenn Sie auf 24 abzielen (oder später, wenn jemand dies in ferner Zukunft liest). Es ist ratsam, auch die letztere Methode zu überschreiben.

Das Folgende ist das Grundgerüst, wie Sie dies erreichen würden:

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

Genau wie shouldOverrideUrlLoadingkönnen Sie einen ähnlichen Ansatz für die shouldInterceptRequestMethode entwickeln.

Henry
quelle
6
@ webo80 Eigentlich ist es in API24 / N developer.android.com/reference/android/webkit/…
Henry
3
Es ist besser, @RequiresApihier anstelle von @TargetApi für die zukünftige Verwendung zu verwenden
Hibbem
1
Das Problem beim Überschreiben beider Methoden, zumindest bei shouldInterceptRequest, besteht darin, dass auf Android N + -Geräten beide aufgerufen werden und Sie jede URL zweimal verarbeiten! Um dem abzuhelfen, habe ich Build.VERSION.SDK_INT < Build.VERSION_CODES.Nin der veralteten Version eine Bedingung hinzugefügt .
Jonik
8
@JohnLee Normalerweise wird nur eine der Methoden aufgerufen. Wenn Sie jedoch super. shouldOverrideUrlLoading(view,request)die nicht veraltete Methode eingeben, werden sowohl die nicht veraltete als auch die veraltete Methode aufgerufen. Dies liegt daran, dass die Standardimplementierung der nicht veralteten Methode darin besteht, die veraltete Methode intern aufzurufen. Schauen Sie sich einfach die an WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Stellen Sie also sicher, dass Sie nicht anrufen super.shouldOverrideUrlLoading().
Henry
1
Nur darauf hinzuweisen, dass die Funktionalität des Aufrufs beider Methoden nicht dokumentiert ist. Ich würde mich nicht darauf verlassen, dass dies immer der Fall ist, da dies in der Dokumentation nicht erwähnt wird.
Austyn Mahoney
15

Verwenden

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}
Saleem Kalro
quelle
2
es ist view.loadUrl (request.getUrl (). toString ());
Hibbem
seine Arbeit, aber wenn wir damals verwenden, wird es die App schließen
MRRaja
4
Dies würde API nicht weniger als 21 unterstützen
mumair
-1

Implementieren Sie sowohl veraltete als auch nicht veraltete Methoden wie unten. Erstens wird API-Level 21 und höher behandelt, zweitens wird API-Level 21 behandelt

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
quelle
1
Dies scheint eine teilweise Kopie von Henrys Antwort zu sein, aber dies verwirft den von Uri.parseund zurückgegebenen Wert parseUri. Neue Antworten sollten nützliche neue Informationen und neue Einblicke in das Thema hinzufügen.
AdrianHHH
Ich habe Zeit verloren, da API nur auf API 24 und nicht auf 21 veraltet ist
Gustavo Baiocchi Costa