android webview js交互,Android与JS交互

现在越来越多的App是混合开发,很需要原生与网页交互,下面介绍如何交互以及有可能出现的坑。

Java调用JS方法

对于Android调用JS方法的方式有2种:

通过WebView的loadUrl()

通过WebView的evaluateJavascript()

方式一:loadUrl()

第一步:设置与Js交互的权限

WebSettings webSettings = mWebView.getSettings();

// 设置与Js交互的权限

webSettings.setJavaScriptEnabled(true);

第二步:设置加载网页

mWebview.loadUrl("加载的网页");

第三步:调用JS方法

通过使用mWebview.loadUrl 调用“javascript:" + 方法

如果JS这样定义的

function callJS(){

alert("Android调用了JS的无参callJS方法");

}

function callJSParameter(message){

alert("Android调用JS的有参callJS方法,参数为"+message);

}

在Java代码中

//调用无参

mWebView.loadUrl("javascript:callJS()");

//调用有参

mWebView.loadUrl("javascript:callJSParameter('测试')");

方式一注意事项(也就是坑)

调用JS方法时一定要在onPageFinished()回调之后才能调用,否则不会调用。

onPageFinished()属于WebViewClient类的方法,主要在页面加载结束时调用

调用JS方法时一定要在主线程,否则会崩溃异常。

java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Thread-18022'. All WebView methods must be called on the same thread.

如果非要在子线程调用,也要将其转换到主线程中去:

mWebView.post(new Runnable() {

@Override

public void run() {

mWebView.loadUrl("javascript:callJS()");

}

});

调用的带参数的JS方法时,参数类型如果为String ,切记使用单引号( ') 包裹;如果为数组类型则不用,如:javascript:callJs([01, 02, 03]);如果为其他复杂类型则可以转换为 Json 字符串的形式传递。

方式二:evaluateJavascript()

*执行该方法不会使页面刷新,而第一种方法(loadUrl )的执行则会,但是Android 4.4 后才可使用,兼容性要求偏高。

JS代码

function callJSReturn(message){

return message;

}

Java代码

mWebView.evaluateJavascript("javascript:callJSReturn('方式二调用JS')", new ValueCallback() {

@Override

public void onReceiveValue(String value) {

//此处为 js 返回的结果

Toast.makeText(MainActivity.this, value, Toast.LENGTH_SHORT).show();

}

});

两种方式对比

调用方式

优点

缺点

使用场景

loadUrl()

兼容性好

获取返回值麻烦

不需要获取返回值

evaluateJavascript()

只能从4.4(18)以上使用

获取返回值简单

4.4(18)以上

JS调用Java

JS调用Java的方式有三种

通过WebView的addJavascriptInterface()

通过WebViewClient 的shouldOverrideUrlLoading()方法回调拦截 url

通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息

方式一:addJavascriptInterface()

JS代码

LYJ

function testCallAndroid(){

test.callAndroid("JS调用了Android方法");

}

点击按钮通过方式一调用Android方法

第一步:定义一个JS调用的方法

@JavascriptInterface

public void callAndroid(String message){

Toast.makeText(CallAndroidActivity.this,message,Toast.LENGTH_SHORT).show();

}

1.必须要有@JavascriptInterface,在 Android4.2(17) 及更高版本的系统中,任何暴露给 Js 访问的 Java 接口都需要添加这个注解,否则会报异常:Uncaught TypeError: Object [object Object] has no method ‘XXX’。系统在之前的版本中有漏洞,Js 可以通过反射的方式访问注入 WebView 中的 Java 对象的 public 类型 field 和 method,从而随意修改宿主程序,所以为了安全增加了这个注解。想更深入的了解参考这篇文章你不知道的 Android WebView 使用漏洞

2.方法名切记要和JS调用的方法名一样

第二步将Java对象映射到JS对象

mWebView.addJavascriptInterface(this, "test");

第一个参数是写有JS调用方法的Android对象,第二个参数是JS调用的对象名,切记跟网页上的一致。

方式一注意事项

Js 调用 Java 方法时,不是在主线程 (Thread Name:main) 中运行的,而是在一个名为 JavaBridge 的线程中执行的,如果需要 Java 继续回调 Js,千万别在 JavascriptInterface 方法体中直接执行 loadUrl() 方法,而是像前面一样进行线程切换操作。

方式二:WebViewClient 的shouldOverrideUrlLoading()方法

JS代码

function testTwoCallAndroid(){

document.location = "js://webview?key1=value1&key2=value2";

}

点击按钮通过方式二调用Android方法

Java代码

// 复写WebViewClient类的shouldOverrideUrlLoading方法

mWebView.setWebViewClient(

new WebViewClient() {

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) {

// 第一步:根据协议的参数,判断是否是所需要的url

// 一般根据scheme(协议格式) & authority(协议名)判断

//假定传入进来的 url = "js://webview?key1=value1&key2=value2"(同时也是约定好的需要拦截的)

Uri uri = Uri.parse(url);

// 第二步:如果url的协议 = 预先约定的 js 协议,就解析往下解析参数

if (uri.getScheme().equals("js")) {

//第三步:再判断,如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议

// 所以拦截url,下面JS开始调用Android需要的方法

if (uri.getAuthority().equals("webview")) {

// 第四步:

// 执行JS所需要调用的逻辑

// 获取协议执行的参数

HashMap params = new HashMap<>();

Set collection = uri.getQueryParameterNames();

for (String key : collection){

String value = uri.getQueryParameter(key);

Log.d("==","key = " + key + ",value = " + value);

params.put(key,value);

}

}

return true;

}

return super.shouldOverrideUrlLoading(view, url);

}

}

);

}

注释比较清楚,就按注释的步骤走。

shouldOverrideUrlLoading(WebView view, String url)在Android 7.0(24)过时,官方改为shouldOverrideUrlLoading (WebView view,

WebResourceRequest request)。然后获取Uri改为Uri uri = request.getUrl();。

方式三:通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息

方法

作用

返回值

备注

alert()

弹出警告框

没有

在文本加入/n可换行

confirm()

弹出确认框

两个

返回boolean值,true代表确认,false代表取消

prompt()

弹出输入框

任意

点击确认返回输入框的值,点击取消返回null

下面的例子将用拦截 JS的输入框(即prompt()方法)说明,其他两种与其类似 :

JS代码

function testPromptCallAndroid(){

var result=prompt("js://prompt?key1=value1&key2=value2");

alert("方式三 " + result);

}

点击按钮通过方式三调用Android方法

Java代码

mWebView.setWebChromeClient(

new WebChromeClient() {

// 拦截输入框(原理同方式2)

// 参数message:代表promt()的内容(不是url)

// 参数result:代表输入框的返回值

@Override

public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {

// 根据协议的参数,判断是否是所需要的url(原理同方式2)

// 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)

//假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)

Uri uri = Uri.parse(message);

// 如果url的协议 = 预先约定的 js 协议

// 就解析往下解析参数

if (uri.getScheme().equals("js")) {

// 如果 authority = 预先约定协议里的 webview,即代表都符合约定的协议

// 所以拦截url,下面JS开始调用Android需要的方法

if (uri.getAuthority().equals("prompt")) {

// 执行JS所需要调用的逻辑

// 可以在协议上带有参数并传递到Android上

HashMap params = new HashMap<>();

Set collection = uri.getQueryParameterNames();

for (String key : collection) {

String value = uri.getQueryParameter(key);

Log.d("==", "key = " + key + ",value = " + value);

params.put(key, value);

}

//参数result:代表消息框的返回值(输入值)

result.confirm("js通过方式三调用了Android的方法成功");

}

return true;

}

return super.onJsPrompt(view, url, message, defaultValue, result);

}

}

);

整体上跟上一个方式相差不多。

其他

如果需要回调这种需求,你只要android的异步回调中,使用loadUrl调用js的相关方法。

如果需要给JS返回值,除了方式三以外,还可以这么做

JS代码

function returnResult(result){

alert("result is" + result);

}

Java代码

mWebView.loadUrl("javascript:returnResult(" + result + ")");

参考文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值