WebView是Android的一个常用控件,下面介绍下JS和Java的沟通机制
通过一个简单的Demo介绍这个机制
布局就是一个简单的WebView, 但是每个连接都加了js方法
html中的js
这个html中,使用类似javascript:Android.callPhone("15633336666")
的进行调用Android中的Java方法,暂时放在assets目录下了
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
</head>
<body>
<font color="#0099FF" size="5">Js Demo</font> </p>
<p><a href='javascript:Android.callPhone("15633336666")'>telephone: 15633336666</a></p>
<p><a href='javascript:Android.callAppByUri("hebust://com.edu.hebust.handlerthread.mainactivity")'>OtherAPP called by Uri.</a></p>
<p><a href='javascript:Android.callAppByComponent("cn.edu.hebust.handlerthread","cn.edu.hebust.handlerthread.MainActivity")'>OtherAPP called by Component.</a></p>
<table id="table">
</table>
</p></p></p></p></p>
<font color="#233fF1" size="2">
Js回调上面的Java方法,实现JS和Java的相互调用
<b>javascript:Android</b> 是指Js需要触发的事件,对java来说是JsBridge的名称</p>
</font>
</body>
</html>
WebView配置
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LOGGER";
private WebView mWvWeb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWvWeb = (WebView) findViewById(R.id.id_wv_web);
WebSettings settings = mWvWeb.getSettings();
settings.setJavaScriptEnabled(true);
mWvWeb.loadUrl("file:///android_asset/test.html"); // 引用assets目录下的html
// 添加JSBridge
mWvWeb.addJavascriptInterface(new MyJsInterface(this), "Android"); // 这里添加了JSBridge,Android是js中的事件名
}
}
JSBridge的配置
使用反射调用这些java方法,但是为了安全性必须加上注解
/**
* Created by shixi_tianrui1 on 16-11-20.
* Js回调的java方法
*/
public class MyJsInterface {
private static final String TAG = "LOGGER";
private Context mContext;
public MyJsInterface(Context context) {
mContext = context;
}
// 呼起拨号界面
// 'JavascriptInterface'注解的方法必须设置为'public'
@JavascriptInterface
public void callPhone(final String talePhone) {
if (TextUtils.isEmpty(talePhone)) {
return;
}
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + talePhone));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
Log.d(TAG, "callPhone: " + talePhone);
}
// 呼起第三方APP
@JavascriptInterface
public void callAppByUri(final String uri) {
if (TextUtils.isEmpty(uri)) {
return;
}
Log.d(TAG, "callAPP: uri " + uri);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse(uri));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
@JavascriptInterface
public void callAppByComponent(final String pkg, final String clz) {
Log.d(TAG, "callAppByComponent: pkg = " + pkg + " clz = " + clz);
if (TextUtils.isEmpty(pkg) || TextUtils.isEmpty(clz)) {
return;
}
ComponentName comp = new ComponentName(pkg, clz);
Intent intent = new Intent();
intent.setComponent(comp);
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
点击第二和第三个连接会跳转到其他Activity,所以对其他Activity进行配置
其他APP manifest文件中
配置相应的<Intent-Filter>
即可
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!--通过Uri点击呼起-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="com.edu.hebust.handlerthread.mainactivity"
android:scheme="hebust" />
</intent-filter>
<!--通过ComponentName呼起-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>