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

android 调js方法并传值 android调用js方法_html

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。