Android中Java和JavaScript交互实例

Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScript又是一个很举足轻重的脚本。本文将介绍如何实现Java代码和Javascript代码的相互调用。

如何实现

实现Java和js交互十分便捷。通常只需要以下几步。

1.WebView开启JavaScript脚本执行
2.WebView设置供JavaScript调用的交互接口。
3.客户端和网页端编写调用对方的代码。

本例代码

为了便于讲解,先贴出全部代码

Java代码

代码如下:

package com.example.javajsinteractiondemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {
  private static final String LOGTAG = "MainActivity";
  @SuppressLint("JavascriptInterface")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      final WebView myWebView = (WebView) findViewById(R.id.myWebView);
      WebSettings settings = myWebView.getSettings();
      settings.setJavaScriptEnabled(true);
      myWebView.addJavascriptInterface(new JsInteration(), "control");
      myWebView.setWebChromeClient(new WebChromeClient() {});
      myWebView.setWebViewClient(new WebViewClient() {

@Override
          public void onPageFinished(WebView view, String url) {
              super.onPageFinished(view, url);
              testMethod(myWebView);
          }
         
      });
      myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
  }
 
  private void testMethod(WebView webView) {
      String call = "javascript:sayHello()";
     
      call = "javascript:alertMessage(\"" + "content" + "\")";
     
      call = "javascript:toastMessage(\"" + "content" + "\")";
     
      call = "javascript:sumToJava(1,2)";
      webView.loadUrl(call);
     
  }
 
  public class JsInteration {
     
      @JavascriptInterface
      public void toastMessage(String message) {
          Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
      }
     
      @JavascriptInterface
      public void onSumResult(int result) {
          Log.i(LOGTAG, "onSumResult result=" + result);
      }
  }

}

前端网页代码

代码如下:

<html>
<script type="text/javascript">
    function sayHello() {
        alert("Hello")
    }

function alertMessage(message) {
        alert(message)
    }

function toastMessage(message) {
        window.control.toastMessage(message)
    }

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
    }
</script>
Java-Javascript Interaction In Android
</html>

调用示例

js调用Java

调用格式为window.jsInterfaceName.methodName(parameterValues) 此例中我们使用的是control作为注入接口名称。

代码如下:

function toastMessage(message) {
  window.control.toastMessage(message)
}

function sumToJava(number1, number2){
   window.control.onSumResult(number1 + number2)
}

Java调用JS

webView调用js的基本格式为webView.loadUrl(“javascript:methodName(parameterValues)”)

调用js无参无返回值函数

代码如下:

String call = "javascript:sayHello()";
webView.loadUrl(call);

调用js有参无返回值函数

注意对于字符串作为参数值需要进行转义双引号。

代码如下:

String call = "javascript:alertMessage(\"" + "content" + "\")";
webView.loadUrl(call);

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

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

1.Java调用js代码

代码如下:

String call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);

2.js函数处理,并将结果通过调用java方法返回

代码如下:

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
}

3.Java在回调方法中获取js函数返回值

代码如下:

@JavascriptInterface
public void onSumResult(int result) {
  Log.i(LOGTAG, "onSumResult result=" + result);
}

4.4处理

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

代码如下:

function getGreetings() {
      return 1;
}

java代码时用evaluateJavascript方法调用

代码如下:

private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

@Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}

输出结果

代码如下:

I/MainActivity( 1432): onReceiveValue value=1

注意

1.上面限定了结果返回结果为String,对于简单的类型会尝试转换成字符串返回,对于复杂的数据类型,建议以字符串形式的json返回。
2.evaluateJavascript方法必须在UI线程(主线程)调用,因此onReceiveValue也执行在主线程。

疑问解答

Alert无法弹出

你应该是没有设置WebChromeClient,按照以下代码设置

代码如下:

myWebView.setWebChromeClient(new WebChromeClient() {});
Uncaught ReferenceError: functionName is not defined

问题出现原因,网页的js代码没有加载完成,就调用了js方法。解决方法是在网页加载完成之后调用js方法

代码如下:

myWebView.setWebViewClient(new WebViewClient() {

@Override
  public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);
      //在这里执行你想调用的js函数
  }
 
});

Uncaught TypeError: Object [object Object] has no method

安全限制问题

如果只在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以以后的平台上,网页无法访问到你的方法。

解决方法

1.将targetSdkVersion设置成17或更高,引入@JavascriptInterface注释
2.自己创建一个注释接口名字为@JavascriptInterface,然后将其引入。注意这个接口不能混淆。这种方式不推荐,大概在4.4之后有问题。

注,创建@JavascriptInterface代码

代码如下:

public @interface JavascriptInterface {

}

代码混淆问题

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

代码如下:

-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}

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回调线程并不是主线程。如打印日志可验证

代码如下:

ThreadInfo=Thread[WebViewCoreThread,5,main]

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

代码如下:

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

(0)

相关推荐

  • Android WebView上实现JavaScript与Java交互

    其实webview加载资源的速度并不慢,但是如果资源多了,当然就很慢.图片.css .js .html这些资源每个大概需要10-200ms ,一般都是30ms就ok了.不过webview是必须等到全部资源都完成加载,才会进行渲染的,所以加载的速度很重要!从Google上我们了解到,webview加载页面的顺序是:先加载html,然后从里面解析出css.js文件和页面上的图片资源进行加载.如果webkit的缓存里面有,就不加载.加载完这些资源之后,就进行css的渲染和js的执行.Css的渲染一般不

  • android中WebView和javascript实现数据交互实例

    在看懂这篇文章之前首先要有javascript基础. (1) js调用android的方法: 复制代码 代码如下: WebView wView: wView. addJavascriptInterface (Object obj, String interfaceName); 是实例化一个对象,在html的js中调用,第二个参数是实例化对象的别名,如果要使用这个obj,则在js中使用的名字 就是interfaceName. 复制代码 代码如下: public class jsWebDemo ex

  • Android中极简的js与java的交互库(SimpleJavaJsBridge)

    前言 最近接触android中js与java交互的东西很多,当然它们之间的交互方式有几种,但是我觉得这几种交互方式都存在一定的不足,这是我决定编写SimpleJavaJsBridge这个库的关键原因. 我会按以下顺序进行本文章: 现有js与java通信方案及不足 js与java完美通信方案设计 SimpleJavaJsBridge 现在进入正题 1. 现有js与java通信方案及不足 先来说明一点js与java通信,指的是js既可以给java发送消息,同时java也可以给js发送消息.那就来屡屡

  • Android中fragment与activity之间的交互(两种实现方式)

    (未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<详解Android中Fragment的两种创建方式>,就如何创建Fragment混合布局做了详细的分析,今天就来详细说道说道Fragment与宿主Activity之间是如何实现数据交互的. 我们可以这样理解,宿主Activity中的Fragment之间要实现信息交互,就必须通过宿主Activity,Fragment之间是不可能直接实现信息交互的. Fragmen

  • 解析Android中webview和js之间的交互

    1.android中利用webview调用网页上的js代码.Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为true,,然后通过loadUrl就可以直接进行调用,如下所示:mWebView.getSettings().setJavaScriptEnabled(true);mWebView.loadUrl("javascript:test()"); 2. 网页上调用android中java代码的方法在网页中

  • Android WebView使用方法详解 附js交互调用方法

    目前很多Android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性. 先说下WebView的一些优点: --可以直接显示和渲染web页面,直接显示网页 --webview可以直接用html文件(网络上或本地assets中)作布局 --和JavaScript交互调用 一.基本使用 首先layout中即为一个基本的简单控件: <WebView android:id="@+id/webView1

  • Android中使用开源框架eventbus3.0实现fragment之间的通信交互

    1.概述 在之前的博文中简单介绍过如何实现fragment之间的信息交互:<Android中Fragment与Activity之间的交互(两种实现方式)>,今天继续给大家介绍一种可以实现此效果的另外一种方式EventBus.(相比于handler,接口回调,bundle传参,这个简单好用到哭) EventBus是Android下高效的发布/订阅事件的消息总线.作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment.Activity.Service.线程

  • android中webview控件和javascript交互实例

    当我们要实现丰富的图文混排效果的时候,我们一般会使用webview,这是一个功能十分强大的的控件,来看看官方的解释: 复制代码 代码如下: A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit

  • Android基础之Fragment与Activity交互详解

    今天继续讲解Fragment组件的特性,主要是跟Activity的交互和生命周期的关系,我们前面已经说过Fragment是依赖于Activity的,而且生命周期也跟Activity绑定一起.下面我们看看Fragment跟Activity的关系. 1.为Activity创建事件回调方法在一些情况下, 你可能需要一个fragment与activity分享事件. 一个好的方法是在fragment中定义一个回调的interface, 并要求宿主activity实现它.当activity通过interfa

  • Android中WebView与Js交互的实现方法

    获取WebView对象 调用WebView对象的getSettings()方法,获取WebSettings对象 调用WebSettings对象的setJavaScriptEnabled()方法,设置js可用,参数:布尔值 在判断是否支持js的时候,不要用alert(),默认不起作用,可以先用document.write()测试 调用WebView对象的addJavascriptInterface(obj, interfaceName)方法,添加js接口,参数:Object对象,String接口名

随机推荐