关于android月js或者说html交互的方式,在很早的版本中是通过android端添加js支持,然后传递一个js操作本地方法的对象,然后就可以调用本地的方法。在后边的版本为了统一管理,添加了@JavascriptInterface  ,只有添加了这个标志的方法才能被js调用。

但是这样的调用方式还是存在安全的漏掉,所有后边就有了另外的俩种调用方式。

android如何调用js方法参数类型 安卓调用js方法_ide

android如何调用js方法参数类型 安卓调用js方法_json_02

android如何调用js方法参数类型 安卓调用js方法_ide_03

android如何调用js方法参数类型 安卓调用js方法_本地方法_04

方式 一:

WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSObject(), "myObj");

添加js支持,传递调用本地方法的对象到js中。

方式二:

主要是监听shouldOverrideUrlLoading 方法,该方法是WebViewClient中实现的方法。

mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
});

下边是对自己定义好的参数进行处理,因为只要点击网页中的任何按钮都会调用

shouldOverrideUrlLoading方法,所有要进行不同请求方式的不同处理。http与https让他还是默认访问本来地址,对于自己要处理的本地请求做本地处理

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (url.startsWith("http") || url.startsWith("https"))
{
return super.shouldOverrideUrlLoading(view, url);
}else{
Log.i("jw", "url:"+url);
//协议url:"js://demo?arg1=111"
try {
//只处理指定协议
String protocol = JSBridge.getUrlScheme(url);
JSBridge bridge = new JSBridge(mContext);
if("baidumobilegamejsload".equals(protocol)){
HashMap map = JSBridge.getUrlParams(url);
String method = JSBridge.getUrlMethod(url);
JSONObject jsonObject = new JSONObject();
if(method.equals("downloadGame")){//下载游戏
String pkg = map.get(JSBridge.PACKAGER);
String title = map.get(JSBridge.TITLE);
String gameId = map.get(JSBridge.GAMEID);
String size = map.get(JSBridge.SIZE);
String download_url = map.get(JSBridge.DOWNLOADURL);
String icon_url = map.get(JSBridge.ICONURL);
String version = map.get(JSBridge.VERSION);
bridge.downloadGame(pkg, title, gameId, size, download_url, icon_url, version);
}else if(method.equals("isInstall")){//应用是否安装
jsonObject.put(JSBridge.RESULT, bridge.isInstall(map.get(JSBridge.PACKAGER)));
}else if(method.equals("startApp")){//打开应用
bridge.startApp(map.get("packageName"));
}else if(method.equals("checkStatus")){//检查应用的状态,0、未下载 ,1、已安装 。2、下载中(暂停)
jsonObject.put(JSBridge.STATUS, bridge.getDownloadAppStatus( map.get("JSBridge.PACKAGER"), map.get(JSBridge.DOWNLOADURL)));
}else if(method.equals("continueDownloadGame")){
bridge.restartDownloadGame(map.get(JSBridge.DOWNLOADURL));
}else if(method.equals("installGame")){
bridge.installOrOpenGame(map.get(JSBridge.DOWNLOADURL));
}else if(method.equals("getDownloadGameProgress")){
int progress = bridge.getDownloadGameProgress(map.get(JSBridge.DOWNLOADURL));
jsonObject.put(JSBridge.PROGRESS, progress);
}
mWebView.loadUrl("javascript:sys("+jsonObject.toString()+")");
return true;
}
} catch (Exception e) {
Log.i("jw", "error:"+Log.getStackTraceString(e));
}
}
return false;
}

方式三:

方式三与方式二十分相似,是来拦截onJsAlert(js对话框),或者onJsConfirm(确认对话框)或者onJsPrompt(可编辑文本框)来进行js对于本地代码的请求。

但是要注意的是只有onJsPrompt可以传递数据到js,前边俩个只能接收js调用本地方法的请求,没有办法进行参数回传。

mWebView.setWebChromeClient(new WebChromeClient(){
//拦截JS的alert方法
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
//拦截JS的confirm方法
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return super.onJsConfirm(view, url, message, result);
}
//拦截JS的prompt方法
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
JsPromptResult result) {
Log.i("jw", "url:"+url+",message:"+message);
//协议url:"js://demo?arg1=111"
try {
//只处理指定协议
String protocol = getUrlScheme(message);
if("js".equals(protocol)){
HashMap map = getUrlParams(message);
String arg1 = map.get("arg1");//获取到指定key的参数值,调用本地方法
String res = getPwd(arg1);
result.confirm(res);//返回值
}
} catch (Exception e) {
Log.i("jw", "error:"+Log.getStackTraceString(e));
}
return true;
}
});

这就是基本使用方式,但是要注意的是alert等框的弹出的处理,因为我们只是要交换数据,没有必要弹出对话框。

只要在拦截的方法里边return的 时候不调用相对应的super就可以拦截对话框的弹出,

直接返回true。那么就拦截了对话框的弹出,那么就可以放心的进行数据交互了。

对于为啥方式一有漏洞,可以自行百度。