Android hybrid之JS与Native的通信方式

场景

为了降低开发成本和跨平台一致性的用户体验.通常敏捷开发中通常采用混合型应用Hybrid App(Native View与WebView交替调用),而Js作为Html页面中常用的逻辑处理脚本,掌握JS和Java的相互通信是非常重要的!

操作步骤

  • webView设置支持JavaScript
  • webView提供JavaScript接口
  • 客户端和网页端定义好方法申明.编写代码

Js调用Java

ps: 有时候,在webview中有个Button,而点击这个Button.我们的App需要finish掉这个页面,但是我们在App中是没法捕捉到这个按钮的点击事件的,.那么这时候就需要用到Js 回调Java的方法来实现了

①布局文件

  <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

②Js代码

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
</head>
<body>
<title>test html</title>
<button onclick="window.js.comeplete()">comeplete()</button>
<br/>
</body>
</html>

很简单,就是一个按钮,并添加点击事件,这里需要注意的是我们的调用,里面有一个.js,其实这个是我们在java代码中天加的接口名字.

③java代码

首先为了能够支持JavaScript,我们的webView必须setJavaScriptEnabled(true)

mWebView = (WebView) findViewById(R.id.webview);
        // 启用javascript
        mWebView .getSettings().setJavaScriptEnabled(true);
        // 从assets目录下面的加载html
        mWebView .loadUrl("file:///android_asset/js.html");
        mWebView .addJavascriptInterface(this, "js");

④最后添加相应的方法

public void comeplete(){
        this.finish();
    }

Java调用JS

同样,有时候,我们又需要根据不同的操作,让页面显示不同的内容,那么这时候就需要用到Java调用JavaScript了/

①这时候,我们的html页面是这样的

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
function javacalljs(){
     document.getElementById("content").innerHTML +=   
         "<br\>java调用了js函数";
}

function javacalljswithargs(arg){
     document.getElementById("content").innerHTML +=   
         ("<br\>"+arg);
}

</script>
</head>
<body>
<title>test html</title>
<div id="content">内容显示</div>
</body>
</html>

②布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

  <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="java调用js函数" />
    <Button
        android:id="@+id/button2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="java调用js函数(带参数)" />
</LinearLayout>

③Java代码

mWebView = (WebView) findViewById(R.id.webview);
        // 启用javascript
        mWebView .getSettings().setJavaScriptEnabled(true);
        // 从assets目录下面的加载html
        mWebView .loadUrl("file:///android_asset/js.html");
        Button button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(btnClickListener);
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(btnClickListener);

④按钮的点击事件

OnClickListener btnClickListener = new Button.OnClickListener() {
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.button1:
// 无参数调用
    mWebView.loadUrl("javascript:javacalljs()");
                break;
            case R.id.button2:// 传递参数调用 
                            mWebView .loadUrl("javascript:javacalljswithargs(" + "'hello world,i`m Java'" + ")");
                break;
            default:
                break;
            }       
        }
    };

Android 4.2以后的注入事项

  • @JavascriptInterface

在使用中,我们发现当targetSdkVersion>17的时候就会出现一下异常E/Web Console: Uncaught TypeError: Object [object Object] has no method 'toString'

通过查看官方文档,解释如下

From the Android 4.2 documentation:

Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

意思就是当targetSdkVersion>17的时候,我们需要在暴露给js的接口加上@JavascriptInterface注解

因此4.2 之后的js 调用java方式是这样的

@JavascriptInterface
public void comeplete(){
        this.finish();
    }

调用js有参数有返回值的函数

Android在4.4之前并没有提供直接调用js函数并获取值的方法,所以在此之前,常用的思路是 java调用js方法,js方法执行完毕,再次调用java代码将值返回。

Js代码:

function button2click1(){
window.js.showResult(index);
}

Java代码

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

// 在回调中获取返回值
  @JavascriptInterface
    public void showResult(String s){
        Toast.makeText(this,s+"",Toast.LENGTH_LONG).show();
    }

Android 4.4之后使用evaluateJavascript即可获取JavaScript返回值.

Js代码

var index=0;  
function android_call_js_parameter(arg){  
    index+=Number(arg);
     document.getElementById("content").innerHTML +=("<br\>"+index);  
     return index;
}  

function  button2click(){  
   return 1;
}

Java代码

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    mWebView.evaluateJavascript("button2click()",
                    //设置回调接口
                            new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {
                                    mWebView.loadUrl("javascript:android_call_js_parameter('" + value + "')");
                                }
                            });
                }

效果图:

Android JavaScript和java 交互

使用Dmeo:JsJavaInteractive [Github]

参考:
stackoverflow: [Android - How I can call javascript function and getting the retur value from javascript function]

技术小黑屋: [Android中Java和JavaScript交互]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值