Android与JS交互

Android与JS的方法互调

在Android的开发过程中、遇到一个新需求、那就是让Java代码和Javascript代码进行交互、在IOS中实现起来很麻烦、而在Android中相对来说容易多了、Android对这种交互进行了很好的封装、我们可以很简单的用Java代码调用WebView中的js函数、也可以用WebView中的js来调用Android应用中的Java代码。
案例主要包含了:
一、Html调用Android方法
二、Android调用JS方法无参数
三、Android调用JS方法有参数
四、Android调用JS方法有参数且有返回值处理方式(Android4.4以下)
五、Android调用JS方法有参数且有返回值处理方式2(Android4.4以上)

一、Html调用Android方法

1.创建JS对象


/**
 * 添加javascriptInterface
 * 第一个参数:这里需要一个与js映射的java对象
 * 第二个参数:该java对象被映射为js对象后在js里面的对象名,在js中要调用该对象的方法就是通过这个来调用
 */
webView.addJavascriptInterface(this,"customName");

2.Android代码


@JavascriptInterface
public void showToast(String toast){
    Toast.makeText(this,toast,Toast.LENGTH_SHORT).show();
}

3.JS代码


//调起本地的Java方法()
function showAndroidToast(toast) {
    window.customName.showToast(toast);
}

二、Android调用JS方法无参数

1.Android代码


    isUpload=false;
   webView.post(new Runnable() {
        @Override
         public void run() {
//                webView.loadUrl("javascript:androidCallJS('"+isUpload+"')");
                   webView.loadUrl("javascript:androidCallJSNoParam()");
                                       }
                       								 });

2.JS代码


function androidCallJSNoParam(){
    alert("Android调用JS方法无参数");
}

三、Android调用JS方法有参数

1.Android代码


        isUpload=true;
        webView.post(new Runnable() {
           @Override
            public void run() {
             webView.loadUrl("javascript:androidCallJS("+isUpload+")");
                           		}

注:其实Android调用JS方法只需要
webView.loadUrl(“javascript:androidCallJS(”+isUpload+")");
这一行代码就够了,为什么要放在webView.post(new Runnable(){…})这个方法中去执行呢,原因是如果直接调用这行代码,在Android4.4版本以上的手机上会出现
java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread ‘JavaBridge’. All WebView methods must be called on the same thread.
这种错误,大概意思是说方法被一个叫”javaBridge”的子线程调用了,所有的WebView中的方法都必须在同一个线程中执行.又因为webView.loadUrl()这个方法得在主线程中执行,所以我们要放在webView.post(new Runnable(){…})这个方法中去执行,将WebView放在主线程即可
参考:https://stackoverflow.com/questions/22607657/webview-methods-on-same-thread-error
https://stackoverflow.com/questions/21955593/android-webview-loadurl-wont-load-another-webpage

2.JS代码


    function androidCallJS(isUpload){
    if(isUpload){
         alert("Android调用JS方法有参数");
    }
}

四、Android调用JS方法有参数且有返回值处理方式(Android4.4以下)

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


  webView.post(new Runnable() {
    @Override
    public void run() {
        webView.loadUrl("javascript:sumToJava(1,2)");
    }
});

2.JS方法执行完毕,调用Java代码将值返回


function sumToJava(number1, number2){
    var result=number1+number2;
     window.customName.onSumResult(result)
}

@JavascriptInterface
public void onSumResult(int result) {
    Log.i("TAG", "onSumResult result=" + result);
    Toast.makeText(getApplicationContext(),"result====="+result,Toast.LENGTH_SHORT).show();
}

五、Android调用JS方法有参数且有返回值处理方式(Android4.4以上)

Android 4.4之后使用evaluateJavascript即可。这里展示一个简单的交互示例 具有返回值的js方法
1.JS代码


function getGreetings() {
      return 1;
}

2.Java直接调用JS代码获取返回值


@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void testEvaluateJavascript(WebView webView) {
    webView.evaluateJavascript("getGreetings()", new ValueCallback() {
        @Override
        public void onReceiveValue(String value) {
            Log.i("TAG", "onReceiveValue value=" + value);
            Toast.makeText(getApplicationContext(),"value====="+value,Toast.LENGTH_SHORT).show();
        }});
}

一些需要注意的点:

1.Alert无法弹出
应该是没有设置WebChromeClient,按照以下代码设置


webView.setWebChromeClient(new WebChromeClient());

2.安全限制问题
如果只在4.2版本以上的机器出问题,那么就是系统处于安全限制的问题了。Android文档这样说的
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.
中文大意为
警告:如果你的程序目标平台是17或者是更高,你必须要在暴露给网页可调用的方法(这个方法必须是公开的)加上@JavascriptInterface注释。如果你不这样做的话,在4.2以后的平台上,网页无法访问到你的方法。
解决方法:
将targetSdkVersion设置成17或更高,引入@JavascriptInterface注释
自己创建一个注释接口名字为@JavascriptInterface,然后将其引入。注意这个接口不能混淆。
注,创建@JavascriptInterface代码


@JavascriptInterface
public void showToast(String toast){
    Toast.makeText(this,toast,Toast.LENGTH_SHORT).show();
}

3.Java代码不能设置为private,否则不能被JS调用

4.Java调用JS方法
All WebView methods must be called on the same thread
过滤日志曾发现过这个问题。


E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546):   at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546):   at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546):   at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546):   at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546):   at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546):   at android.os.HandlerThread.run(HandlerThread.java:61)

在js调用后的Java回调线程并不是主线程。如打印日志可验证


lineos:false
ThreadInfo=Thread[WebViewCoreThread,5,main]

解决上述的异常,将webview操作放在主线程中即可。


	webView.post(new Runnable() {
    @Override
    public void run() {
        webView.loadUrl(YOUR_URL).
    }
});

5.代码混淆问题
如果在没有混淆的版本运行正常,在混淆后的版本的代码运行错误,并提示Uncaught TypeError: Object [object Object] has no method,那就是你没有做混淆例外处理。 在混淆文件加入类似这样的代码


-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值