46

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?

ericn
  • 12,476
  • 16
  • 84
  • 127
JPM
  • 1,482
  • 5
  • 18
  • 25
  • 5
    Possible duplicate of [android.view.InflateException Error inflating class android.webkit.WebView](https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview) – Dmitry Brant Sep 24 '19 at 14:45
  • same happening with me but it's a duplicate question. – Shubham AgaRwal Sep 25 '19 at 04:41
  • 3
    Wow, I am having the exact same crash with the emulator running Android 5.0.2, but a physical device running Android 5.1 runs without any issue. As the answer @DmitryBrant posted above, the issue is not with API 28 or 29 but with `androidx.appcompat:appcompat:1.1.0`, if you downgrade to `1.0.2` or `1.1.0-beta01` that crash should disappear. – Seven Sep 26 '19 at 16:20
  • 1
    @Seven Are you sure it is working fine on physical device ! Because I don't have physical device of API level 21 to test! – Sumit Shukla Oct 01 '19 at 13:41
  • @SumitShukla yeah, I am sure. It worked fine in my physical device running Android 5.1 (Moto G 1st Gen). – Seven Oct 01 '19 at 17:18
  • This has been fixed as of 1.2.0-alpha02 – hoshiKuzu Feb 15 '20 at 10:40

4 Answers4

24

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.

  • 1
    Beautiful. This fixed it for me `LayoutInflater.from(activity.applicationContext).inflate(layoutResId, null)` instead of using `activity` – arberg Jun 16 '20 at 11:51
  • 1
    it works for me but what is the difference between context and getapplicationContext? why it does not work for lollipop? – Gustavo Forero Carvajal Jul 22 '20 at 19:04
18

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

Updates

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

Disclaimers

My minSdk version is 21 (Lollipop) so can't guarantee my solution works for apps with lower minSdk version

Jemshit
  • 9,501
  • 5
  • 69
  • 106
ericn
  • 12,476
  • 16
  • 84
  • 127
  • 1
    overriding applyOverrideConfiguration worked for me! – Murat Jan 29 '20 at 10:38
  • Thank you. The solutions are working well. Just wondering if there is any potential risk to override the _applyOverrideConfiguration_ function. – Freddie Feb 19 '20 at 00:19
  • 1
    Be careful not to use the WebView context when retrieving any attributes from the theme, because the newly-created context will not have them. – Sver Mar 14 '20 at 20:06
  • @ericn upgrading to implementation 'androidx.appcompat:appcompat:1.2.0-beta01 solved the issue, would be any side effects of it on the above versions(6.0 and above) – Girish Apr 07 '20 at 14:20
  • I've done all the testing I could and found no problem so far. I don't think there's a way to know 100% for sure @Girish – ericn Apr 24 '20 at 01:12
  • 1
    Thanks for not using Lollipop version of constructor with `defStyleRes: Int`. In this case it is called even in API 19 and crashes. So, you just didn't add it and it doesn't crash. – CoolMind Jan 28 '21 at 09:23
12

Fixed in androidx.appcompat:appcompat:1.2.0-alpha02 Just update your app build.gradle file with line:

implementation "androidx.appcompat:appcompat:1.2.0-alpha02"
Andris
  • 3,895
  • 2
  • 24
  • 27
  • Updating to 1.2.0-alpha02 fixed this issue but introduced different ones. Ended up doing a workaround @ericn mentioned below – user3783123 Mar 03 '20 at 08:41
  • 1
    @user3783123, could you say, what bugs have appeared? Was the advice of Gunnar Bernstein helpful? – CoolMind Mar 04 '20 at 10:47
  • @user3783123 upgrading to implementation 'androidx.appcompat:appcompat:1.2.0-beta01 solved the issue, is there any side effects of it on the above versions(6.0 and above) – Girish Apr 07 '20 at 14:17
  • @Girish it somehow broke the app's change language (locale) functionality on android 6.0 and below. Didn't have time to research how and why it happened though – user3783123 Apr 09 '20 at 06:46
  • @user3783123 is that the only thing that broke or any other? – Girish Apr 09 '20 at 08:49
  • @Girish it was the only thing that stopped working in our case – user3783123 Apr 14 '20 at 13:03
8

It seems to be a bug with appcompat 1.1.0 - https://issuetracker.google.com/issues/141132133

Looking at #30 in that discussion, this solved my problem:

// add to gradle module:app
configurations.all {
    resolutionStrategy {
        force 'androidx.appcompat:appcompat:1.1.0-rc01'
    }
}
Gunnar Bernstein
  • 6,074
  • 2
  • 45
  • 67