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方法详细,注释也算很齐全,相信大家能理解,最后我来总结一下:
对于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() 方法 | 没有漏洞 | 需要双方约定协议 | 能满足大多数 |
相关文章推荐
- Android中Webview与Js交互技巧大全(一)
- Android就业面试技巧系列-技术篇5 (WebView和JS交互)
- android WebView访问本地页面swf交互JS权限 #2060错误
- Android中webview和js之间的交互及注意事项
- android webView js方法和java 方法交互
- android webview js交互 第一节 (java和js交互)
- android webview js交互, 响应webview中的图片点击事件
- android webview js交互, 响应webview中的图片点击事件
- Android WebView与JS交互
- android webview js交互 第一节 (java和js交互)
- android通过webview和js交互
- android webview js交互, 响应webview中的图片点击事件
- Android WebView与Js交互
- Android中webview和js之间的交互
- android webview js交互, 响应webview中的图片点击事件
- android开发中,webview的js与Native code交互
- Android WebView 与JS的数据交互
- Android 的webview与js交互
- Android中webview和js之间的交互
- android WebView js 交互