【问题标题】:Android WebView onPageCommitVisible not firedAndroid WebView onPageCommitVisible 未触发
【发布时间】:2016-05-18 14:26:53
【问题描述】:

我有一个 WebView,它从服务器加载一个 html 页面,但该页面在 WebView 上是不可见的。 html 已正确加载(我已使用 chrome://inspect 和 html 进行了调试,包括所有 javascripts 都存在),但它在手机屏幕上不可见。 当这个错误出现时,我的代码没有任何变化。当我在手机上安装 Android System WebView 更新时出现了该错误。 如果我卸载更新,一切都会再次正常运行。 另外,我检查了 WebViewClient 的回调,并注意到 onPageCommitVisible 没有被调用。所以不知何故,页面没有正确加载。只有当我按下返回按钮退出 WebView 时,我才会看到我的网页调用了 onPageCommitVisible(但它没有帮助,因为返回按钮存在 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);
        }
    }

【问题讨论】:

  • Android System Web View 发布的最新版本解决了该问题。所以这是 Web 视图中的错误
  • 您好,您找到解决方案了吗?

标签: android webview android-webview


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

请注意,这仅适用于 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。也许这有帮助...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2021-09-27
    • 2016-03-17
    相关资源
    最近更新 更多