阔别Android一年多,最近又接手过来公司里的Android端的项目,按照需求如果手机中没有安装淘宝或者拼多多、京东及其他app应用就在应用内使用webview加载第三方应用页面,但是一直错误重定向或者打不开页面,看了很多篇文章最后筛选组合起来终于解决了,下面是具体问题与解决方法
加载第三方应用页面问题
-
如图所示使用WebView加载京东的页面(https://u.jd.com/g4SHnM),直接显示白屏了
-
当访问拼多多一商品(https://p.pinduoduo.com/cnH9JxxZ)页面的时候会出现下面图片的重定向问题
问题解决
原因一
- 根据控制台输出的日志可以看出是因为webview无法加载HTTPS协议的页面。
"Mixed Content: The page at 'https://u.jd.com/g4SHnM' was loaded over HTTPS, but requested an insecure favicon 'http://www.jd.com/'. This request has been blocked; the content must be served over HTTPS.", source: https://u.jd.com/g4SHnM (0)
HTTPs页面加载不出来的主要原因是SSL证书不能被正确识别,这里要做的,就是重载WebViewClient中的OnReceiveSslError方法:
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
这样,当收到证书错误时,忽略掉,直接继续处理就行了;相当于信任了所有的证书一样。
原因二
大多数页面都需要开启DOM缓存,如果未开启则也会出现空白页的情况
webSettings.setDomStorageEnabled(true);
原因三
- 当访问页面(https://p.pinduoduo.com/cnH9JxxZ)时,被重定向到以pinduoduo://开头的一个链接上,仔细观察图中url可以发现这是一个自定协议的url,究其原因,就是拦截webview中的url, 如果url是自定义协议(如: tel, weixin, alipays 等等)开头的, 就url转换成原生调用(intent跳转), 因为webview只能识别http, https这样的协议. webview其实就相当于pc端的浏览器, 遇到http/https开头的url时会向host发起一个请求, 而遇到自定义的协议时就不知道该如何处理了, 因此就会出现ERR_UNKNOWN_URL_SCHEME这样的错误。
- 解决方法:给WebView设置WebViewClient,并重写WebViewClient中的shouldOverrideUrlLoading方法
@Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if(url == null) return false;
try {
if(url.startsWith("weixin://") //微信
|| url.startsWith("alipays://") //支付宝
|| url.startsWith("mailto://") //邮件
|| url.startsWith("tel://")//电话
|| url.startsWith("dianping://")//大众点评
|| url.startsWith("tbopen://")//淘宝
|| url.startsWith("openapp.jdmobile://")//淘宝
|| url.startsWith("tmast://")//淘宝
|| url.startsWith("pinduoduo://")//拼多多
//其他自定义的scheme
) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
} catch (Exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash)
return true;//没有安装该app时,返回true,表示拦截自定义链接,但不跳转,避免弹出上面的错误页面
}
//处理http和https开头的url
wv.loadUrl(url);
return true;
}
代码
布局文件就包含一个简单的webview控件,过于简单就不再粘贴xml布局文件了
public class H5Activity extends AppCompatActivity {
@BindView(R.id.h5_web_view)
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_h5);
ButterKnife.bind(this);
initData();
}
private void initData() {
WebSettings webSettings = mWebView.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);
// 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//缩放操作
webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
webSettings.setAllowFileAccess(true); //设置可以访问文件
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
webSettings.setDomStorageEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView wv, String url) {
if(url == null) return false;
try {
if(url.startsWith("weixin://") //微信
|| url.startsWith("alipays://") //支付宝
|| url.startsWith("mailto://") //邮件
|| url.startsWith("tel://")//电话
|| url.startsWith("dianping://")//大众点评
|| url.startsWith("tbopen://")//淘宝
|| url.startsWith("openapp.jdmobile://")//淘宝
|| url.startsWith("tmast://")//淘宝
|| url.startsWith("pinduoduo://")//拼多多
//其他自定义的scheme
) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
} catch (Exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash)
return true;//没有安装该app时,返回true,表示拦截自定义链接,但不跳转,避免弹出上面的错误页面
}
//处理http和https开头的url
wv.loadUrl(url);
return true;
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
});
mWebView.loadUrl("https://p.pinduoduo.com/cnH9JxxZ");
}
}
如有问题,欢迎同学们在下方评论留言。
end 参考文章
简书 Doikki WebView出现net::ERR_UNKNOWN_URL_SCHEME错误
github Michael Lee 【Android】WebView加载HTTPS页面以及正确加载淘宝客连接