14

Android 7.0 allows users (via developer options) to choose the implementation of their WebView. The user can choose the standalone WebView or use the Chrome APK to render WebViews. Reference

Since this potentially means those who use WebViews now have two different code bases to worry about, it would be useful to know which implementation is currently selected.

Is there a way to determine what WebView implementation is selected in Android 7?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
DataDino
  • 1,507
  • 1
  • 15
  • 30

5 Answers5

7

Looks like this now available in Android O Preview:

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 Documentation: https://developer.android.com/reference/android/webkit/WebView.html#getCurrentWebViewPackage()

DataDino
  • 1,507
  • 1
  • 15
  • 30
4

To get the current Android WebView implementation and version I've created this method which should be valid for every API level.

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

Then you can evaluate the result

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: https://stackoverflow.com/a/29809338/2910520, 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).

MatPag
  • 41,742
  • 14
  • 105
  • 114
  • For the second approach (Lollipop until Oreo) you have to make sure that "WebView has already been loaded into the current process". If no WebView is initialized `getLoadedPackageInfo` will return null. – G00fY Nov 15 '18 at 14:43
  • 1
    Currently there is no way to know when the WebView is loaded. That's why the code is inside a try-catch. Maybe we could add a delay to perform the check to have more chances the WebView has been loaded. I can assure you I'm having the same problem even if I call only public API, for example calling WebView.enableSlowWholeDocumentDraw() as first thing in Application, I've reports on CrashLytics of background exception related to this :( – MatPag Nov 15 '18 at 15:00
  • @MatPag Can we safely assume that this is only a matter of time, before a WebView implementation is wired into the current process? I experience occasional crashes on RuntimeException in an activity inflating WebView, when started via a PendingIntent from notification. Do you think adding a delay might help? Thx – Gabriel Jun 19 '19 at 06:02
2

As a supplementary info to the answer of DataDino, for APIs below 26 here's a chunk of code that would give the desired output:


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

azizbekian
  • 60,783
  • 13
  • 169
  • 249
2

There is an appCompat version:

WebViewCompat.getCurrentWebViewPackage(context)

tonyo.dev
  • 692
  • 1
  • 5
  • 12
0
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;
}
Shahrad Elahi
  • 774
  • 12
  • 22