I am getting errors from Crashlytics that indicates that some devices are missing com.google.android.webview. How is that even possible?
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.app/com.myapp.ReaderActivity}: android.view.InflateException: Binary XML file line #29: Error inflating class com.myapp.MyWebView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: android.view.InflateException: Binary XML file line #29: Error inflating class com.myapp.MyWebView
at android.view.LayoutInflater.createView(LayoutInflater.java:633)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(SourceFile:206)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(SourceFile:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(SourceFile:297)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(SourceFile:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(SourceFile:228)
at android.support.v7.app.ActionBarActivity.setContentView(SourceFile:102)
at com.myapp.ReaderActivity.onCreate(SourceFile:120)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Constructor.java)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(SourceFile:206)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(SourceFile:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(SourceFile:297)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(SourceFile:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(SourceFile:228)
at android.support.v7.app.ActionBarActivity.setContentView(SourceFile:102)
at com.myapp.ReaderActivity.onCreate(SourceFile:120)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: android.util.AndroidRuntimeException: android.content.pm.PackageManager$NameNotFoundException: com.google.android.webview
at android.webkit.WebViewFactory.getFactoryClass(WebViewFactory.java:161)
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:101)
at android.webkit.WebView.getFactory(WebView.java:2185)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2180)
at android.webkit.WebView.setOverScrollMode(WebView.java:2239)
at android.view.View.(View.java:3581)
at android.view.View.(View.java:3675)
at android.view.ViewGroup.(ViewGroup.java:491)
at android.widget.AbsoluteLayout.(AbsoluteLayout.java:55)
at android.webkit.WebView.(WebView.java:538)
at android.webkit.WebView.(WebView.java:483)
at android.webkit.WebView.(WebView.java:466)
at android.webkit.WebView.(WebView.java:453)
at com.myapp.MyWebView.(SourceFile:31)
at java.lang.reflect.Constructor.newInstance(Constructor.java)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(SourceFile:206)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(SourceFile:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(SourceFile:297)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(SourceFile:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(SourceFile:228)
at android.support.v7.app.ActionBarActivity.setContentView(SourceFile:102)
at com.myapp.ReaderActivity.onCreate(SourceFile:120)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: android.content.pm.PackageManager$NameNotFoundException: com.google.android.webview
at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:114)
at android.webkit.WebViewFactory.getFactoryClass(WebViewFactory.java:133)
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:101)
at android.webkit.WebView.getFactory(WebView.java:2185)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2180)
at android.webkit.WebView.setOverScrollMode(WebView.java:2239)
at android.view.View.(View.java:3581)
at android.view.View.(View.java:3675)
at android.view.ViewGroup.(ViewGroup.java:491)
at android.widget.AbsoluteLayout.(AbsoluteLayout.java:55)
at android.webkit.WebView.(WebView.java:538)
at android.webkit.WebView.(WebView.java:483)
at android.webkit.WebView.(WebView.java:466)
at android.webkit.WebView.(WebView.java:453)
at com.myapp.MyWebView.(SourceFile:31)
at java.lang.reflect.Constructor.newInstance(Constructor.java)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.createCustomViewInternal(SourceFile:206)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.access$000(SourceFile:20)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater$PrivateWrapperFactory2.onCreateView(SourceFile:297)
at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater.inflate(SourceFile:60)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(SourceFile:228)
at android.support.v7.app.ActionBarActivity.setContentView(SourceFile:102)
at com.myapp.ReaderActivity.onCreate(SourceFile:120)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
And it is only from devices running Lollipop. I have tested it on my Nexus 5, but I can not reproduce the error. I am using proguard
My MyWebView looks like this:
public class MyWebView extends WebView {
public static final String tag = MyWebView.class.getName();
private HtmlJSInterfaceNew js;
public MyWebView(Context context) {
super(context);
gd = new GestureDetector(context, sogl);
init();
}
public MyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
gd = new GestureDetector(context, sogl);
init();
}
public MyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
gd = new GestureDetector(context, sogl);
init();
}
@SuppressLint("NewApi")
private void init() {
setPadding(0, 0, 0, 0);
MyWebViewClient myWebViewClient = new MyWebViewClient();
this.setWebViewClient(myWebViewClient);
setWebChromeClient(new MyWebChromeClient());
if(!isInEditMode())
{
getSettings().setAllowFileAccess(true);
getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
getSettings().setJavaScriptEnabled(true);
WebSettings webSettings = getSettings();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
webSettings.setAllowContentAccess(false);
}
webSettings.setUseWideViewPort(true);
}
}
public void addMyJavascriptInterface(HtmlJSInterfaceNew htmlJSInterface, String string) {
js = htmlJSInterface;
addJavascriptInterface(htmlJSInterface, string);
}
public class MyWebChromeClient extends WebChromeClient
{
public void onProgressChanged(WebView view, int progress) {
}
}
}
The root cause most be:
android.util.AndroidRuntimeException: android.content.pm.PackageManager$NameNotFoundException: com.google.android.webview
at android.webkit.WebViewFactory.getFactoryClass(WebViewFactory.java:161)
So I am thinking it might have something to do with proguard and maybe the JavascriptInterface. Any ideas?
EDIT: from grepcode I have found the method getFactoryClass:
private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
Application initialApplication = AppGlobals.getInitialApplication();
try {
// First fetch the package info so we can log the webview package version.
String packageName = getWebViewPackageName();
sPackageInfo = initialApplication.getPackageManager().getPackageInfo(packageName, 0);
Log.i(LOGTAG, "Loading " + packageName + " version " + sPackageInfo.versionName +
" (code " + sPackageInfo.versionCode + ")");
// Construct a package context to load the Java code into the current app.
Context webViewContext = initialApplication.createPackageContext(packageName,
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
initialApplication.getAssets().addAssetPath(
webViewContext.getApplicationInfo().sourceDir);
ClassLoader clazzLoader = webViewContext.getClassLoader();
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
try {
return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
clazzLoader);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
}
} catch (PackageManager.NameNotFoundException e) {
// If the package doesn't exist, then try loading the null WebView instead.
// If that succeeds, then this is a device without WebView support; if it fails then
// swallow the failure, complain that the real WebView is missing and rethrow the
// original exception.
try {
return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
} catch (ClassNotFoundException e2) {
// Ignore.
}
Log.e(LOGTAG, "Chromium WebView package does not exist", e);
throw new AndroidRuntimeException(e);
}
}
It's likely that this is happening in the very short time frame immediately after Lollipop's Android System WebView application updates.
I'd seen this error in the Google Play Dev Console, but also had never been able to reproduce it on my Nexus 5, regardless of how much I really tried to stop my app from having access to the Android System WebView app:
java.lang.RuntimeException: Unable to create application com.uninteresting.app.name:
android.util.AndroidRuntimeException: android.content.pm.PackageManager$NameNotFoundException: com.google.android.webview
Then we got word that our app was consistently crashing with the above message on some devices immediately after the System WebView app updates, so I tested that. Still no results, the vanilla Nexus 5 refused to crash our app! So I tried other phones from other manufacturers (roughly 75% of our reports are from Samsung Galaxy devices) and suddenly we were crashing consistently. My testing methodology:
A few little caveats with what I've said so far:
In short, I don't immediately think you're doing anything incorrect with ProGuard or your JavascriptInterface. I'm leaning very strongly toward blaming the firmware as the root cause of the majority of reports, resulting in what should be a smooth update process becoming one that instead causes some apps to outright crash.
Edit: I ran a few more tests and it turns out that all the devices that didn't crash are 5.0 or 5.0.1, while all the devices that did crash were 5.0.2, so I can't comfortably point my finger at OEMs anymore.