Error inflating class android.webkit.WebView happens sporadically in production

前端 未结 5 648
自闭症患者
自闭症患者 2020-12-03 01:00

my application is on Google Play and it runs fine on most of devices (thousands of users). But in rare cases (fraction of percent of daily active users) I get Error in

相关标签:
5条回答
  • 2020-12-03 01:14

    If you see these reports from devices running Android Lollipop, please ignore them. This likely happens whenever something launches an activity that uses WebView while the WebView package is in the middle of being updated by Play Store (which can only happen on Lollipop currently). During updates, packages are treated as not installed by the package manager. That is, there is nothing wrong with your app. The time window while the updated package is considered non-existent is typically small, so when the app is relaunched after such a crash, it will start normally.

    0 讨论(0)
  • 2020-12-03 01:20

    I've got this problem in 2020 too and, now, there's a solution:

    Just add this new dependencies:

    implementation 'androidx.appcompat:appcompat:1.2.0-beta01'
    implementation 'androidx.appcompat:appcompat-resources:1.2.0-beta01'
    

    The documentation says:

    Fixed an issue where androidx.appcompat:appcompat:1.1.0 crashes webview when webview is long pressed (b/141351441)

    0 讨论(0)
  • 2020-12-03 01:28

    In the onCreate of the activity that inflates Webview in the UI, you can have a try-catch to save yourself from the errors producing in the Crashlytics.

      /**
         * This element touches the UI elements
         * of the application and set them up.
         */
       try {
            setContentView(R.layout.activity_main);
            // ... further setup
        } catch (Exception ex) {
            transferToNoPackageFoundActivity(ex.getMessage());
        }
    
    
        private void transferToNoPackageFoundActivity(String errorMessage) {
            Intent intent = new Intent(this, NoPackageFoundActivity.class);
            intent.putExtra(Intent.EXTRA_INTENT, errorMessage);
            startActivity(intent);
            finish();
        }
    

    In the NoPackageFoundActivity, you can take the user to the Playstore for downloading the webview package.

        /**
     * This field is used for presenting the user
     * with an error image for no connectivity.
     */
    private lateinit var mErrorImage: ImageView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_no_network)
        // get the intent for the error message, if any.
        val intent: Intent = intent
        if (intent.hasExtra(Intent.EXTRA_INTENT)) {
            println(intent.getStringExtra(Intent.EXTRA_INTENT))
        }
    
        mErrorImage = findViewById(R.id.error_image)
        mErrorImage.contentDescription = resources.getString(R.string.no_network_image_desc)
        Glide.with(this)
                .load(R.drawable.ic_no_web_view_illustration)
                .into(mErrorImage)
    
        val enableButton = findViewById<Button>(R.id.error_handler_btn)
        enableButton.setOnClickListener { openGooglePlayStore() }
        enableButton.text = resources.getString(R.string.no_package_btn_text)
    
        val reloadText = findViewById<TextView>(R.id.no_network_reload)
        reloadText.setOnClickListener { reloadApplication() }
    
        val errorHeadingText = findViewById<TextView>(R.id.error_heading)
        val errorSubheadingText = findViewById<TextView>(R.id.error_subheading)
        errorHeadingText.text = resources.getString(R.string.no_package_heading_text)
        errorSubheadingText.text = resources.getString(R.string.no_package_subheading_text)
    }
    
    /**
     * This is a onClickListener Handler that
     * reloads the application when the user
     * clicks on it.
     * It starts the activity again from
     */
    private fun reloadApplication() {
        val intent = Intent(this, SplashScreen::class.java)
        startActivity(intent)
        finish()
    }
    
    private fun openGooglePlayStore() {
        // you can also use BuildConfig.APPLICATION_ID
        val appId = "com.google.android.webview"
        val rateIntent = Intent(Intent.ACTION_VIEW,
                Uri.parse("market://details?id=$appId"))
        var marketFound = false
        // find all applications able to handle our rateIntent
        val otherApps = packageManager
                .queryIntentActivities(rateIntent, 0)
        for (otherApp in otherApps) { // look for Google Play application
            if (otherApp.activityInfo.applicationInfo.packageName
                    == "com.android.vending") {
                val otherAppActivity = otherApp.activityInfo
                val componentName = ComponentName(
                        otherAppActivity.applicationInfo.packageName,
                        otherAppActivity.name
                )
                // make sure it does NOT open in the stack of your activity
                rateIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                // task reparenting if needed
                rateIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                // if the Google Play was already open in a search result
                //  this make sure it still go to the app page you requested
                rateIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                // this make sure only the Google Play app is allowed to
                // intercept the intent
                rateIntent.component = componentName
                startActivity(rateIntent)
                marketFound = true
                break
            }
        }
        // if GP not present on device, open web browser
        if (!marketFound) {
            val webIntent = Intent(Intent.ACTION_VIEW,
                    Uri.parse("https://play.google.com/store/apps/details?id=$appId"))
            startActivity(webIntent)
        }
    }
    
    0 讨论(0)
  • 2020-12-03 01:36

    If you are not relying on new Material 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.

    0 讨论(0)
  • 2020-12-03 01:37

    To fix this problem that appears on Android Lollipop you can use a custom WebView that creates a new configuration only on Android Lollipop (API 21 and 22). Replace the WebView on your XML layout with this custom WebView.

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.res.Configuration;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.webkit.WebView;
    
    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);
        }
    
        // To fix Android Lollipop WebView problem create a new configuration on that Android version only
        private static Context getFixedContext(Context context) {
            if (Build.VERSION.SDK_INT == 21 || Build.VERSION.SDK_INT == 22) // Android Lollipop 5.0 & 5.1
                return context.createConfigurationContext(new Configuration());
            return context;
        }
    }
    
    0 讨论(0)
提交回复
热议问题