Reputation: 3614
In Lollipop (API 22) every time in my application I show a webview the application crashes. I have multiple crashes in my android developer console related to this event.
No need to say that it works on Android 4, 6 and 7.
Reading the stack trace (posted at the end of this post), something bugs me
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040003
I searched in the generated R.java without any luck, obviously because the ID does not exists, but it was worth a try.
Googling around the problem seems to be related to how lollipop handles the webview. I started a fresh AVD with lollipop based on a device I found on the crash reporter in GDC, and I can reproduce the problem.
Full stack trace:
android.view.InflateException: Binary XML file line #7: Error inflating class android.webkit.WebView
at android.view.LayoutInflater.createView(LayoutInflater.java:633)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2040003
at android.content.res.Resources.getText(Resources.java:299)
at android.content.res.Resources.getString(Resources.java:385)
at com.android.org.chromium.content.browser.ContentViewCore.setContainerView(ContentViewCore.java:684)
at com.android.org.chromium.content.browser.ContentViewCore.initialize(ContentViewCore.java:608)
at com.android.org.chromium.android_webview.AwContents.createAndInitializeContentViewCore(AwContents.java:631)
at com.android.org.chromium.android_webview.AwContents.setNewAwContents(AwContents.java:780)
at com.android.org.chromium.android_webview.AwContents.<init>(AwContents.java:619)
at com.android.org.chromium.android_webview.AwContents.<init>(AwContents.java:556)
at com.android.webview.chromium.WebViewChromium.initForReal(WebViewChromium.java:311)
at com.android.webview.chromium.WebViewChromium.access$100(WebViewChromium.java:96)
at com.android.webview.chromium.WebViewChromium$1.run(WebViewChromium.java:263)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.drainQueue(WebViewChromium.java:123)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue$1.run(WebViewChromium.java:110)
at com.android.org.chromium.base.ThreadUtils.runOnUiThread(ThreadUtils.java:144)
at com.android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.addTask(WebViewChromium.java:107)
at com.android.webview.chromium.WebViewChromium.init(WebViewChromium.java:260)
at android.webkit.WebView.<init>(WebView.java:554)
at android.webkit.WebView.<init>(WebView.java:489)
at android.webkit.WebView.<init>(WebView.java:472)
at android.webkit.WebView.<init>(WebView.java:459)
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:607)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.java:67)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Upvotes: 152
Views: 54045
Reputation: 510
Solution for November 2022
This issue is solve with do change on
implementation 'androidx.appcompact:appcompact:1.2.0-alpha02'
Special Note
Make sure you are not using getUserId()
in your entire project. Change or replace this function.
Please do uninstall app and then check it. It's work for me.
Upvotes: 1
Reputation: 4156
I used the latest version from this source. Please check and use your own based on what you think is best.
In case you want to skip, below implementation solves the issue:
implementation 'androidx.appcompat:appcompat:1.2.0'
Upvotes: 5
Reputation: 1995
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:
Upvotes: 193
Reputation: 603
Instead of changing version of any dependency, I implemented programmatically generation of webView as a solution.
The problem actually looks like starting with reading layout from xml file. So if programmatic way is applicable solution for you please check bellow sample.
private WebView generateWebView(){
WebView wv = new WebView(YourContext);
wv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
wv.setFitsSystemWindows(false); // your preferences
wv.setVerticalScrollBarEnabled(false); // your preferences
wv.setPadding(15,15,15,15); // your preferences
return wv;
}
Than just add into your parent view:
LinearLayout scrollContainer = findViewById(R.id.scrollContainer);
scrollContainer.addView(generateWebView());
Upvotes: 1
Reputation: 61
The below code will fix the problem. Please add it in your Activity
:
@Override
public AssetManager getAssets() {
return getResources().getAssets();
}
Upvotes: 6
Reputation: 531
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
}
Upvotes: 53
Reputation: 274
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)
}
Upvotes: 22
Reputation: 28793
In my case a problem was in method
fun getUserId(): Int = userId
of a MainActivity. I don't know why it affects WebView
. getUserId()
is neither overriden, nor public method of the Activity
class. If I rename or remove this method, WebView
starts to open. Also trying to change
private var userId: Int = 0
to
var userId: Int = 0
private set
leads to the same exception. I understood that when had seen an exception: Caused by: java.lang.SecurityException: Permission Denial: null asks to run as user 123456 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
. In that case user=123456 was in fact my authorized user, that was used in some requests, not in WebView
. I suspect Android uses userId
as a local user_id for its processes.
As many other people noticed we could use appcompat:1.1.0
or 1.0.2
and extend WebView
class. In emulator 21 without Google Play Services this WebView
will crash on long touch over text labels, but on typical devices everything is allright.
Upvotes: 1
Reputation: 5
Check version. Androidx appcompat and Google material version keep same always.
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation "androidx.cardview:cardview:1.0.0"
Upvotes: -4
Reputation: 166
I was able to reproduce this issue on a Nexus 7 API 22. The issue is fixed by updating the tablet's version of Android System WebView from version 39 (2237560-arm) to version 79.0.3945.136
This isn't in my control for a user to do this, but it is a solution if you need to help someone use your app immediately.
Upvotes: 2
Reputation: 31
AppCompat 1.2.0-alpha02 was released today, so you can use
implementation 'androidx.appcompat:appcompat:1.2.0-alpha02'
which will fix WebView issues on Lollipop.
Upvotes: 2
Reputation: 71
Just as a side note, I struggled for a while even though I downgraded to 1.0.2, just because I seemed to have a transitive dependency to appcompat:1.1.0 via androidx.constraintlayout:constraintlayout:2.0.0-beta3. Once I downgraded that to constraintlayout:1.1.3 everything worked fine
(According to https://issuetracker.google.com/issues/141351441 issue will be fixed soon with appcompat:1.2.0-alpha02)
Upvotes: 3
Reputation: 2309
And one more try to fix the problem. Should override this method in your activity:
@Override
public void applyOverrideConfiguration(final Configuration overrideConfiguration) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 25) {
overrideConfiguration.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
}
super.applyOverrideConfiguration(overrideConfiguration);
}
Upvotes: 11
Reputation: 91
The issue was solve for my by downgrading to implementation 'androidx.appcompat:appcompat:1.0.2'
Upvotes: 1
Reputation: 2650
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.
Upvotes: 21
Reputation: 3151
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)
Upvotes: 45
Reputation: 15042
I was able to reproduce the crash on API 21 in the emulator.
So I tried to add this to the implementation, as described in the docs:
dependencies {
def appcompat_version = "1.1.0"
implementation "androidx.appcompat:appcompat:$appcompat_version"
// For loading and tinting drawables on older versions of the platform
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
}
Adding appcompat-resources
did not fix the issue.
Maybe a future version will, but I wanted to mention that there seems to be a complementary resource library that is supposed to address this issue. So when trying to fix this with a new version of appcompat
, add the appcompat-resources
library with the same version.
Reverting to androidx.appcompat:appcompat:1.0.2
did fix the issue as a workaround.
Upvotes: 6
Reputation: 899
/**
* Customized WebView to avoid crashing on Android 5 and 6 (API level 21 to 23)
* If the Android System WebView is old and is not updated, the WebView view inflation fails.
* To reproduce the issue, try on OS 5 or 6 with Android System WebView 72.0.3626.76 (this version is just a reference point from being which we saw no crashes)
*/
class BrilliantWebView : WebView {
companion object {
private fun getBrilliantContext(context: Context?) =
if (!OSUtils.hasNougat()) // OS < 24 or OS < 7.0
context?.createConfigurationContext(Configuration())
else
context
}
constructor(context: Context?) : super(getBrilliantContext(context))
constructor(context: Context?, attrs: AttributeSet?) : super(getBrilliantContext(context), attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(getBrilliantContext(context), attrs, defStyleAttr)
}
Upvotes: 2
Reputation: 2650
戴文锦 was right for me too. But downgrading just androidx.appcompat:appcompat:1.1.0 to 1.0.2 did not succeed.
I downgraded all my previously upgraded androidx versions from
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta04'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.core:core:1.2.0-alpha04'
back to
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta03'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta03'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0-rc01'
implementation 'androidx.preference:preference:1.1.0-rc01'
implementation 'androidx.core:core:1.2.0-alpha03'
A reminder that Googles code is by far not bug free and well tested and that someone should never upgrade the versions flippantly.
Upvotes: 2
Reputation: 19243
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;
}
}
Upvotes: 37
Reputation: 171
Try use for creating webview:
mWebView = new WebView(getActivity().createConfigurationContext(new Configuration()));
Upvotes: 17