Android WebView onPageCommitVisible not fired

主宰稳场 提交于 2020-06-14 06:50:10

问题


I have a WebView, which loads an html page from server, but the page is invisible on the WebView. The html is loaded properly (I've debugged with chrome://inspect and the html, including all javascripts exist), but it is invisible on the phone screen. There was no changes in my code, when this bug appeared. The bug appeared when I installed updates to Android System WebView on my phone. If I uninstall the updates, all works properly again. In addition, I've checked the callbacks of the WebViewClient and noticed that onPageCommitVisible is not called. So somehow, the page is not loaded properly. Only if I press the Back button, to exit the WebView, I see that the onPageCommitVisible is called for my webpage (buat it doesn't help, as the back button exists the WebView, as expected).

Here is my code for the webview:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    RelativeLayout rlMain = new RelativeLayout(getActivity());
    rlMain.setContentDescription(Constants.STARTAPP_AD_MAIN_LAYOUT_CONTENT_DESCRIPTION);
    rlMain.setId(Constants.MAIN_LAYOUT_ID);
    getActivity().setContentView(rlMain);

    // Create WebView and set its parameters
    try{
        webView = new WebView(getActivity().getApplicationContext());
        webView.setBackgroundColor(0xFF000000);
        getActivity().getWindow().getDecorView().findViewById(android.R.id.content).setBackgroundColor(0x00777777);
        webView.setVerticalScrollBarEnabled(false);
        webView.setHorizontalScrollBarEnabled(false);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebChromeClient(new WebChromeClient());
        // set software acceleration
        if (softwareAcceleration) {
            ApiUtil.setWebViewLayerTypeSoftware(webView, null);

        } 

        webView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                return true;
            }
        });
        webView.setLongClickable(false);

        webView.addJavascriptInterface(createJsInterface(), Constants.INTERFACE);

        setWebViewSpecificParameters(webView);  


        webView.loadDataWithBaseURL("http://www.xxxxxx.com", getHtml(), "text/html", "utf-8", null);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }
        webView.setWebViewClient(new MyWebViewClient());

        RelativeLayout.LayoutParams webviewPrms = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT
            );
        rlMain.addView(webView, webviewPrms);
}

public void setWebViewSpecificParameters(final WebView webView) {
        webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return (event.getAction() == MotionEvent.ACTION_MOVE);
            }
        });
}

private class MyWebViewClient extends WebViewClient {


        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            Logger.log(TAG, Log.DEBUG, "!!!!!shouldInterceptRequest" );
            return super.shouldInterceptRequest(view, url);
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            Logger.log(TAG, Log.DEBUG, "!!!!!shouldInterceptRequest" );
            return super.shouldInterceptRequest(view, request);
        }


        @Override
        public void onPageFinished(WebView view, String url) {
            setWebViewBackground(view);
            runJavascript(Constants.JAVASCRIPT_SET_MODE_SERVER, getPosition());
            runJavascript(Constants.JAVASCRIPT_ENABLE_SCHEME, "externalLinks");
            InterstitialMode.this.onWebviewPageFinished();

        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return clicked(url);
        }
    }

回答1:


In an app that navigates from one website to another based on user input, there's a high chance (>50%) that the second website won't display at all after calling WebView.loadUrl and the previous website stays visible - it's even interactive, i.e. scrolling works. The problem is usually resolved after calling WebView.loadUrl again. There's no obvious indication of the bug occurring other than the user not seeing the second website. Relying on the user to reload the page manually is not a satisfying solution since the bug occurs quite often.

I was able to workaround this issue by using a custom WebViewClient to detect that the second website was not loaded properly and triggering a reload:

        setWebViewClient(new WebViewClient() {

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    buggyWebViewHandler.postDelayed(new Runnable() {

                        @Override
                        public void run() {
                            if (!wasCommitCalled) {
                                loadUrl(url);
                            }
                        }
                    }, 2500);
                }
            }

            @Override
            public void onPageCommitVisible(WebView view, String url) {
                wasCommitCalled = true;
            }
        });

Where buggyWebViewHandler is a Handler or any other class that allows deferring a piece of code for some time. Additionally, you'll need to set wasCommitCalled = false; whenever WebView.loadUrl is called - for example by overriding the method.

Note that this only works for Android 23 onwards because that's when onPageCommitVisible was added. See here for a full implementation: https://github.com/TomTasche/OpenDocument.droid/blob/8c2eec5c57e5962e9ac4c46549be2241b259eb32/app/src/main/java/at/tomtasche/reader/ui/widget/PageView.java#L72-L96

If anyone is brave enough to dig deeper into why this is happening: while debugging it seemed that onPageStarted is not called whenever this bug occurs. Maybe that helps...



来源:https://stackoverflow.com/questions/37302532/android-webview-onpagecommitvisible-not-fired

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!