If you use androidx.appcompat:appcompat:1.1.0
, try androidx.appcompat:appcompat:1.0.2
instead.
it seems that 1.1.0
doesn't fix the bug with WebView
in Android 5.1.1
.
Feb-2020 update: Reverting to 1.0.2
stopped working for many people (including my app), but using the current version of androidx.appcompat:appcompat:1.2.0-alpha02
did fix the crash. (I was seeing it on a Huawei P8 Lite running Android 5.0 during Google's automated "Pre-launch report" testing).
Jun-2020 update: There are newer releases available than the one mentioned in the Feb-2020 update, you can see the currently available versions here:
If you are using androidx.appcompat:appcompat:1.1.0
and don't want to downgrade to androidx.appcompat:appcompat:1.0.2
or upgrading to androidx.appcompat:appcompat:1.2.0-alpha03
, there's another solution which is described in this comment on the Google Issue Tracker.
I noticed that after calling applyOverrideConfiguration,
Context.getAssets()
andContext.getResources().getAssets()
are not returning the same AssetManager object. The AssetManager returned fromContext.getAssets()
can't access resources in other packages (including the system WebView package), causing WebView to crash. If I overrideContext.getAssets()
to returngetResources().getAssets()
, the problem is gone.
Based on that comment, you can override the getAssets()
in the WebView's Activity so that it returns getResources().getAssets()
instead to solve the issue.
Java
@Override
public AssetManager getAssets() {
return getResources().getAssets();
}
Kotlin
override fun getAssets(): AssetManager {
return resources.assets
}
Warning: this workaround might also break some things; see the comments for details
If you'd like to inflate the WebView from an XML layout, you can wrap it in a nice little subclass (based on ikostet's answer):
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
}
public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}
EDIT: now even nicer with Kotlin
class LollipopFixedWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : WebView(context.createConfigurationContext(Configuration()), attrs, defStyleAttr, defStyleRes)
my advice is to use custom/new Configuration
only when "original one" is causing problems, so on Lollipop only. @SpaceBizon code work well till Android 8.x, on 9 and Q (currenly beta) every select/dropdown press won't show AlertDialog
picker, instead of that memory leak occurs... below fixed getFixedContext
method with "iffed" proper version code
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
private static Context getFixedContext(Context context) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) // Android Lollipop 5.0 & 5.1
return context.createConfigurationContext(new Configuration());
return context;
}
}
If you are using androidx.appcompat:appcompat:1.1.0, either change to androidx.appcompat:appcompat:1.0.2 or if you want to use DayNight Theme, override applyOverrideConfiguration in your activity as follows. (Note: This requires app restart while switching from Dark Theme to Light Theme and vice versa).
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
if (Build.VERSION.SDK_INT in 21..25 && (resources.configuration.uiMode == applicationContext.resources.configuration.uiMode)) {
return
}
super.applyOverrideConfiguration(overrideConfiguration)
}
If you are not relying on DayNight theme switching (or other UiMode events), you can add android:configChanges="uiMode" to the webview activity manifest to prevent AppCompatDelegate updating the Resources configuration and thereby messing up the webview inflation.
Try use for creating webview:
mWebView = new WebView(getActivity().createConfigurationContext(new Configuration()));
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