`shouldOverrideUrlLoading` 真的被弃用了吗?我可以用啥代替?

Posted

技术标签:

【中文标题】`shouldOverrideUrlLoading` 真的被弃用了吗?我可以用啥代替?【英文标题】:Is `shouldOverrideUrlLoading` really deprecated? What can I use instead?`shouldOverrideUrlLoading` 真的被弃用了吗?我可以用什么代替? 【发布时间】:2016-07-28 19:13:05 【问题描述】:

“shouldOverrideUrlLoading”真的被弃用了吗?如果是这样,我可以用什么代替?

似乎shouldOverrideUrlLoading 已弃用针对 Android N,我需要让应用程序从 API 19 开始工作,直到现在最新的 android N(测试版),我使用了一些功能是 Android N 中的新功能(如 Data Saver),因此定位 Marshmallow 对解决问题没有帮助,因为我需要使用这些新功能,这是我使用的代码部分:

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 says nothing about that deprecation.

我想知道使用@SuppressWarnings("deprecation") 是否可以让我在从 API 19 到最新的 Android N Beta(及其发布时的最终版本)的所有设备上工作,我自己无法测试它,我从未使用过而且我需要确保它有效,所以,任何人都可以说出来吗?

【问题讨论】:

该回调方法有两个版本。旧的已弃用。在这种情况下,“不推荐使用”的意思是“嘿,如果适合你,我们还有一些你可能想尝试的东西”。旧回调应该会继续工作,因为旧的回调是前 N 版本的 Android 所必需的。 首先,感谢您的评论,我使用的版本我认为是好的版本,因为与Android开发者文档完全相同,除了字符串的名称,他们使用“ view”,我用的是“webview”,其余的都是一样的,那我为什么要让它在所有版本上都能正常工作呢? 【参考方案1】:

我认为我使用的版本很好,因为它与 Android 开发者文档完全相同,除了字符串的名称,他们使用“view”,我使用“webview”,其余的是一样的

不,不是。

N 开发者预览版的新功能有这个方法签名:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

包括N在内的所有Android版本都支持的那个有这个方法签名:

public boolean shouldOverrideUrlLoading(WebView view, String url)

那我为什么要让它在所有版本上都能正常工作呢?

覆盖已弃用的那个,即采用String 作为第二个参数的那个。

【讨论】:

您好,感谢您的回答,自 API 19 以来仍然不兼容,因为要获取 URL 字符串,我必须使用“url.getUrl().toString()”并且它已被添加在 API 21 上,从 API 19 开始有什么方法可以让它工作? @Minion:“自 API 19 以来仍然不兼容”——是的,是的。 “因为要获取 URL 字符串,我必须使用“url.getUrl().toString()””——不,URL 是作为第二个参数提供的,以 String 的形式提供。例如,this sample app,针对 API 级别 19 编译,可以正常工作,例如在基于 Android 6.0 的 Nexus 5 上。 您好,使用“WebResourceRequest 请求”没有String参数 @Minion:正确。这仅适用于 Android N(并且可能更高)。您问“那我为什么要让它适用于所有版本?”。我告诉过您要覆盖已弃用的那个,即以String 作为第二个参数的那个。例如,我链接到的示例应用程序覆盖了已弃用的回调,在运行 N Developer Preview 1 的 Nexus 6 上运行良好。 如果您想要面向未来,您实际上可以覆盖这两种方法。这样,您的应用程序将继续在 getUrl(),因为新方法只会在 24+ 时被调用【参考方案2】:

使用

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

【讨论】:

是 view.loadUrl(request.getUrl().toString()); 它的工作,但如果我们使用回来,那么它会关闭应用程序 不支持小于 21 的 api【参考方案3】:

为未来的读者详细记录:

简短的回答是您需要覆盖这两种方法。 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 方法想出类似的方法。

【讨论】:

这里最好使用@RequiresApi而不是@TargetApi以备将来使用 覆盖这两种方法的问题,至少在shouldInterceptRequest 中,是在Android N+ 设备上,它们被both 调用,你将处理每个uri 两次!为了解决这个问题,我在已弃用的版本中添加了 Build.VERSION.SDK_INT < Build.VERSION_CODES.N 条件。 @JohnLee 通常只会调用其中一种方法。但是,如果您将super. shouldOverrideUrlLoading(view,request) 放在非弃用方法中,那么是的,非弃用方法和弃用方法都将被调用。这是因为非弃用方法的默认实现是在内部调用弃用方法。看看WebViewClient.shouldOverrideUrlLoading(WebView view, WebResourceRequest request)。所以请确保你不要打电话给super.shouldOverrideUrlLoading() @AustynMahoney 我没有说我们必须依赖内部实现。上面的答案不依赖于内部实现。我引用它来解释为什么有时会在最新的 API 版本中调用已弃用和未弃用的方法。目标是覆盖这两种方法并确保仅调用其中一种。如果造成任何误解,我很抱歉 为了加入讨论,我已经尝试过 Pie 上的代码,并且只调用了其中一种方法。【参考方案4】:

同时实现已弃用和未弃用的方法,如下所示。第一个是处理 API 级别 21 及更高,第二个是处理低于 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
        

【讨论】:

这似乎是亨利答案的部分副本,但这会丢弃 Uri.parseparseUri 返回的值。新答案应该为主题添加有用的新信息和新见解。 让我浪费时间,因为 api 仅在 API 24 而不是 21 上被弃用

以上是关于`shouldOverrideUrlLoading` 真的被弃用了吗?我可以用啥代替?的主要内容,如果未能解决你的问题,请参考以下文章

WebView shouldOverrideUrlLoading功能

shouldOverrideUrlLoading 仅在某些网页上被调用

android webview中shouldOverrideUrlLoading方法的返回值问题

错误消息-> shouldOverrideUrlLoading Webview Android

如果在超时回调中修改了“window.location.href”,则 shouldOverrideUrlLoading(...) 不会执行

Android 的 WebView 中的 shouldOverrideUrlLoading 未运行