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方法,有参数
- js调用android方法需要添加
myWebView.addJavascriptInterface(new JsInteration(), "control");
,表示添加js接口,其中类JsInteration自己声明,”control”可以认为是该类的别名,并且在onCreate方法前声明@SuppressLint("JavascriptInterface")
。 - js调用android方法需要定义一个公共类,并且声明一个供js调用的方法,为了让api>17的系统也能调用,方法需要声明
@JavascriptInterface
。 - 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中显示
可能会出现的问题
- 如果在自己定义的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
- 如果使用过程中不小心把“别名“写错,不会调用相应的方法,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下载
- Android和JavaScript互相调用分析
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- Android和JavaScript互相调用
- vbscript和javascript互相调用
- flex 和javascript互相调用
- JsBridge实现JavaScript和Android的互相调用
- Android WebView中javascript和java的互相调用
- 关于android和javascript函数的互相调用
- Android中WebView和JavaScript(JS)的互相调用
- Android WebView 和 javaScript的互相调用(一)
- Android WebView 和 javaScript的互相调用(二)
- Android WebView 和 javaScript的互相调用(三)
- Android中java和javascript方法的互相调用示例
- 我和敏捷开发的故事--敏捷角色-SM
- 触摸事件
- JSONObject 好坑啊
- 360笔试题回忆版
- Android基础学习之BroadcastRceiver(通信机制)广播
- Android和JavaScript互相调用分析
- 在积累中成长-记2015周年总结
- hdoj4617Weapon【空间直线间的距离】
- ubuntu下终端(gnome-terminal)快捷键基本使用
- java中内部类的使用
- 代理与回调的异同
- 迭代器模式
- WCF 之 AJax前台调用WCF服务
- 多线程的基本理解