Android WebView onPageCommitVisible未触发

时间:2016-05-18 14:26:53

标签: android webview android-webview

我有一个WebView,它从服务器加载一个html页面,但该页面在WebView上是不可见的。 html正确加载(我使用chrome调试//检查和html,包括所有javascripts存在),但它在手机屏幕上是不可见的。 当这个bug出现时,我的代码没有变化。当我在手机上安装Android System WebView更新时出现错误。 如果我卸载更新,则一切正常。 另外,我检查了WebViewClient的回调,并注意到没有调用onPageCommitVisible。所以不知何故,页面没有正确加载。只有当我按下Back按钮退出WebView时,我才会看到为我的网页调用onPageCommitVisible(buat它没有帮助,因为后退按钮存在WebView,正如预期的那样)。

以下是我的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 个答案:

答案 0 :(得分:1)

在基于用户输入从一个网站导航到另一个网站的应用中,很有可能(> 50%)第二个网站在调用WebView.loadUrl之后根本不会显示,并且前一个网站仍然可见-它甚至是交互式的,即滚动作品。通常在再次调用WebView.loadUrl之后即可解决该问题。除了用户没有看到第二个网站以外,没有明显的迹象表明发生了该错误。依靠用户手动重新加载页面并不是令人满意的解决方案,因为该错误经常发生。

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

        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是处理程序或任何其他允许将一段代码延迟一段时间的类。此外,每当调用wasCommitCalled = false;时,您都需要设置WebView.loadUrl-例如,通过重写方法。

请注意,这仅适用于Android 23及更高版本,因为这是在添加onPageCommitVisible时开始的。完整的实现请参见此处:https://github.com/TomTasche/OpenDocument.droid/blob/8c2eec5c57e5962e9ac4c46549be2241b259eb32/app/src/main/java/at/tomtasche/reader/ui/widget/PageView.java#L72-L96

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