【webView重定向】遇到的坑

缘由:

项目开发中用,不是所以界面都需要原生开发,也有一部分会用到H5。下面说的问题就是因为项目webView加载H5造成的。

现象:

1、打开一些网页,正常,而有一些就不正常;
2、因为都是同个项目的网页,预测可能这些网页写法不同导致的
3、也可能是手机webkit内核不同造成的

思路:

1、首先如果是手机浏览器内核问题,那么一定是有些手机能打开所以网页 ,有些手机打不开;但结果是所以的测试机展现效果是一致的;
2、根据 1、的结果,得出可能是能打开的网页 和不能打开的网页有不一样的写法;
3、但是对比这些网页,发现并没有异样;
4、那么还是回到代码去解决;

5、debug完整的client
webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                titleBuilder.setMiddleTitleText(view.getTitle());
//                view.loadUrl("javascript:window.local_obj.showSource('<head>'+"
//                        + "document.getElementsByTagName('html')[0].innerHTML+'</head>');");
            }

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

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                return super.shouldInterceptRequest(view, url);
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                return super.shouldInterceptRequest(view, request);
            }

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

            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
                
            }
        });
 发现 方法 shouldInterceptRequest 被调用,返回为空,那么这个url是有问题的;
6、用浏览器打开,发现重定向了一个新的url这个url 404

结论:

如果遇到请求网址重定向到一个错误的、不存在的url,就会导致shouldOverrideUrlLoading无法回调,webView无法打开url。
发现很多网友说 webView的 shouldOverrideUrlLoading不调用,现在可以再加上这种情况,重定向的URL网址不存在以至于请求中断,无法回调shouldOverrideUrlLoading方法。


辅助:

1、调试过程中 并没有发现是重定向。于是给大家提供一种重定向的确定方法

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewConfiguration;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.netease.nim.uikit.common.activity.TActivity;
import com.umeng.analytics.MobclickAgent;
import com.yzx.youneed.R;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultRedirectHandler;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
 * 通用网页界面
 *
 * @author lif
 */
public class CommWebViewActivity extends TActivity {
    public static final String TAG = CommWebViewActivity.class.getSimpleName();
    // 通用网页活动实例
    private CommWebViewActivity instance;
    protected WebView webView = null;
    // 关于我们主页
	private String url = "http://www.51ttjd.com";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.common_webview);
        findView();
        setView();
    }

    private void findView() {
        webView = (WebView) findViewById(R.id.comm_webview);
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void setView() {
        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
        webView.getSettings().setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
        webView.getSettings().setSupportZoom(true);//是否可以缩放,默认true
        webView.getSettings().setBuiltInZoomControls(true);//是否显示缩放按钮,默认false
        webView.getSettings().setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式
        webView.getSettings().setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题
        webView.getSettings().setAppCacheEnabled(true);//是否使用缓存
        webView.getSettings().setDomStorageEnabled(true);//DOM Storage
// displayWebview.getSettings().setUserAgentString("User-Agent:Android");//设置用户代理,一般不用


//		webView.setVerticalScrollbarOverlay(true);
//		webView.getSettings().setJavaScriptEnabled(true);
//		webView.getSettings().setAllowFileAccess(true);
//		webView.getSettings().setDomStorageEnabled(true);
//		// webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
//		webView.getSettings().setSavePassword(false);// 默认是保存密码,设为false就不会报错.


        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }


            // 这个方法在用户试图点开页面上的某个链接时被调用
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (url != null) { // 如果想继续加载目标页面则调用下面的语句 //
                    /*if (url.contains(".apk")) {
						Uri uri = Uri.parse(url);
						Intent it = new Intent(Intent.ACTION_VIEW, uri);
						startActivity(it);
					} else {
						view.loadUrl(url); //
					}*/
                    view.loadUrl(url); //
                }
                // 如果不想那url就是目标网址,如果想获取目标网页的内容那你可以用HTTP的API把网页扒下来。
                // 返回true表示停留在本WebView(不跳转到系统的浏览器)
//                return super.shouldOverrideUrlLoading(view, url);
                return true;
            }
        });
//        webView.loadUrl(url);
        new MyTask().execute(url);
    }

    private void webViewDestroy() {
        if (webView != null) {
            webView.getSettings().setBuiltInZoomControls(true);
            webView.setVisibility(View.VISIBLE);
            long timeout = ViewConfiguration.getZoomControlsTimeout();
            // new Timer().schedule(new TimerTask() {
            //
            // @Override
            // public void run() {
            // webView.destroy();
            // }
            // }, timeout);
            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    // webView.clearHistory();
                    // webView.clearCache(true);
                    // webView.loadUrl("about:blank");
                    // webView.freeMemory(); //new code
                    // webView.pauseTimers(); //new code
                    // webView.clearView();
                    webView.destroy();
                    webView = null;
                }
            }, timeout);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        webViewDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        MobclickAgent.onResume(instance);
    }

    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPause(instance);
    }

    private String redirectUrl = null;
    public int getPost(String string) {
        // TODO Auto-generated method stub
        int code = 0;
        HttpGet getMethod = new HttpGet(string);
        DefaultHttpClient loginClient = new DefaultHttpClient();
        MyRedirectHandler redirectHandler = new MyRedirectHandler();
        loginClient.setRedirectHandler(redirectHandler);
        try {
            HttpResponse response = loginClient.execute(getMethod);
            code = response.getStatusLine().getStatusCode();

            for(Header header:response.getAllHeaders()){
                if("Location".equals(header.getName())){
                    redirectUrl= header.getValue();
                    break;
                }
            }


            Log.i(TAG, "resCode = " + response.getStatusLine().getStatusCode()); //获取响应码
            Log.i(TAG, "result = " + EntityUtils.toString(response.getEntity(), "utf-8"));//获取服务器响应内容
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return code;
    }


    public class MyTask extends AsyncTask<String, String, Integer> {

        @Override
        protected Integer doInBackground(String... params) {
            // TODO Auto-generated method stub
            String url = params[0];
            return getPost(url);
        }

        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            if(result==302&&redirectUrl!=null){//302为临时移动
                webView.loadUrl(redirectUrl);
            }
        }

    }

    public class MyRedirectHandler extends DefaultRedirectHandler {

        @Override
        public boolean isRedirectRequested(HttpResponse response,
                                           HttpContext context) {
            // TODO Auto-generated method stub
            return false;
        }

    }
}
 错误code:
3xx(已重定向)  要完成请求,您需要进一步进行操作。通常,这些状态代码是永远重定向的。Google 建议您在每次请求时使用的重定向要少于 5 个。您可以使用网站管理员工具来查看 Googlebot 在抓取您已重定向的网页时是否会遇到问题。诊断下的抓取错误页中列出了 Googlebot 由于重定向错误而无法抓取的网址。
代码	说明
300(多种选择)	服务器根据请求可执行多种操作。服务器可根据请求者 (User agent) 来选择一项操作,或提供操作列表供请求者选择。
301(永久移动)	请求的网页已被永久移动到新位置。服务器返回此响应(作为对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。您应使用此代码通知 Googlebot 某个网页或网站已被永久移动到新位置。
302(临时移动)	服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置。但由于 Googlebot 会继续抓取原有位置并将其编入索引,因此您不应使用此代码来通知 Googlebot 某个页面或网站已被移动。
303(查看其他位置)	当请求者应对不同的位置进行单独的 GET 请求以检索响应时,服务器会返回此代码。对于除 HEAD 请求之外的所有请求,服务器会自动转到其他位置。
304(未修改)	
自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
如果网页自请求者上次请求后再也没有更改过,您应当将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。由于服务器可以告诉 Googlebot 自从上次抓取后网页没有更改过,因此可节省带宽和开销
。
305(使用代理)	请求者只能使用代理访问请求的网页。如果服务器返回此响应,那么,服务器还会指明请求者应当使用的代理。
307(临时重定向)	服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置。但由于 Googlebot 会继续抓取原有位置并将其编入索引,因此您不应使用此代码来通知 Googlebot 某个页面或网站已被移动。

希望对大家有所帮助


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值