Dunisani Matt
Dunisani Matt

Reputation: 51

webview causing my app to crash after a few minutes

I have an Android app with a webview that crashes after about 15 minutes of running. There isn't a stacktrace on logcat, only the following error message appears before the crash :

[ERROR:aw_browser_terminator.cc(81)] Render process (29413) kill (OOM or update) wasn't handed by all associated webviews, killing application.

What could be the cause of this?

NB : The webview loads an Angular 5 web application which contains a few svg charts.

Edit
My code is the following

final WebSettings ws = webView.getSettings();
ws.setJavaScriptEnabled(true);
ws.setDomStorageEnabled(true);
ws.setAllowContentAccess(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
  ws.setAllowFileAccessFromFileURLs(true);
  ws.setAllowUniversalAccessFromFileURLs(true);
}
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient());

webView.loadUrl("http://192.168.137.133/sectiontasks");

Upvotes: 3

Views: 3000

Answers (1)

Murat Gungor
Murat Gungor

Reputation: 125

Very useful for those to handle webview crash and recover from it.

Termination Handling API The Termination Handling API handles cases where the renderer process for a WebView object goes away, either because the system kills the renderer to reclaim necessary memory or because the renderer process crashes. By using this API, you let your app continue executing, even though the renderer process goes away.

https://developer.android.com/develop/ui/views/layout/webapps/managing-webview#termination-handle

    public class MyRendererTrackingWebViewClient extends WebViewClient {
    private WebView mWebView;

    @Override
    public boolean onRenderProcessGone(WebView view,
            RenderProcessGoneDetail detail) {
        if (!detail.didCrash()) {
            // Renderer is killed because the system ran out of memory. The app
            // can recover gracefully by creating a new WebView instance in the
            // foreground.
            Log.e("MY_APP_TAG", "System killed the WebView rendering process " +
                    "to reclaim memory. Recreating...");

            if (mWebView != null) {
                ViewGroup webViewContainer =
                        (ViewGroup) findViewById(R.id.my_web_view_container);
                webViewContainer.removeView(mWebView);
                mWebView.destroy();
                mWebView = null;
            }

            // By this point, the instance variable "mWebView" is guaranteed to
            // be null, so it's safe to reinitialize it.

            return true; // The app continues executing.
        }

        // Renderer crashes because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!");

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you handle the crash more gracefully and let
        // your app continues executing, you must destroy the current WebView
        // instance, specify logic for how the app continues executing, and
        // return "true" instead.
        return false;
    }
}

Destroying webview

     private void destroyWebview() {
        if (webView != null) {
            Utilities.logThis("MainActivity destroyWebview  DESTROY WebView ... ACTION");
            //ViewGroup webViewContainer = (ViewGroup) findViewById(R.id.webview_container);
            webviewContainer.removeView(webView);
            webView.stopLoading();  // Stop any ongoing loading in case of a crash
            webView.onPause();      // Pause JavaScript execution
            webView.clearHistory(); // Clear WebView history
            webView.clearFormData();
            webView.removeAllViews(); // Remove all child views
            webView.clearCache(true);
            webView.destroy();  // Destroy the WebView
            webView = null; // Set the WebView reference to null
            webViewClient = null;
        }
    }

Reconstruction it programmatically

     public void setupWebview() {  

        //webView = (WebView) findViewById(R.id.webview);
        // Create a new WebView instance
        webView = new WebView(this);
        webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        // Add the WebView to the container
        webviewContainer.addView(webView);


        Log.d("setupWebview", "Webview created " + webView);

        //Enabling hardware acceleration for WebView can improve performance but may also lead to crashes. You can disable it if it's causing issues:
        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setLoadsImagesAutomatically(true);
        webView.getSettings().setAllowContentAccess(true);
        webView.getSettings().setLoadWithOverviewMode(true);
        //webView.getSettings().setAppCacheEnabled(true);
        //webView.getSettings().setAppCacheMaxSize(1024 * 1024 * 8); // 8MB
        webView.getSettings().setUseWideViewPort(true);

        webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            webView.getSettings().setSafeBrowsingEnabled(false);
        }

        webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

        //webView.setWebViewClient(new WebViewClient()); //https://stackoverflow.com/questions/48054518/android-app-not-connecting-to-internet-on-emulator

        webView.setRendererPriorityPolicy(WebView.RENDERER_PRIORITY_BOUND, true);
        //webViewClient = new MyRendererTrackingWebViewClient(this, webView);
        webViewClient = new MyWebViewClient();

        webView.setWebViewClient(webViewClient);
       

        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(false);
        cookieManager.setAcceptThirdPartyCookies( webView, false);
    }

Upvotes: 0

Related Questions