用途
加载网页
- 说明:默认会打开自带的浏览器,使用WebView去加载,则需复写shouldOverrideUrlLoading方法,并返回为true
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
//返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器
return true;
}
});
- return值的说明:
- true: 在打开新的url时WebView就不会再加载这个url了,所有处理都需要在WebView中操作,包含加载
- false(默认): 系统就认为上层没有做处理,接下来还是会继续加载这个url的
- 如果我们拦截了某个url,那么return false 和 return true区别不大,所以一般建议 return false
302问题
- 通过判断HitTestResult类型, 并return false;
WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
HitTestResult hit = webView.getHitTestResult();
int hitType = hit.getType();
if (hitType == HitTestResult.SRC_ANCHOR_TYPE) {//点击超链接
//这里执行自定义的操作
return true;//返回true浏览器不再执行默认的操作
}else if(hitType == 0){//重定向时hitType为0
return false;//不捕获302重定向
}else{
return false;
}
}
});
加载本地的html布局
- 步骤:
- 将静态的html放在assets目录(与res目录同级)下
- 调用
mWebView.loadUrl("file:///android_asset/neterror.html");
获取点击跳转的url地址
- 自定义WebViewClient,复写shouldOverrideUrlLoading方法,返回为true,用于截获url地址,可以开启新的Activity页面
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
获取标题
- 自定义WebChromeClient,复写onReceivedTitle
清除之前的view的状态, 释放页面的资源(包括JS),
webView.loadUrl("about:blank");
播放视频
- 5.0以下,setWebChromeClient中需添加onShowCustomView
- 开启硬件加速
android:hardwareAccelerated="true"
- 支持插件
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.getSettings().setUseWideViewPort(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
与JS的交互
Android调用JS
调用JS中的方法
- 调用形式:
mWebView.loadUrl("javascript:callJavaScriptMethod()");
- 说明:callJavaScriptMethod()为JS中的方法
调用JS中的alert,confirm和prompt
- 调用方式: 调用setWebChromeClient方法,复写
onJsAlert
,onJsConfirm
和onJsPrompt
方法
JS调用Android
- 调用形式:
<a onClick="window.obj.invokeAndroid()">
- 说明:
obj
为android中指定的调用名称;- 添加
mWebView.addJavascriptInterface(new MyJavaScriptInterface(), "obj");
- MyJavaScriptInterface为一个类,该类中有invokeAndroid()的方法,且该方法必须为public
双向交互
- 思路:
- 方式:
- JS 先调用Android,Android再调用JS中的方法 :
- 在Android的MyJavaScriptInterface类中调用
mWebView.loadUrl("javascript:wave()");
- Android先调用JS,JS再反过来调用Android中MyJavaScriptInterface类的方法
- 目的:通过JS向Android的方法中传递参数,将该参数保存带全局变量
mWebView.loadUrl("javascript:window.obj.get");
使用小技巧
使用物理按键回退上一个网页(如果存在)
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK {
if(webView.canGoBack()){
webView.goBack();//返回上一页面
return true;
} else{
System.exit(0);//退出程序
}
}
return super.onKeyDown(keyCode, event);
}
访问https网站
- 如果出现某些https的网站无法访问,首先需要添加支持JS
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
- 在2.2及以上系统中处理只需要重载WebViewClient 的 onReceivedSslError即可。
webview.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
//handler.cancel(); 默认的处理方式,WebView变成空白页
//handler.process();接受证书
//handleMessage(Message msg); 其他处理
}
});
与SwiperefreshLayout 结合使用
- 可以调用WebView的reload方法,再次加载页面
通用配置
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportZoom(false);
webSettings.setBuiltInZoomControls(false);
webSettings.setAllowFileAccess(true);
webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setGeolocationEnabled(true);
webSettings.setAppCacheEnabled(true);
webSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
webSettings.setDefaultTextEncodingName("UTF-8");
//屏幕自适应
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
} else {
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
webSettings.setDisplayZoomControls(false);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webSettings.setLoadsImagesAutomatically(true);
} else {
webSettings.setLoadsImagesAutomatically(false);
}
mWebView.setScrollBarStyle(WDWebView.SCROLLBARS_INSIDE_OVERLAY);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.setHorizontalFadingEdgeEnabled(false);
mWebView.setVerticalFadingEdgeEnabled(false);
注意事项:
播放视频:
- 声音消失: 调用pauseTimers(), 需要注意在onResume调用resumeTimers(), 而且同一个进程中的WebView都会收到影响, 需要在onResume中
调用resumeTimers(), 不然会卡住
关于refer
关于select标签
- WebView的初始化不能传入Application的context, 不然调不起来,或者crash
Cookie管理
CookieSyncManager.createInstance(mContext);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
String[] cookievalues = cookies.split(";");
for (String value : cookievalues){
cookieManager.setCookie(url,value);
}
if (Build.VERSION.SDK_INT < 21) {
CookieSyncManager.getInstance().sync();
} else {
CookieManager.getInstance().flush();
}
文件上传
- WebChromeClient中提供了选择文件的方法, 但每个版本的内核的方法不同, 需要进行兼容处理
兼容处理
public ValueCallback<Uri> mUploadMessage;
public ValueCallback<Uri[]> mUploadMessageForAndroid5;
private final int OPEN_GALLERY_CODE = 110;
private final int OPEN_GALLERY_CODE_ANDROID5 = 111;
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openChooserImpl(uploadMsg);
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openChooserImpl(uploadMsg);
}
//For Android 5.0+
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
openFileChooserImplForAndroid5(filePathCallback);
return true;
}
//3.0+
public void openChooserImpl(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent intentImage = new Intent(Intent.ACTION_PICK);
intentImage.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
mActivity.startActivityForResult(intentImage, OPEN_GALLERY_CODE);
}
//5.0+
public void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg) {
mUploadMessageForAndroid5 = uploadMsg;
Intent intentImage = new Intent(Intent.ACTION_PICK);
intentImage.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
mActivity.startActivityForResult(intentImage, OPEN_GALLERY_CODE_ANDROID5);
}
注意:
- openFileChooser为hide的方法, 打包混淆需要在proguard-rules.pro中keep
-keepclassmembers class com.hinabian.migrate.activity.AtWebView$MyChromeViewClient{
*;
}
参考