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

Determine WebView Implementation (System WebView or Chrome)

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

因为这可能意味着那些使用 WebViews 的人现在需要担心两个不同的代码库,所以了解当前选择了哪个实现会很有用。

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

看起来像现在可以在 Android O 预览:

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

Starting in Android 7.0 (API level 24), users can choose among several different packages for displaying web content in a WebView object. Android O includes an API for fetching information related to the package that is displaying web content in your app. This API is especially useful when analyzing errors that occur only when your app tries to display web content using a particular package's implementation of WebView.

To use this API, add the logic shown in the following code snippet:

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

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

作为 的补充信息,对于低于 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"
    }

为了获得当前的 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);
}

Remember: Immediately after an app update of WebView, a crash could appear as described here: , at this moment, this line webViewFactory.getMethod("getLoadedPackageInfo") of the code above would return null. Actually there is nothing you can do to prevent this, (this should not happen if the WebView implementation is taken from Chrome app but is not confirmed).

有一个 appCompat 版本:

WebViewCompat.getCurrentWebViewPackage(context)

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