Android中如何实现WebView与JavaScript的相互调用

这一篇将讲解WebView中JavaScript与java相互调用的一个例子。

首先说明一重要代码的情况:

android中的关键代码:

webview.getSettings().setJavaScriptEnabled(true);
webview.addJavascriptInterface(object,"name"); //把Name="name"的对象添加到object中。object如果是this,就是window.name
webview.loadUrl("file:///android_asset/index.html"); //注意这个资源的位置放在assets文件夹下。

js或html中调用android中方法代码:

js中使用 window.name.java中的方法();

android中调用js的function方法:

Callfunction(){
webview.loadUrl("javascript: function ()");

需要注意的是:很多数据类型js不认识,最好是在android那边封装好,提供必要的方法接口。比如传到js中的list,在js中是没办法去得到里面的元素的。

addJavascriptInterface:addJavascriptInterface方法中要绑定的Java对象及方法要运行在另外的线程中,不能运行在构造他的线程中,也就是说不能运行在当前的activity线程中,就是把这个方法绑定到页面中,js也可以调用。

文档中的解释:

Use this function to bind an object to Javascript so that the methods can be accessed from Javascript.

The Java object that is bound runs in another thread and not in the thread that it was constructed in.

下面给出具体的测试代码:

1、Activity 代码

public class TestWebView extends Activity {
    private WebView mWebView;
    private List<String> list;
    private int mkeyCode;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mWebView = (WebView) findViewById(R.id.htmlview);
        initData();
        WebSettings webSettings = mWebView.getSettings();
        // 是否允许在webview中执行javascript
        webSettings.setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(this, "javatojs");
        //加载网页
        mWebView.loadUrl("file:///android_asset/index.html");
    }
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        mkeyCode = keyCode;
        Log.i("AA","keyCode="+keyCode);
        mWebView.loadUrl("javascript: OnKeyUp()");
        return super.onKeyUp(keyCode, event);
    }
    public int getKeyCode(){
        return mkeyCode;
    }
    void initData() {
        list = new ArrayList<String>();
        for (int i = 0; i < 5; i++) {
            list.add("我是List中的第" + (i + 1) + "行");
        }
    }
    /**
     * 该方法将在js脚本中,通过window.javatojs.....()进行调用
     *
     * @return
     */
    public Object getObject(int index) {
        Log.i("A","getObject");    
        return list.get(index);
    }
    public int getSize() {
        Log.i("A","getSize");
        return list.size();
    }
    public void Callfunction() {
        Log.i("A","Callfunction");
        mWebView.loadUrl("javascript: GetList()");
    }
    public void printStr(String str){
        Log.i("A","GetList:" + str);
    }  
}

2、js 代码 index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>demotitle></title>
<script language="javascript">
function GetList(){
    var i=window.javatojs.getSize();
    for(var n=0;n<i;n++){
        var jsdata= window.javatojs.getObject(n);//拿到activity里面的属性javadata
        window.javatojs.printStr("test");
    }
}
function OnKeyUp() {
    var keycode = window.javatojs.getKeyCode();
    window.javatojs.printStr(keycode);
}
</script>
</head>
 <body style="background-color:#000;">
  <table width="400" align="center"><tr><td>
  <p> </p>
  <p>
<table width="400" align="center">
<div id="output" >test</div>
    <input type="submit" value="buttons"
    onclick="document.getElementById('output').innerHTML=window.javatojs.Callfunction()"/>
  <br>
  </p>
  </td></tr></table>
</body>
</html>

以上代码主要测试js与java相互调用,而由于按键这种系统事件被webview截获掉,有如下两种方式进行处理

1、把方向键的流程改成:先传给webcore,假如没处理,再在webview里面处理,这个需要修改webview.java代码

2、直接应用搞定,java捕获按键,然后调js函数,上面代码就是使用这种方法。

测试结果如下: 点击buttons按钮:

I/A       ( 4990): Callfunction

I/A       ( 4990): getSize

I/A       ( 4990): getObject

I/A       ( 4990): GetList:test

I/A       ( 4990): getObject

I/A       ( 4990): GetList:test

I/A       ( 4990): getObject

I/A       ( 4990): GetList:test

I/A       ( 4990): getObject

I/A       ( 4990): GetList:test

I/A       ( 4990): getObject

I/A       ( 4990): GetList:test

you press KEY_RIGHT

I/AA      ( 4990): keyCode=22

I/A       ( 4990): GetList:22

you press KEY_UP

I/AA      ( 4990): keyCode=19

I/A       ( 4990): GetList:19

you press KEY_DOWN

I/AA      ( 4990): keyCode=20

I/A       ( 4990): GetList:20

you press KEY_LEFT

I/AA      ( 4990): keyCode=21

I/A       ( 4990): GetList:21

这里为何使用这种方式,是因为对于上下左右及确定这种功能键被webview截取掉了,无法传递到webcore中,而只能重载OnKeyDown/OnKeyUp方法,再由js调用java方法来获取得。

对于数字键的处理可以直接在js中进行处理:

logcat中会有明显的打印,对于这些键没有截掉,所以可以直接获取得到:

D/webcore ( 4990): proc key: code=12

D/webcore ( 4990): proc key: nativeKey return false

D/webcore ( 4990): proc key: nativeKey return true

js代码可以如此编写:

<script language="JavaScript">
  document.onkeypress = grab_keypress_event;
  document.onirkeypress = grab_irkeypress_event;
  document.onsystemevent = grab_system_event;
  document.onkeydown = grab_keydown_event;
  document.onkeyup = grab_keyup_event;
  function init()
  {
      document.getElementById("txt_keypress").innerHTML = "";
      document.getElementById("txt_irkey").innerHTML= "";
      document.getElementById("txt_systemevent").innerHTML="";
      document.getElementById("txt_keydown").innerHTML="";
      document.getElementById("txt_keyup").innerHTML="";
  }
  function grab_keypress_event(event)
  {
      var keycode = event.keyCode;
      document.getElementById("txt_keypress").innerHTML=keycode;
  }
  function grab_irkeypress_event(event)
  {
      var keycode = event.keyCode;
      document.getElementById("txt_irkey").innerHTML=keycode;
  }
  function grab_system_event(event)
  {
      var keycode = event.which;
      document.getElementById("txt_systemevent").innerHTML=keycode;
  }
  function grab_keydown_event(event)
  {
      var keycode = event.keyCode;
      var type = event.type;
      var mod = event.modifiers;
      document.getElementById("txt_keydown").innerHTML=keycode;
  }
  function grab_keyup_event(event)
  {
      var keycode = event.keyCode;
      document.getElementById("txt_keyup").innerHTML=keycode;
  }
</script>