Android和JavaScript互相调用分析

来源:互联网 发布:mac内存清理 编辑:程序博客网 时间:2024/06/07 20:14

代码在Android Studio1.4, android的6.0的模拟器上测试没有问题,Android中的java方法和js方法互相调用,根据有参和无参,可以分为四种情况,以下逐一通过代码分析。java方法和js方法互相调用的前提是需要设置settings.setJavaScriptEnabled(true);
这里写图片描述

Android方法调用JavaScript,有参数

在js中定义方法jsWithArgs(arg),android方法需要调用该方法必须通过webview的loadurl方法,loadurl参数格式必须是javascript:jsWithArgs(\"" + "content" + "\") 其中jsWithArgs是js中定义的方法,且传入js方法的参数必须用双引号引起来
index_js.html

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <Button android:id="@+id/btn"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_margin="20dp"        android:text="调用js方法" />    <WebView        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:id="@+id/myWebView" /></LinearLayout>

MainActivity.java

public class MainActivity extends Activity {    private WebView myWebView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWebView = (WebView) findViewById(R.id.myWebView);        Button btn = (Button)findViewById(R.id.btn);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                callJs(myWebView);            }        });        WebSettings settings = myWebView.getSettings();        settings.setJavaScriptEnabled(true);        myWebView.setWebChromeClient(new WebChromeClient() {});        myWebView.loadUrl("file:///android_asset/index_js.html");    }    private void callJs(WebView webView) {        String call1 = "javascript:jsWithArgs(\"" + "content" + "\")";        webView.loadUrl(call1);    }}

Android方法调用JavaScript,无参数

android方法调用js方法没有参数情形相对简单,无须传参,直接置空。如js中声明 jsWithNoArgs() ,使用是"javascript:jsWithNoArgs()"
index_js.html

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <Button android:id="@+id/btn"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_margin="20dp"        android:text="调用js方法" />    <WebView        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:id="@+id/myWebView" /></LinearLayout>

MainActivity.java

public class MainActivity extends Activity {    private WebView myWebView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWebView = (WebView) findViewById(R.id.myWebView);        Button btn = (Button)findViewById(R.id.btn);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                callJs(myWebView);            }        });        WebSettings settings = myWebView.getSettings();        settings.setJavaScriptEnabled(true);        myWebView.setWebChromeClient(new WebChromeClient() {});        myWebView.loadUrl("file:///android_asset/index_js.html");    }    private void callJs(WebView webView) {        String call1 = "javascript:jsWithNoArgs()";        webView.loadUrl(call1);    }}

JavaScript调用Android方法,有参数

  1. js调用android方法需要添加myWebView.addJavascriptInterface(new JsInteration(), "control"); ,表示添加js接口,其中类JsInteration自己声明,”control”可以认为是该类的别名,并且在onCreate方法前声明@SuppressLint("JavascriptInterface")
  2. js调用android方法需要定义一个公共类,并且声明一个供js调用的方法,为了让api>17的系统也能调用,方法需要声明@JavascriptInterface
  3. js中调用android方法格式为:control.showToast('显示Toast') ,其中control就是类的别名,’显示Toast’是传给android方法的参数。
    index_js.html
<html><input type="button" onclick="control.showToast('显示Toast')" value="点我出来一条消息" /></html>

activity_main.xml

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

MainActivity.java

public class MainActivity extends Activity {    private WebView myWebView;    @SuppressLint("JavascriptInterface")    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWebView = (WebView) findViewById(R.id.myWebView);        WebSettings settings = myWebView.getSettings();        settings.setJavaScriptEnabled(true);        myWebView.addJavascriptInterface(new JsInteration(), "control");        myWebView.setWebChromeClient(new WebChromeClient() {});        myWebView.loadUrl("file:///android_asset/index_js.html");    }    public class JsInteration {        @JavascriptInterface        public void showToast(String msg) {            Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();        }    }}

JavaScript调用Android方法,无参数

index_js.html

<html><input type="button" onclick="control.jump()" value="点我打开新的activity" /></html>

activity_main.xml

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

MainActivity.java

public class MainActivity extends Activity {    private WebView myWebView;    @SuppressLint("JavascriptInterface")    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWebView = (WebView) findViewById(R.id.myWebView);        WebSettings settings = myWebView.getSettings();        settings.setJavaScriptEnabled(true);        myWebView.addJavascriptInterface(new JsInteration(), "control");        myWebView.setWebChromeClient(new WebChromeClient() {});        myWebView.loadUrl("file:///android_asset/index_js.html");    }    public class JsInteration {        @JavascriptInterface        public void jump(){            Handler handler = new Handler();            handler.post(new Runnable() {                @Override                public void run() {                    startActivity(new Intent(MainActivity.this, IntentActivity.class));                }            });        }    }}

android方法调用js,而js调用android方法

这种情况跟android方法调用js类似,只是在js方法体中有一点不同:

<html><script type="text/javascript">    function toastMessage(message) {        window.control.toastMessage(message)    }</script></html>

window是html中的组件,control就是在java文件中声明对象时指定的“别名“,toastMessage是自定义类中的方法名。有这种方法就可以在java中获取用户在html中输入的值。

android方法传递json给js,在webview显示

这种情况跟android方法调用js类似,只是在js方法体中有一点不同:

public class MyObject {    @JavascriptInterface    public void init() {        webView.post(new Runnable() {            @Override            public void run() {                //调用客户端setContactInfo方法                webView.loadUrl("javascript:setContactInfo('" + getJsonStr() + "')");            }        });    }    @JavascriptInterface    public String getJsonStr() {        try {            JSONObject object1 = new JSONObject();            object1.put("id", 1);            object1.put("name", "张三");            object1.put("phone", "123456");            JSONObject object2 = new JSONObject();            object2.put("id", 2);            object2.put("name", "李四");            object2.put("phone", "456789");            JSONArray jsonArray = new JSONArray();            jsonArray.put(object1);            jsonArray.put(object2);            return jsonArray.toString();        } catch (JSONException e) {            e.printStackTrace();        }        return null;    }}
<!DOCTYPE HTML><html><head>    <title></title>    <script type="text/javascript">    function showtext() {        var a = document.getElementById("text").value;        window.myObject.getHtmlInput(a)        alert(a)    }    //data数据类型为字符串,字符串里面是数组,每一个数组元素为一个json对象,例如"[{id:1,name:'张三',phone:'135656461'},{id:2,name:'李四',phone:'1896561'}]"    function setContactInfo(data) {        var tableObj = document.getElementById("contact");        var jsonObjects = eval(data);   //通过eval方法处理得到json对象数组        for(var i=0; i<jsonObjects.length; i++) {            var jsonObj = jsonObjects[i];   //获取json对象            var tr = tableObj.insertRow(tableObj.rows.length);  //添加一行            //添加三列            var td1 = tr.insertCell(0);            var td2 = tr.insertCell(1);            var td3 = tr.insertCell(2);            td1.innerHTML = jsonObj.id;            td2.innerHTML = jsonObj.name;            td3.innerHTML = jsonObj.phone;        }    }    </script></head><!--onload="javascript:myObject.init()调用服务器端init方法--><body onload="javascript:myObject.init()"><input type="text" id="text" value=""><input type="button" onclick="myObject.showtxt()" value="显示输入框内容"/><table id="contact">    <tr>        <td>编号</td>        <td>姓名</td>        <td>电话</td>    </tr></table></body></html>

通过上述代码就可以把java方法中的json字符串传递给js方法,并在webview中显示

可能会出现的问题

  1. 如果在自己定义的JsInteration类中的方法做如下操作:
 @JavascriptInterface public void jump(){     Handler handler = new Handler();     handler.post(new Runnable() {         @Override         public void run() {             myWebView.loadUrl("javascript:jsWithNoArgs()");         }     }); }

则会出现这样的问题:
java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread.
正确的方法是用myWebView替换上述方法体中的handler.

        @JavascriptInterface        public void jump(){            myWebView.post(new Runnable() {                @Override                public void run() {                    myWebView.loadUrl("javascript:jsWithNoArgs()");                }            });        }

在stackoverflow中也有同样的问题,详见:
http://stackoverflow.com/questions/22607657/webview-methods-on-same-thread-error

  1. 如果使用过程中不小心把“别名“写错,不会调用相应的方法,log日志则会有提示:I/chromium: [INFO:CONSOLE(33)] "Uncaught ReferenceError: control is not defined", source: file:///android_asset/intent_js.html (33) 主意这个级别是info级别,所以最好不要把log级别调成error。

工程源码:android和js互相调用示例源码 CSDN下载

0 0
原创粉丝点击