Android之WebView 超时操作

WebView作为承载网页的控件,在网页显示的过程中会产生一些事件,并回调给我们的应用程序,以便我们在网页加载过程中做应用程序想处理的事情。比如说客户端需要显示网页加载的进度、网页加载发生错误等等事件。

由于现在项目中部分页面图片之类的资源很多,导致数据传输量很大,一定概率会出现空白页面,也就是资源加载超时导致的。

为了解决这个问题,目前解决的思路是:通过计时器来控制同一个资源是否超时加载,如果超过时限,可以控制重新再加载或者提示错误之类的显示。

代码如下:

1.webView  配置设置
         webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webView.getSettings().setLoadsImagesAutomatically(true);
        webView.getSettings().setAllowFileAccess(true);资源加载超时操作
        webView.getSettings().setAllowFileAccessFromFileURLs(true);
        webView.getSettings().setTextSize(WebSettings.TextSize.NORMAL);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setDatabaseEnabled(true); 
        webView.getSettings().setAppCacheEnabled(true);
        webView.getSettings().setGeolocationEnabled(true);
        webView.getSettings().setBlockNetworkImage(true);
        webView.getSettings().setAppCacheMaxSize(5 * 1048576);
        webView.clearCache(true);

        webView.setWebChromeClient(new WebChromeClient() {

2.webView  配置缓存容量  (非必须设置项)
    // 通知应用程序webview内核web sql 数据库超出配额,请求是否扩大数据库磁盘配额。默认行为是不会增加数据库配额。    
           @Override
            public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota,
                    long estimatedSize, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
                quotaUpdater.updateQuota(estimatedSize * 2);
            }
//扩充缓存的容量 
            @Override
            public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota, QuotaUpdater quotaUpdater) {
                quotaUpdater.updateQuota(spaceNeeded * 2);
            }
        });

3.webView  网页中超链接按钮的响应
   //对网页中超链接按钮的响应。当按下某个连接时WebViewClient会调用这个方法,并传递参数:按下的url。
        // 设置Web视图 
        webView.setWebViewClient(new WebViewClient(){
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (url.startsWith(WebView.SCHEME_TEL)) {     //
                    try {
                        Intent intent = new Intent(Intent.ACTION_DIAL);
                        intent.setData(Uri.parse(url));
                        startActivity(intent);
                    } catch (android.content.ActivityNotFoundException e) {
                        DLog.e("markdayinfo", "Error dialing " + url + ": " + e.toString());
                    }
                }// If sending email (mailto: [email protected])
                else if (url.startsWith(WebView.SCHEME_MAILTO)) {
                    try {
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        intent.setData(Uri.parse(url));
                        startActivity(intent);
                    } catch (android.content.ActivityNotFoundException e) {
                        DLog.e("markdayinfo", "Error sending email " + url + ": " + e.toString());
                    }
                }

                // If sms:5551212?body=This is the message
                else if (url.startsWith("sms:")) {
                    try {
                        Intent intent = new Intent(Intent.ACTION_VIEW);

                        // Get address
                        String address = null;
                        int parmIndex = url.indexOf('?');
                        if (parmIndex == -1) {
                            address = url.substring(4);
                        }
                        else {
                            address = url.substring(4, parmIndex);

                            // If body, then set sms body
                            Uri uri = Uri.parse(url);
                            String query = uri.getQuery();
                            if (query != null) {
                                if (query.startsWith("body=")) {
                                    intent.putExtra("sms_body", query.substring(5));
                                }
                            }
                        }
                        intent.setData(Uri.parse("sms:" + address));
                        intent.putExtra("address", address);
                        intent.setType("vnd.android-dir/mms-sms");
                        startActivity(intent);
                    } catch (android.content.ActivityNotFoundException e) {
                        DLog.e("markdayinfo", "Error sending sms " + url + ":" + e.toString());
                    }
                }

                // All else
                else {
                    if ((url.startsWith("file://") || url.startsWith("http://") || url.startsWith("https://")) && !url.endsWith(".apk")) {
                        //This will fix iFrames
                        view.loadUrl(url);
                    }

                    // If not our application, let default viewer handle
                    else {
                        try {
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setData(Uri.parse(url));
                            startActivity(intent);
                        } catch (android.content.ActivityNotFoundException e) {
                            DLog.e("markdayinfo", "Error loading url " + url + ":" + e.toString());
                        }
                    }
                }

                return true;             
//1、 默认返回:return super.shouldOverrideUrlLoading(view, url); 这个返回的方法会调用父类方法,也就是跳转至手机浏览器,平时写 webview一般都在方法里面写                    webView.loadUrl(url); 然后把这    个返回值改成下面的false。 
2、返回: return true; webview处理url是根据程序来执行的。 
3、返回: return false; webview处理url是在webview内部执行。


            }

4.webView  页面加载   超时操作
            private String startUrl;
            private Timer timer;
            private boolean isReload;
 
            //在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次(JS CSS 图片加载都需要调用)
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                DLog.e("markdayinfo", "onPageStarted url:" + url);
                startUrl = url;
                isReload = false;
                super.onPageStarted(view, url, favicon);
            }

            //加载每个资源 都需要调用。比较start的url和load的url  是否一样 来确定该资源加载时间 ,从而确定是否超时  以及后续操作
            @Override
            public void onLoadResource(WebView view, String url) {
                DLog.e("markdayinfo", "onLoadResource url:" + url);
                if (startUrl != null && !startUrl.equals(url)) {
                    stopTimer();
                }
                if (startUrl != null && startUrl.equals(url)) {
                    startTimer();
                }
                super.onLoadResource(view, url);
            }

            public void onPageFinished(WebView view, String url) {
                DLog.e("markdayinfo", "onPageFinished");
                stopTimer();
                if (isReceivedError) {
                    return;
                }
                webView.getSettings().setBlockNetworkImage(false);
                if (!isReload) {
                    if (webView.getVisibility() == View.GONE) {
                        webView.setVisibility(View.VISIBLE);
                    }
                    progressBar.setVisibility(View.GONE);
                }

                super.onPageFinished(view, url);
            }

            @Override
            public void onReceivedError(WebView view, int errorCode,
                    String description, String failingUrl) {
                DLog.e("markdayinfo", "onReceivedError");
                stopTimer();
                isReceivedError = true;
                showError();

                super.onReceivedError(view, errorCode, description, failingUrl);
            }

         //计时器   计时 加载每个资源 的时间  (超时操作)
       private void startTimer() {
                DLog.e("markdayinfo", "startTimer");
                TimerTask timerTask = new TimerTask() {
                    @Override
                    public void run() {
                        DLog.i("markdayinfo", "timerTask reload");
                        stopTimer();
                        isReload = true;
                        mHandler.sendEmptyMessage(2);
                    }
                };
                if (timer != null) {
                    timer.cancel();
                }
                timer = new Timer();
                timer.schedule(timerTask, 1500);
            }

       private void stopTimer() {
                DLog.e("markdayinfo", "stopTimer");
                startUrl = null;
                if (timer != null) {
                    timer.cancel();
                    timer.purge();
                    timer = null;
                }
            }

        });
        webView.addJavascriptInterface(this, "control");

        progressBar.setVisibility(View.VISIBLE);
//        mHandler.sendEmptyMessage(1);

    }
PS:目前处理方法是这个,如果大家有什么更好的方法可以分享一下。谢谢!

你可能感兴趣的:(安卓)