确定 WebView 实现(系统 WebView 或 Chrome)

Posted

技术标签:

【中文标题】确定 WebView 实现(系统 WebView 或 Chrome)【英文标题】:Determine WebView Implementation (System WebView or Chrome) 【发布时间】:2017-05-05 05:14:26 【问题描述】:

android 7.0 允许用户(通过开发人员选项)选择其 WebView 的实现。用户可以选择独立的 WebView 或使用 Chrome APK 来呈现 WebView。 Reference

由于这可能意味着使用 WebViews 的用户现在需要担心两个不同的代码库,因此了解当前选择了哪个实现会很有用。

有没有办法确定在 Android 7 中选择了哪种 WebView 实现?

【问题讨论】:

【参考方案1】:

现在在 Android O 预览版中看起来像这样:

链接:https://developer.android.com/preview/features/managing-webview.html

从 Android 7.0(API 级别 24)开始,用户可以在多个 用于在 WebView 对象中显示 Web 内容的不同包。 Android O 包含一个 API,用于获取与 在您的应用中显示 Web 内容的包。这个 API 是 在分析仅当您的应用程序出现的错误时特别有用 尝试使用特定包的显示 Web 内容 WebView 的实现。

要使用这个API,添加如下代码sn-p所示的逻辑:

PackageInfo webViewPackageInfo = WebView.getCurrentWebViewPackage();
Log.d(TAG, "WebView version: " + webViewPackageInfo.versionName);

WebView.getCurrentWebViewPackage 文档:https://developer.android.com/reference/android/webkit/WebView.html#getCurrentWebViewPackage()

【讨论】:

还有 WebViewCompat.getCurrentWebViewPackage() 可以在 L+ 上工作【参考方案2】:

为了获取当前的 Android WebView 实现和版本,我创建了这个方法,它应该对每个 API 级别都有效。

@SuppressLint("PrivateApi")
@SuppressWarnings("unchecked", "JavaReflectionInvocation")
public @Nullable PackageInfo getCurrentWebViewPackageInfo() 
    PackageInfo pInfo = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
        //starting with Android O (API 26) they added a new method specific for this
        pInfo = WebView.getCurrentWebViewPackage();
     else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
        //with Android Lollipop (API 21) they started to update the WebView 
        //as a separate APK with the PlayStore and they added the
        //getLoadedPackageInfo() method to the WebViewFactory class and this
        //should handle the Android 7.0 behaviour changes too
        try 
            Class webViewFactory = Class.forName("android.webkit.WebViewFactory");
            Method method = webViewFactory.getMethod("getLoadedPackageInfo");
            pInfo = (PackageInfo) method.invoke(null);
         catch (Exception e) 
            e.printStackTrace();
        
     else 
        //before Lollipop the WebView was bundled with the
        //OS, the fixed versions can be found online, for example:
        //Android 4.4 has WebView version 30.0.0.0
        //Android 4.4.3 has WebView version 33.0.0.0
        //etc...
    
    return pInfo;

然后你可以评估结果

if (pInfo != null) 
    Log.d("WEBVIEW VERSION", pInfo.packageName + ", " + pInfo.versionName);

记住:WebView 的应用更新后,会立即崩溃 可能如下所示: https://***.com/a/29809338/2910520,此时,上面代码的这一行webViewFactory.getMethod("getLoadedPackageInfo") 将返回null。 其实有 您无法采取任何措施来防止这种情况发生(如果 WebView 实现取自 Chrome 应用但未得到确认,则不应发生这种情况)。

【讨论】:

对于第二种方法(Lollipop 直到 Oreo),您必须确保“WebView 已加载到当前进程中”。如果没有初始化 WebView getLoadedPackageInfo 将返回 null。 目前无法知道 WebView 何时加载。这就是代码在 try-catch 中的原因。也许我们可以添加一个延迟来执行检查,以便有更多的机会加载 WebView。我可以向你保证,即使我只调用公共 API,我也会遇到同样的问题,例如在 Application 中调用 WebView.enableSlowWholeDocumentDraw() 作为第一件事,我已经报告了与此相关的背景异常的 CrashLytics :( @MatPag 在将 WebView 实现连接到当前进程之前,我们可以安全地假设这只是时间问题吗?当通过通知中的 PendingIntent 启动时,我在膨胀 WebView 的活动中偶尔遇到 RuntimeException 崩溃。您认为添加延迟可能会有所帮助吗?谢谢【参考方案3】:

作为the answer of DataDino 的补充信息,对于低于 26 的 API,这里有一段代码可以提供所需的输出:

Class webViewFactory = Class.forName("android.webkit.WebViewFactory"); Method method = webViewFactory.getMethod("getLoadedPackageInfo"); PackageInfo packageInfo = (PackageInfo) method.invoke(null, null); if ("com.android.webview".equals(packageInfo.packageName)) // "Android System WebView" is selected else // something else selected // in case of chrome it would be "com.android.chrome"

【讨论】:

【参考方案4】:

有一个appCompat版本:

WebViewCompat.getCurrentWebViewPackage(context)

【讨论】:

【参考方案5】:
dependencies 

    // ...
    implementation 'androidx.webkit:webkit:1.4.0' // Add to your gradle


public static String WebViewPackageName(Context context) 
    PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(context);
    return webViewPackageInfo.packageName;

【讨论】:

以上是关于确定 WebView 实现(系统 WebView 或 Chrome)的主要内容,如果未能解决你的问题,请参考以下文章

Android系统 WebView是啥?有啥用?

webview 的右键菜单

android webview怎么实现下拉刷新

webView导致tableview滞后

如何正确使用 swipeWithEvent 导航 webView,Obj-C

怎么设置webview内容大小