未触发Android WebView onPageCommitVisible [英] Android WebView onPageCommitVisible not fired

查看:267
本文介绍了未触发Android WebView onPageCommitVisible的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WebView,该WebView从服务器加载html页面,但是该页面在WebView上不可见. html已正确加载(我已经使用chrome://inspect进行了调试,并且html,包括所有存在的javascript都存在),但是在电话屏幕上不可见. 出现此错误时,我的代码没有任何更改.当我在手机上安装了对Android System WebView的更新时,出现了该错误. 如果我卸载更新,则所有更新都将再次正常运行. 此外,我检查了WebViewClient的回调,并注意到未调用onPageCommitVisible.因此,页面无法正确加载.仅当我按下后退"按钮退出WebView时,我才会看到为我的网页调用了onPageCommitVisible(命令无效,因为后退"按钮存在WebView,符合预期).

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

推荐答案

在基于用户输入从一个网站导航到另一个网站的应用中,第二个网站极有可能不会显示在只需调用WebView.loadUrl之后,所有以前的网站都将保持可见状态-甚至是交互式的,即滚动作品.通常在再次调用WebView.loadUrl之后即可解决该问题.除了用户没有看到第二个网站之外,没有明显的迹象表明发生了该错误.依靠用户手动重新加载页面并不是令人满意的解决方案,因为该错误经常发生.

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.

我能够通过使用自定义WebViewClient来检测第二个网站未正确加载并触发重新加载来解决此问题:

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

其中buggyWebViewHandler是Handler或任何其他允许将一段代码延迟一段时间的类.此外,无论何时调用WebView.loadUrl,您都需要设置wasCommitCalled = false;,例如,通过覆盖方法.

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.

请注意,这仅适用于Android 23及更高版本,因为这是添加onPageCommitVisible的时间.参见此处以获取完整的实现:

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

如果有人有足够的勇气更深入地了解发生这种情况的原因:在调试时,似乎只要此错误发生,onPageStarted都不会被调用.也许有帮助...

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

这篇关于未触发Android WebView onPageCommitVisible的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆