Android - 如何检查 WebView 是否可用?

6

有没有一种方法可以检查设备上是否可用Webview?

背景: 如果我在清单中添加<uses-feature android:name="android.software.webview"/>,那么在Google Play上支持的设备数量从12,000多个下降到不到6,000个设备。因此,我将android:required="false"添加到此功能。如果可用Webview,则应在应用程序内显示网站,否则在默认浏览器中启动:

String mUrl = "http://www.example.com";
if (*** WHAT TO PUT HERE? ***) {
    WebView webview = (WebView) findViewById(R.id.webView);
    if (Build.VERSION.SDK_INT >= 24) {
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                view.loadUrl(request.toString());
                return false;
            }
        });
    } else {
        webview.setWebViewClient(new WebViewClient() {
            @SuppressWarnings("deprecation")
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return false;
            }
        });
    }
    webview.loadUrl(mUrl);
} else {
    Uri uri = Uri.parse(mUrl);
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    startActivity(intent);
}
编辑(以澄清问题):<uses-permission android:name="android.permission.INTERNET" /> 是(且一直是)清单的一部分。只有添加 <uses-feature android:name="android.software.webview" /> 才会导致不支持的设备数量减少。

这里有一个遇到相同问题的人:https://issuetracker.google.com/issues/37035282 (不幸的是没有得到答复)

6个回答

10
尽管@vsatkh指出将此功能声明为必需项并非必要,但您可以按以下方式检查设备的功能兼容性:

尽管@vsatkh指出将此功能声明为必需项并非必要,但您可以按以下方式检查设备的功能兼容性:

getPackageManager().hasSystemFeature("android.software.webview")

该方法返回真或假。

关于Google Play过滤的一些额外信息: Google Play只根据清单中声明的<uses-feature>元素来过滤支持的设备。除非<uses-permission>元素暗示了一个特性,否则不会影响Google Play的过滤。 android.permission.INTERNET并不暗示任何特性。 暗示特性的权限列在此处: https://developer.android.com/guide/topics/manifest/uses-feature-element.html#permissions


3
使用API 20及更高版本,您可以使用PackageManager.FEATURE_WEBVIEW代替硬编码字符串。 - Jacob Ras

9

替代方案:
val hasWebView: Boolean = kotlin.runCatching { CookieManager.getInstance() }.isSuccess

它的原理是如果WebView不可用,那么CookieManager.getInstance()将抛出AndroidRuntimeException异常。

getPackageManager().hasSystemFeature("android.software.webview")不是很可靠。如果设备应该有一个webview,但在系统设置中已禁用,则它将返回true。

我在华为P20上进行了测试,方法是前往 设置 -> 应用程序 -> 安卓系统 WebView -> 禁用。


1
已在Android 10和11上进行了测试。它可以正常工作!添加了您代码的Java版本。 - Rohit Singh

6

有绕过的方法:CookieManager

AFAIK(据我所知):没有专门的API可以提供这些信息。但是如果告诉你有一个方法可以绕过去呢?

如Torkel所述,getPackageManager().hasSystemFeature(..)不能保证告诉您Android系统WebView是否启用或禁用。

即使用户在设置中禁用了WebView,getPackageManager().hasSystemFeature(..)仍将返回true。

CookieManager

因此,一种替代方法是使用CookieManager
应用程序WebView的cookie由CookieManager管理。当WebView被禁用时,尝试创建CookieManager实例会引发异常。

在Kotlin中,您可以从块语句中获取结果,但在Java中不可能。所以您可以在函数中使用异常处理逻辑来决定。

以下是一个示例:

public boolean webViewEnabled(){

    try{

       CookieManager.getInstance();
       return true;

    }catch(Exception e){

       return false;

    }

}

注意:

当前的实现可能会在未来发生变化,或者他们可能会针对此问题提供一个专门的API。我曾在许多论坛中尝试寻找完美的解决方案,但这是我所能达到的最接近的方法。
使用这个解决方案将可以防止你的应用程序崩溃,但你仍然会在日志中看到错误信息,因为CookieManager.getInstance会抛出异常对象。


1
您可以在这里阅读更详细的内容 https://source.android.com/compatibility/android-cdd.pdf
根据 WebView 兼容性部分,android.software.webview 功能表示设备或 OEM 必须提供完整的 android.webkit.WebView API 实现。因此,实际上,大多数设备没有完全实现 webkit 所需的所有 API,因此 Play 商店上的设备数量有所下降。
因此,如果您的网络内容需要某些 html5 功能,请在此处检查 http://mobilehtml5.org/,如果您的应用程序目标是 KitKat 或甚至 Lollipop+,那么您应该是安全的。
因此,除非您的网络内容确实需要 webkit 的所有 API,否则无需声明 android.software.webview 功能。

1
从API 26开始,您可以使用WebView.getCurrentWebViewPackage()来检查是否安装并激活了有效的WebView。CookieManager检查可能非常缓慢(高达500毫秒),如果检查发生在关键路径中,可能会影响启动性能。
从文档中可以看到:

如果WebView已经加载到当前进程中,则此方法将返回用于加载它的包。否则,将返回如果现在加载WebView将要使用的包;这不会导致WebView被加载,因此此信息可能随时过时。

当当前WebView包更新、禁用或卸载时,WebView包会更改。也可以通过开发人员设置进行更改。如果WebView包更改,任何已加载WebView的应用程序进程都将被终止。下次应用程序启动并加载WebView时,它将使用新的WebView包。

@return 当前WebView包,如果没有则为{@code null}。

您可以通过交换WebView实现并调用此方法来列出PackageName(例如,如果您正在运行dev/beta Chrome WebViews)来验证此功能是否按预期工作:

WebView.getCurrentWebViewPackage()?.packageName

您可以通过运行以下ADB命令来测试禁用状态(尽管您可能需要通过adb root以root身份运行模拟器):adb shell pm disable <webview-package-id>

-1

当然。这个权限已经包含在清单中了。如果webview始终可用,为什么支持的设备数量会下降? - klabauter
3
WebView 并不总是可用的。 - Demigod
例如,在“WebView”更新安装期间 - 如果在商店应用程序中设置了自动更新,则可能随时自动触发(即使在使用“WebView”的其他应用程序运行期间)。我已经阅读到,一些新的Android版本(10?)通过在后台安装更新(任何应用程序的更新),并且只有在不使用应用程序时才替换旧包来修复此问题。 - snachmsm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接