您的位置:首页 > 移动开发 > Android开发

Android中Webview与Js交互技巧大全(二)

2018-04-02 16:40 447 查看
上一篇给大家说了下WebView调用js这个应该来说比较简单,在说JS调用WebView之前如果有没看过上篇的这里有传送门,好了接下来还是直接上代码吧!
对于JS调用Android代码的方法大体来说有三种:
1,通过WebView的addJavaScriptInterface()就是对象映射的方式(虽然有瑕疵,但是这是本人非常常用的方法)
2,通过WebViewClient的shouldOverrideUrlLoading()方法回调拦截url

3,通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、

 confirm()、prompt() 消息
先看第一种通过WebView的addJavaScriptInterface()
/步骤1:定义一个与JS对象映射关系的Android类:AndroidtoJs
public class AndroidtoJs extends Object{

//定义js需要调用的方法(必须加入@JavascriptInterface注解)
@JavascriptInterface
public void hello(String str){
System.out.println(str);
}

}再看看html写法
<html>
<head>
<meta charset="utf-8">
<title>YANXUN</title>
<script>
function callAndroid(){
//由于对象映射,所以调用了test对象等于调用了Android映射的对象
test.hello("js调用了Android当中的你好方法");
}
</script>
</head>
<body>
<button type="button" id="b1" onclick="callAndroid()" >调用callAndroid()方法</button>
<style>
button{
width:300px;
height:45px;
}
</style>
</body>
</html>看看activity中的写法
public class MainActivity extends AppCompatActivity {

private WebView mWebView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = ((WebView) findViewById(R.id.wv));
WebSettings mWebViewSettings = mWebView.getSettings();
//与js交互的权限
mWebViewSettings.setJavaScriptEnabled(true);
//通过WebView的addJavascriptInterface()进行对象映射 方式使用简单.
//但是该方法会存在严重漏洞:当JS拿到Android这个对象后,就可以调用这个Android对象中所有的方法(java反射机制),包括系统类(java.lang.Runtime 类),从而进行任意代码执行。
/**例如:可以执行命令获取本地设备的SD卡中的文件等信息从而造成信息泄露
*当一些APP通过扫描二维码打开一个外部网页时,攻击者就可以执行这段 js 代码进行漏洞攻击
* 在微信盛行、扫一扫行为普及的情况下,该漏洞的危险性非常大
*/
/*参数一:一个与JS对象映射关系的Android类
*参数二:JS中进行映射的对象
*/
mWebView.addJavascriptInterface(new AndroidtoJs(),"test");//AndroidtoJS类对象映射到js的test对象
//加载h5,注意格式为:file:///android_asset/文件名
mWebView.loadUrl("file:///android_asset/MyJs.html");

}
}后面的布局都是这个
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="yanxun.com.jstowebview.MainActivity">

<WebView
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#ffffff"
android:layout_margin="10dp"
android:id="@+id/wv"
/>

</LinearLayout>
---------------------------------------------------------------------------------------------------------------------------------
第二种就复杂一点了!通过WebViewClient的shouldOverrideUrlLoading()方法回调拦截url
先看看html代码
<html>
<head>
<meta charset="utf-8">
<title>Lebron James</title>
<script>
function callAndroid(){
/*约定的url协议为:js://webview?arg1=111&arg2=222*/
document.location = "js://webview?arg1=111&arg2=222";
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button>
<style>
button{
width:300px;
height:45px;
}
</style>
</body>
</html>再来看看activity写法
public class Main2Activity extends AppCompatActivity {

private WebView mWv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

mWv = ((WebView) findViewById(R.id.wv));
WebSettings webSettings = mWv.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWv.loadUrl("file:///android_asset/MyJsTwo.html");
//1.重写shouldOverrideUrlLoading方法 优点是没有方法一的漏洞但获取Android方法的返回值复杂。
mWv.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 步骤2:根据协议的参数,判断是否是所需要的url
// 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
//假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
Uri uri = Uri.parse(url);
// 如果url的协议 = 预先约定的 js 协议
// 就解析往下解析参数
if(uri.getScheme().equals("js")){
// 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议
// 所以拦截url,下面JS开始调用Android需要的方法
if(uri.getAuthority().equals("webview")){
// 步骤3:
// 执行JS所需要调用的逻辑
System.out.println("js调用了Android的方法");
// 可以在协议上带有参数并传递到Android上
/* HashMap<String, String> params = new HashMap<>();
Set<String> collection = uri.getQueryParameterNames();*/
}
return true;
}

return super.shouldOverrideUrlLoading(view, url);
}
});
}
}
---------------------------------------------------------------------------------------------------------------------------------
第三种则是通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、

 confirm()、prompt() 消息
先看看html的写法
<html>
<head>
<meta charset="UTF-8">
<title>Kobe bryant</title>
<script>
function clickprompt(){
//调用prompt()
var result = prompt("js://demo?arg1=111&arg2=222");
alert("demo" + result);
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="clickprompt()">点击调用Android代码</button>
</body>
<style>
button{
width:300px;
height:45px;
}
</style>
</html>再看看activity写法
public class Main3Activity extends AppCompatActivity {

private WebView mV;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
mV = ((WebView) findViewById(R.id.wv));
WebSettings mVSettings = mV.getSettings();
mVSettings.setJavaScriptEnabled(true);
mVSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mV.loadUrl("file:///android_asset/MyJsThree.html");
mV.setWebChromeClient(new WebChromeClient(){
/*
// 拦截输入框(原理同方式2)
// 参数message:代表promt()的内容(不是url)
// 参数result:代表输入框的返回值
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Uri uri = Uri.parse(url);
if(uri.getScheme().equals("js")){
if(uri.getAuthority().equals("demo")){
//
// 执行JS所需要调用的逻辑
System.out.println("js调用了Android的方法");

//参数result:代表消息框的返回值(输入值)
result.confirm("js调用了Android的方法成功啦");
}
return true;
}

return super.onJsPrompt(view, url, message, defaultValue, result);
}
});
}
}好了以上就是三种js调用webview方法详细,注释也算很齐全,相信大家能理解,最后我来总结一下:
方式优点缺点使用地方
通过WebView的addJavaScriptInterface()使用简单4.2以下有漏洞问题4.2以上比较简单需求
通过WebViewClient的shouldOverrideUrlLoading()方法回调拦截url没有漏洞使用麻烦,需要双方约定协议,从本地往web传值麻烦不需要返回值的时候
通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、
 confirm()、prompt() 方法
没有漏洞需要双方约定协议能满足大多数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息