Android 中通过 URI 实现 Web 页面调用本地 App

HTML 5 和本地 App 各有所长,现在公司的项目中也大量采用 HTML 5 做活动页面,这样本地代码和 HTML 5 的交互就是必须的。

说到 Android 端 Java 代码和 Web 端 HTML / JS 代码的交互,你可能最先想到的就是 WebView 的这两个方法:

  • loadUrl(String url);

  • addJavascriptInterface(Object object, String name);

前者可以实现 native 代码直接执行 JS 代码,而后者可以将 native 代码实现的接口暴露给 Web 页面,这样 Web 页面可以像调用普通 JS function 一样调用这个 native 接口。

但其实还有一种更直接的方式:那就是 URL,准确的说是 URI。

因为 shouldOverrideUrlLoading(WebView view, String url) 等回调方法本身就可以看作 Web 页面通过 URL 和本地应用进行数据交互,因此只要 Web 页面按照 URI 规范将数据传递过来,本地 App 就能在相关回调方法中调用相关 URI 的 API 解析数据,实现数据交互。

事实上,Android 很多内部组件正是通过 URI 传递数据的,特别是在调用系统服务和使用 ContentProvider 时经常用到。例如:

1     
2
3
4
5
6
7
8
//调用地图应用显示地理位置     
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW, uri);
startActivity(it);
//调用拨号程序
Uri uri = Uri.parse("tel:18616612345");
Intent it = new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);

假设 Web 页面采用一个超链接将数据以 URI 形式传递过来:

1     
<a href="MY_SCHEME:\\MY_HOST:MY_PORT\MY_PATH\?arg0=0&arg1=1">Open App</a>     

则 Android 端数据解析代码如下:

1     
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
webView.setWebViewClient(new WebViewClient(){     
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Uri uri=Uri.parse(url);
if(uri.getScheme().equals(MY_SCHEME)
&& uri.getHost().equals(MY_HOST)
&& uri.getPort() == MY_PORT
&& uri.getPath().equals(MY_PATH)){
String arg0 = uri.getQueryParameter("arg0");
String arg1 = uri.getQueryParameter("arg1");
//TODO
} else {
view.loadUrl(url);
}
return true;
}
});

以上是在 WebView 中加载 Web 页面的情况,如果要使外部浏览器中的 Web 页面也能够调用,则需要在 AndroidManifest.xml 中为指定 Activity 注册 intent-filter :

1     
2
3
4
5
6
7
8
9
10
11
12
13
<activity     
android:name=".activity.UriActivity"
android:exported="true">
<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:scheme="MY_SCHEME"
android:host="MY_HOST"
android:port="MY_PORT"
android:path="MY_PATH"/>
</intent-filter>
</activity>

对应的在处理 URI 的 Activity 中只需要调用 getIntent().getData() 方法即可读取 URI 数据。

你可能感兴趣的:(android,dev)