¿`ShouldOverrideUrlLoading` está realmente en desuso? ¿Qué puedo usar en su lugar?

138

¿"ShouldOverrideUrlLoading" está realmente en desuso? Si es así, ¿qué puedo usar en su lugar?

Parece que shouldOverrideUrlLoadingestá en desuso la orientación a Android N y necesito hacer que una aplicación funcione desde la API 19 hasta la última en este momento, que es Android N (beta), utilizo algunas funciones que son nuevas en Android N (como Data Saver), por lo que la orientación Marshmallow no me ayudará con el problema ya que necesito usar esas nuevas funciones, aquí está la parte del código que uso:

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

Y este es el mensaje que me dio Android Studio:

Invalida el método obsoleto en 'android.webkit.WebViewClient'. Esta inspección informa de dónde se utiliza el código obsoleto en el ámbito de inspección especificado.

Google no dice nada sobre esa desaprobación .

Me pregunto si el uso @SuppressWarnings("deprecation")me permitirá trabajar en todos los dispositivos desde la API 19 hasta la última versión de Android N Beta (y su versión final cuando se lance), no puedo probarlo yo mismo, nunca lo usé y necesito estar seguro que funciona, entonces, ¿alguien puede decirlo?

Esbirro
fuente
1
Hay dos versiones de ese método de devolución de llamada. El viejo está en desuso. En este caso, "en desuso" significa "oye, tenemos algo más que quizás quieras probar, si es apropiado para ti". La devolución de llamada anterior debería continuar funcionando, ya que se requiere la devolución de llamada anterior para las versiones anteriores a N de Android.
CommonsWare
Primero, gracias por el comentario, creo que la versión que estoy usando es la buena, ya que es exactamente la misma que la de los desarrolladores de Android Docs, excepto por el nombre de la cadena, usaron "view" y yo usé "webview" , para el resto es lo mismo, entonces, ¿por qué debo hacer para que funcione en todas las versiones?
Minion

Respuestas:

95

La versión que estoy usando, creo que es la buena, ya que es exactamente la misma que la de los documentos para desarrolladores de Android, excepto por el nombre de la cadena, usaron "view" y yo usé "webview", porque el resto es el mismo

No, no es.

El que es nuevo en N Developer Preview tiene la firma de este método:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

El que es compatible con todas las versiones de Android, incluida N, tiene la firma de este método:

public boolean shouldOverrideUrlLoading(WebView view, String url)

Entonces, ¿por qué debo hacer para que funcione en todas las versiones?

Reemplazar el obsoleto, el que toma a Stringcomo segundo parámetro.

CommonsWare
fuente
Hola, y gracias por la respuesta, que todavía no es compatible desde API 19, porque para obtener la cadena URL tengo que usar "url.getUrl (). ToString ()" y se ha agregado en API 21, de cualquier manera para hacer Funciona desde API 19?
Minion
3
@Minion: "eso todavía no es compatible desde API 19" - sí, lo es. "porque para obtener la cadena URL tengo que usar" url.getUrl (). toString () "" - no, la URL se proporciona como el segundo parámetro, en forma de a String. Por ejemplo, esta aplicación de ejemplo , compilada con API Level 19, funciona bien, como en un Nexus 5. con Android 6.0.
CommonsWare
Hola, el uso de la "solicitud WebResourceRequest" no tiene un parámetro de cadena
Minion
2
@ Minion: Correcto. Eso solo funciona en Android N (y, presumiblemente, superior). Usted preguntó "entonces, ¿por qué debo hacer para que funcione en todas las versiones?". Te dije que anularas el obsoleto, el que toma a Stringcomo segundo parámetro. Por ejemplo, la aplicación de muestra a la que me vinculé, que anula la devolución de llamada obsoleta, funciona bien en un Nexus 6 que ejecuta N Developer Preview 1.
CommonsWare
66
Si desea estar preparado para el futuro, podría anular AMBOS métodos. De esa manera, su aplicación continuará funcionando en <21, pero estará listo para funcionar una vez que dejen de utilizar el método anterior. Y no tendrá que preocuparse getUrl()porque el nuevo método solo se solicitará 24+
yuval
187

Documentación detallada para futuros lectores:

La respuesta corta es que debe anular ambos métodos. El shouldOverrideUrlLoading(WebView view, String url)método está en desuso en la API 24 y el shouldOverrideUrlLoading(WebView view, WebResourceRequest request)método se agrega en la API 24. Si está apuntando a versiones anteriores de Android, necesita el método anterior, y si está apuntando a 24 (o posterior, si alguien está leyendo esto en un futuro lejano) También es recomendable anular el último método.

El siguiente es el esqueleto sobre cómo lograrías esto:

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

Al igual que shouldOverrideUrlLoading, puede llegar a un enfoque similar para el shouldInterceptRequestmétodo.

Enrique
fuente
66
@ webo80 En realidad se agrega en API24 / N developer.android.com/reference/android/webkit/…
Henry
3
Es mejor usarlo @RequiresApien lugar de @TargetApi aquí para usarlo en el futuro
Hibbem el
1
¡El problema con anular ambos métodos, al menos con shouldInterceptRequest, es que en los dispositivos Android N + ambos se invocan y manejarás cada uri dos veces! Para remediar eso, agregué una Build.VERSION.SDK_INT < Build.VERSION_CODES.Ncondición en la versión obsoleta.
Jonik
8
@JohnLee Normalmente, solo se invocará uno de los métodos. Pero si tuviera que colocar super. shouldOverrideUrlLoading(view,request)el método no obsoleto, entonces sí, se invocarán tanto el método no obsoleto como el obsoleto. Esto se debe a que la implementación predeterminada del método no obsoleto es invocar internamente el método obsoleto. Solo eche un vistazo a la WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request). Así que asegúrate de no llamar super.shouldOverrideUrlLoading().
Henry
1
Solo señalar que la funcionalidad de tener ambos métodos llamados no está documentada. No confiaría en que siempre sea así, ya que no se menciona en la documentación.
Austyn Mahoney
15

Utilizar

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}
Saleem Kalro
fuente
2
es view.loadUrl (request.getUrl (). toString ());
Hibbem
funciona, pero si la usamos, cerrará la aplicación
MRRaja
44
esto no
admitiría una
-1

Implemente métodos obsoletos y no obsoletos como a continuación. El primero es manejar API nivel 21 y superior, el segundo es manejar más bajo que API nivel 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
fuente
1
Esto parece ser una copia parcial de la respuesta de Henry, pero esto descarta el valor devuelto por Uri.parsey parseUri. Las nuevas respuestas deberían agregar nueva información útil y nuevas ideas sobre el tema.
AdrianHHH
Me hizo perder tiempo ya que la API solo está en desuso en API 24 y no 21
Gustavo Baiocchi Costa