The memory of my application increase with no apparent reason

Viewed 24

I am making an application that needs to run 24 hours a day and that displays local HTML pages using the Android WebView component (call message in the code).

Each WebView corresponds to a web page.

It is important to have two WebViews at the same time (one WebView to display the web page and the second to preload the next page).

After some tests I realized that the application keeps growing and for no apparent reason.

Here is my code:

public class MainActivity extends AppCompatActivity {

    final String PATH                   = "/sdcard/Document/";
    final String FILENAME               = "/displayed.html";
    private final String[] MESSAGE_LIST = { "361613", "353894", "353745", "345204" };

    final String START_MESSAGE  = "startForDSChromium()";
    final String INTERFACE_NAME = "java_event_bus";
    final Handler HANDLER       = new Handler(Looper.getMainLooper());

    private int index           = 0;
    private int preloadIndex    = 0;

    private WebView actualView;
    private WebView preloadView;

    private Context APP_CONTEXT;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        WebView.setWebContentsDebuggingEnabled(true);

        setContentView(R.layout.activity_main);

        APP_CONTEXT = getApplicationContext();

        initFirst();
    }

    /**
     * Create the first message
     */
    private void initFirst() {
        String buildedURL = PATH + MESSAGE_LIST[0] + FILENAME;
        instanciateWebView(buildedURL, false);

        HANDLER.postDelayed(this::preloadMessage, 3000);
    }

    /**
     * Instanciate a new WebView for display a page
     *
     * @param url           local URL of the message to display
     * @param isPreload     define if this message is preloading
     */
    private void instanciateWebView(String url, Boolean isPreload) {
        WebView wv = new WebView(APP_CONTEXT);

        WebSettings settings = wv.getSettings();
        settings.setAllowFileAccess(true);
        settings.setUseWideViewPort(true);
        settings.setJavaScriptEnabled(true);
        settings.setOffscreenPreRaster(true);
        settings.setAllowContentAccess(true);
        settings.setLoadWithOverviewMode(false);
        settings.setAllowFileAccessFromFileURLs(true);
        settings.setAllowUniversalAccessFromFileURLs(true);
        settings.setTextZoom(100);

        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);

        wv.setScrollbarFadingEnabled(true);
        wv.setScrollContainer(false);
        wv.setOverScrollMode(View.OVER_SCROLL_NEVER);
        wv.setVerticalScrollBarEnabled(false);
        wv.setHorizontalScrollBarEnabled(false);

        wv.setInitialScale(100);

        wv.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if(!isPreload) {
                    view.evaluateJavascript(START_MESSAGE, null);
                    view.setVisibility(View.VISIBLE);

                    HANDLER.postDelayed(() -> { nextMessage(); }, 15000);
                }
            }
        });

        wv.addJavascriptInterface(new JSObject(), INTERFACE_NAME);

        RelativeLayout layout = findViewById(R.id.webviewContainer);

        layout.addView(wv);

        RelativeLayout.LayoutParams params = new 
        RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 
        RelativeLayout.LayoutParams.MATCH_PARENT);
        params.addRule(RelativeLayout.ALIGN_TOP);

        wv.setLayoutParams(params);
        wv.setVisibility(View.INVISIBLE);

        wv.loadUrl(url);

        if(isPreload) preloadView = wv;
        else actualView = wv;

        wv = null;
        layout = null;
    }

    /**
     * Change the WebView visibility to display the next message
     */
    public void nextMessage() {
        WebView toDestroy = actualView;

        actualView = preloadView;
        preloadView = null;

        destroyWebview(toDestroy);

        if(actualView == null) return;

        actualView.evaluateJavascript(START_MESSAGE, null);
        actualView.setVisibility(View.VISIBLE);
        index = preloadIndex;

        HANDLER.postDelayed(this::nextMessage, 15000);
        HANDLER.postDelayed(this::preloadMessage, 3000);
    }

    /**
     * Get the right URL for the next message
     */
    public void preloadMessage() {
        preloadIndex = index + 1 < MESSAGE_LIST.length ? index + 1 : 0;

        String preloadURL = PATH + MESSAGE_LIST[preloadIndex] + FILENAME;
        instanciateWebView(preloadURL, true);
        
    }

    /**
     * Destroy WebView when the current message has finish to display
     *
     * @param wv    the WebView to destroy
     */
    public void destroyWebview(final WebView wv) {
        if(wv == null) return;

        RelativeLayout layout = findViewById(R.id.webviewContainer);
        layout.removeView(wv);

        wv.removeAllViews();
        wv.removeJavascriptInterface(INTERFACE_NAME);
        wv.loadUrl("about:blank");
        wv.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        wv.clearView();
        wv.clearHistory();
        wv.clearMatches();
        wv.clearFormData();
        wv.freeMemory();
        wv.removeAllViews();
        wv.getSettings().setJavaScriptEnabled(false);
        wv.removeAllViewsInLayout();
        wv.setWebViewClient(null);
        wv.setWebChromeClient(null);
        wv.destroyDrawingCache();

        wv.destroy();

        System.gc();
        Runtime.getRuntime().gc();
    }

    public static class JsObject extends JSObject {
        @JavascriptInterface
        public void postMessage(String message) {
            Log.e("TAG", "stopSWFAuto");
        }
    }

}

I have already tried to use only 2 WebViews and to alternate them, but the problem still persists.

I also tested to display more "classic" web pages (Google, ...) with the same findings.

Do you have any idea to solve this problem ?

0 Answers
Related