android webview原生与js进行通讯有以下三种方式:
一:js对象注入桥接
通过WebSettings开启JavaScript支持,webSettings.setJavaScriptEnabled(true);然后注入js对象
public class JsInterface {
public JsInterface() {
}
@JavascriptInterface
public String getAppVersion() {
return "1.0";
}
}
JsInterface jsInterface = new JsInterface();
webView.addJavascriptInterface(jsInterface, "android");
在js中调用:window.android.getAppVersion();
二:webview的schema拦截方式处理,此种方法有schema的长度限制。
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("schema://")){
HashMap<String, String> hashMap = paramStringToHashMap(url.replace("schema:///jsbridge/?",""));
if(hashMap.containsKey("action")){
switch (hashMap.get("action")) {
case "post":
getHttpPostData(view,hashMap.get("callback"),null,context);
break;
case "database":
getDataBaseData(context,view,hashMap.get("callback"),null);
break;
}
}
} else {
view.loadUrl(url);
}
return true;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
WebResourceResponse intercepted = null;
if (request.getUrl().toString().contains("file:") &&(
request.getUrl().toString().endsWith("js") || request.getUrl().toString().endsWith("css")) ) {
InputStream localCopy = null;
try {
localCopy = new FileInputStream(request.getUrl().toString().replace("file:",""));
} catch (IOException e) {
e.printStackTrace();
}
intercepted = request.getUrl().toString().endsWith("css")?
new WebResourceResponse("text/css", "UTF-8", localCopy)
:
new WebResourceResponse("text/javascript", "UTF-8", localCopy);
if (intercepted != null) {
if(request.getUrl().toString().endsWith("css"))
intercepted.setMimeType("text/css");
else
intercepted.setMimeType("text/javascript");
}
}
return intercepted;
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
});
/**
* todo url字符串转参数集合
* @param url 地址
* @return 返回执行的javascript字符串
*/
public static HashMap<String, String> paramStringToHashMap(String url) {
HashMap<String, String> hashMap = new HashMap<>();
String[] array = url.split("&");
for(String item:array) {
if(item.indexOf("=") >= 0) {
String[] valueArray = item.split("=");
hashMap.put(valueArray[0],valueArray[1]);
}
}
return hashMap;
}
public static void getHttpPostData(WebView webView,String callBackMethod,JsPromptResult results,Context context) {
MainModel.getInstance().subscribe1(new CallBack() {
@Override
public void sucess(String result) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if(results != null)
results.confirm(result);
webView.evaluateJavascript(executeJsStr(callBackMethod, result),null);
} else {
webView.loadUrl(executeJsStr(callBackMethod, result));
}
}
@Override
public void failed(String result) {
}
},context);
}
public static void getDataBaseData(Context context, WebView webView,String callBackMethod,JsPromptResult results) {
DBHelp.getUser(context, new CallBack() {
@Override
public void sucess(String result) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if(results != null)
results.confirm(result);
webView.evaluateJavascript(executeJsStr(callBackMethod, result),null);
} else {
webView.loadUrl(executeJsStr(callBackMethod, result));
}
}
@Override
public void failed(String result) {
}
});
}
js代码部分:
function invoke(url, action, callback) {
url += "?action=" + action;
var callbackName = ''
if (typeof callback === 'string') {
callbackName = callback
} else {
callbackName = action + Date.now()
window[callbackName] = callback
}
url += '&callback=' + callbackName;
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = url; // 重要!此处会发送连接,会被webviwe捕获到
var body = document.body;
body.appendChild(iframe);
setTimeout(function () {
body.removeChild(iframe);
iframe = null;
});
}
invoke('schema:///jsbridge/?','post',function(res){
console.log("回调成功",res);
alert(res);
});
三:JsPrompt弹窗拦截,此种方法没有长度限制。
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
return true;
}
@Override
public void onReceivedTitle(WebView view, String h5Title) {
super.onReceivedTitle(view, h5Title);
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
return super.onConsoleMessage(consoleMessage);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {// 此方法先于shouldOverrideUrlLoading执行
//对message进行处理
if(message.contains("schema://")){
HashMap<String, String> hashMap = paramStringToHashMap(defaultValue);
if(hashMap.containsKey("action")){
switch (hashMap.get("action")) {
case "post":
getHttpPostData(view,hashMap.get("callback"),result,context);
break;
case "database":
getDataBaseData(context,view,hashMap.get("callback"),result);
break;
}
}
return true;
} else {
return false;
}
}
});
js代码部分
function windowPromote(url,action,callback) {
var param = "action=";
param += action;
var callbackName = ''
if (typeof callback === 'string') {
callbackName = callback
} else {
callbackName = action + Date.now()
window[callbackName] = callback
}
param += '&callback=' + callbackName;
window.prompt(url, param);
}
function callBackMethod(param1) {
document.getElementById('container').innerHTML = param1;
}
windowPromote("schema:///jsbridge/", 'database',callBackMethod);
本文详细介绍了Android WebView与JavaScript进行通信的三种方法:1) 使用`@JavascriptInterface`注解注入Java对象;2) 通过WebView的schema拦截处理;3) 利用`WebChromeClient`的`onJsPrompt`进行JsPrompt弹窗拦截。每种方法都有其特点和适用场景,如js对象注入适合简单交互,schema拦截适用于特定URL请求处理,而JsPrompt则适用于无长度限制的通信。

2288

被折叠的 条评论
为什么被折叠?



