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

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

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

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

【问题讨论】:

    标签: java android webview android-webview android-7.0-nougat


    【解决方案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://stackoverflow.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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-08-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 1970-01-01
          相关资源
          最近更新 更多