I am in the process of updating an Android app from API 27 to API 29 and I noticed that I get a crash when trying to render a WebView on an emulator based on 5.0 and/or 5.1. This issue does not happen on an emulator running 6.0 or higher (API 23-29).
I cannot seem to find any documentation about WebView behaviour that would affect 5.0 or 5.1 but I can confirm the problem doesn't happen when I run the app using API 27. I am at a loss as I don't know if this is an emulator problem or an actual API/device issue (I am thinking the latter).
The issue is the Activity and Fragment won't inflate at all, due to a missing String resource. Here is some of the stacktrace (it can't seem to find a String resource):
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.MyActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.MyWebView Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.MyWebView... Caused by: java.lang.reflect.InvocationTargetException... Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040002
Before the crash happens, there is some related warnings in the logs related to the resource:
W/chromium: [WARNING:resource_bundle.cc(315)] locale_file_path.empty() E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824 W/chromium: [WARNING:proxy_service.cc(901)] PAC support disabled because there is no system implementation W/chromium: [WARNING:data_reduction_proxy_settings.cc(403)] SPDY proxy OFF at startup W/ResourceType: No known package when getting value for resource number 0x02040002
WebView:
public class MyWebView extends WebView { public MyWebView (Context context) { super(context); initialize(); } public MyWebView (Context context, AttributeSet attrs) { super(context, attrs); initialize(); } public MyWebView (Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(); } public MyWebView (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initialize(); } public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) { super(context, attrs, defStyleAttr, privateBrowsing); initialize(); } private void initialize() { this.clearCache(true); this.clearHistory(); this.getSettings().setJavaScriptEnabled(true); this.getSettings().setLoadsImagesAutomatically(true); this.getSettings().setUseWideViewPort(true); this.getSettings().setAllowContentAccess(false); this.getSettings().setAllowFileAccess(false); this.getSettings().setAllowFileAccessFromFileURLs(false); this.getSettings().setAllowUniversalAccessFromFileURLs(false); this.getSettings().setDomStorageEnabled(false); this.getSettings().setAppCacheEnabled(false); this.getSettings().setDatabaseEnabled(false); this.getSettings().setGeolocationEnabled(false); this.getSettings().setSaveFormData(false); this.getSettings().setSupportMultipleWindows(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { this.getSettings().setSafeBrowsingEnabled(false); } } }
Layout:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <com.example.MyWebView android:id="@+id/my_web_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Any ideas what I am doing wrong or what may have changed in API 28 or 29 that could break this?
I went through the same trouble and actually what solved it was changing the context in the constructor to context.getApplicationContext()
.
After that it's building and rendering with no problems on Android 5.
It seems to be a bug with appcompat 1.1.0 - https://issuetracker.google.com/issues/141132133
While you can try downgrading appcompat or wait for a fix, you can also try
Using a custom WebView:
private fun Context.getLollipopFixWebView(): Context { return if (Build.VERSION.SDK_INT in 21..22) { createConfigurationContext(Configuration()) } else this } /** * Workaround appcompat-1.1.0 bug https://issuetracker.google.com/issues/141132133 */ class LollipopFixWebView(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : WebView(context.getLollipopFixWebView(), attrs, defStyle)
Or adding this workaround to the parent Activity of your WebView:
// Workaround appcompat-1.1.0 bug https://issuetracker.google.com/issues/141132133 override fun applyOverrideConfiguration(overrideConfiguration: Configuration) { if (Build.VERSION.SDK_INT in 21..22) { return } super.applyOverrideConfiguration(overrideConfiguration) }
Credits and kudos to https://github.com/ankidroid/Anki-Android/issues/5507 There the guy believes it's happening to Android 7 as well but I couldn't replicate
The custom WebView solution may introduce a new problem: keyboard not showing for all Android versions.
So we'll need to set isFocusable
and isFocusableInTouchMode
to the custom WebView class prevent such problem
class LollipopFixWebView : WebView { constructor(context: Context) : this(context, null) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context.getLollipopFixWebView(), attrs, defStyleAttr) { isFocusable = true isFocusableInTouchMode = true } }
My minSdk
version is 21 (Lollipop) so can't guarantee my solution works for apps with lower minSdk version
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With