一、webview的请求方式
1.1、get方式
//get方式请求
mWebView.loadUrl("url"); //网络路径
mWebView.loadUrl("file:///android_asset/test.html"); //APP本地的Html
//post方式请求,带参数
String postDate = "name=abc&type=1";
mWebView.postUrl(url, postDate.getBytes());
1.2、webview的下载文件
//调用系统浏览器实现下载功能
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(url));
startActivity(intent);
}
});
1.3、setting属性
WebSettings wSet = mWebView.getSettings();
wSet.setJavaScriptEnabled(true); //可以与js交互
wSet.setCacheMode(WebSettings.LOAD_NO_CACHE); //无缓存
wSet.setDomStorageEnabled(true); // 用于解决webview加载的网页不能点击
webSettings.setSupportZoom(true); //支持屏幕缩放
webSettings.setBuiltInZoomControls(true);
wSet.setUserAgentString(wSet.getUserAgentString() + ";Android"); //添加agent特有表示
1.4、设置webviewClient
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
//重定向(也可以做与js的交互)
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
//请求异常,加载本地异常页面
}
});
1.5、设置webChromeClient
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
//进度条
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
//获取html的title
}
});
1.6、webview的前进后退
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mWebView.canGoBack()) {
mWebView.goBack();
//当前显示的页面是内部重定向的时候打开的,当返回时,并不会显示上一个页面的title,显示的还是当前页面的title,这里需要做特殊处理,可以把所有的title添加到一个集合里,
return true;
}
if (mWebView.canGoForward()) {
mWebView.goForward();
return true;
}
return super.onKeyDown(keyCode, event);
}
1.8、清除缓存
//由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
mWebView.clearCache(true);
//清除当前webview的访问历史记录里
mWebView.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
mWebView.clearFormData();
二、Html与js交互方式
1、监听webviewClient的shouldOverrideUrlLoading()方法
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return super.shouldOverrideUrlLoading(view, request);
//重定向(也可以做与js的交互)
Uri uri = request.getUrl();
String schemeStart = uri.getScheme().toLowerCase();
if (schemeStart.equals("android")) {
}
}
2、添加javascriptInterface方式
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new Demo(), "demo");//demo为前端和Html共同约定的
//交互类
public class Demo {
@JavascriptInterface
public void getMethod() {
}
}
js调用原生方法
demo.getMethod();
(1)原生调用js
方式一:loadUrl,不能获取js的返回值,会刷新页面
getText是js方法无参
mWebView.loadUrl("javascript:getText()");
一个参数,注意单引号
String params="value";
mWebView.loadUrl("javascript:getText('"+jsonParams+"')");
json参数,注意单引号
JSONObject jsonParams=new JSONObject();
jsonParams.put("key","value");
mWebView.loadUrl("javascript:getText('"+jsonParams.toString()+"')");
方式二:evaluateJavascript 安卓4.4以后才可以使用,可以获取js返回值
webView.evaluateJavascript("javascript:getText()",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {}
});
3、jsBridge方式
3.1、引入jar包
compile 'com.github.lzyzsd:jsbridge:1.0.4'
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
3.2、xml文件
<com.github.lzyzsd.jsbridge.BridgeWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
3.3、android端初始化
//设置简单没有回调的调用方式
mWebView.setDefaultHandler(new DefaultHandler());
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new BridgeWebViewClient(mWebView));
3.4、js端初始化,注册监听(Android调用js是要再js中注册监听)
// 注册事件监听
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
3.5、Html调用android端
//Js端代码
function testClick(){
window.WebViewJavascriptBridge.callHandler(
'function_name',
{'Data':'给native的数据'},
function(responseData){
//在native操作后,会传数据responseData给js,js继续自己的操作
}
);
}
//Native端代码
mWebView.registerHandler("function_name", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
//data是js返回的数据,在native中用
function.onCallBack("传递数据给js");
}
});
//function_name是方法名,前后端要一致
3.6、android调用js方法
//Native端
mWebView.callHandler("function_name", "传递给js的数据", new CallBackFunction() {
@Override
public void onCallBack(String data) {
//调用完js后,data是js返回的数据,然后native在这执行自己的逻辑
}
});
//js端
bridge.registerHandler("function_name", function(data, responseCallback) {
//data是Android带过来的数据
responseCallback(responseData);//回调返回给Android端
});
3.7、jsBridge的优点
android api4.4之前,谷歌的webview存在安全漏洞,网站js注入,所以调用java方法需要加入@javascriptinterface注解。
3.8、jsBridge原理
JsBridge是Native代码合Js代码的通信桥梁。思路是:Html5触发 Url scheme---->Native捕获uri scheme---->原生分析,执行---->原生调用Html5。如下图:
详细思路如下:
三、webview的优化
1、webview的创建
不要在xml中定义webview,而是在需要的时候在创建webview,并且context使用getApplicationContext
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mWebView = new WebView(getApplicationContext());
mWebView.setLayoutParams(params);
mLayout.addView(mWebView);
2、webview的销毁
先把webview从其父控件移除,然后调动destory方法
@Override
protected void onDestroy() {
super.onDestroy();
((ViewGroup)mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView=null;
}
四、Html打开原生app
1、使用scheme
<a href="[scheme]://[host]/[path]?[query]">启动应用程序</a>
2、代码
在app的启动页配置scheme
<activity
android:name=".base.SplashActivity"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!--通过浏览器Url启动app-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="scheme" />
</intent-filter>
</activity>
在启动页的获取数据
private Uri schemeUriData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_splash);
context = this;
if (getIntent() != null) {
schemeUriData = getIntent().getData();
Uri uri = Uri.parse(data);
String path = uri.getPath();
if (path.endsWith("order")) {//打开订单
}
}
}