Android JS启动APK
1.在移动设备访问m.alipay.com时,如果本地安装了支付宝客户端,则浏览器会调用本地客户端,没有安装则会跳转到下载页面,提示安装。刚好有这样的需求,就分析了下支付宝的实现。网上参考了其他人的实现,大部分都是关于APK和本地js交互,相关资料可以参考
2. APK启动流程
在启动APK时,系统会发出对应的intent,根据包名加intent来启动对应activity,activity如果存在对应的intent-filter则启动该应用,如果多个应用同时匹配,则会出现选择框让用户选择。
如下,启动demo.testjs应用的MainActivity
ActivityManager(313):START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0×10200000 cmp=demo.testjs/.MainActivity bnds=[13,76][127,211]} from pid 607
3.浏览器和本地APK的交互
Android manifest标签参考官方的开发指南
下面是UC的一个
设置
标签,可以拦截浏览器的请求,data可以增加过滤的条件。为了防止我们的启动APK scheme被其它应用拦截,尽量使用唯一的标识符如域名等。
在android应用中application的详细配置实例:
在MainActivity增加了
过滤器。
android:allowBackup=“true”
android:icon=“@drawable/ic_launcher”
android:label=“@string/app_name”
android:theme=“@style/AppTheme” >
android:name=“demo.testjs.MainActivity”
android:label=“@string/app_name” >
在web页面中加入如下测试代码
测试页面
//ios判断 if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i))
//判断是否是android设备浏览器 if (navigator.userAgent.match(/android/i)) {
if (navigator.userAgent.match(/android/i)) {
document.getElementById(‘openApp’).onclick = function(e) {
// 通过iframe的方式试图打开APP,如果能正常打开,会直接切换到APP,并自动阻止a标签的默认行为
// 否则打开a标签的href链接
var ifrSrc = ‘testjs://platformapi/startApp?name=tom&age=18′;
if (!ifrSrc) {
return;
}
var ifr = document.createElement(‘iframe’);
ifr.src = ifrSrc;
ifr.style.display = ‘none’;
document.body.appendChild(ifr);
setTimeout(function() {
document.body.removeChild(ifr);
}, 1000);
};
if (document.all) {
document.getElementById(‘openApp’).click();
}
// 其它浏览器
else {
var e = document.createEvent(“MouseEvents”);
e.initEvent(“click”, true, true);
document.getElementById(“openApp”).dispatchEvent(e);
}
}
新建web工程,加入测试页面。在手机浏览器上访问该页面,如果本地安装了对应的APK,则会启动APK,没有安装则跳转到对应的下载页面。以上web页面的脚本从支付宝手机客户端访问的页面截取的。(UC7.8版本的android浏览器可以下载保存网页)
4.获取浏览器传递的值
var ifrSrc = ‘testjs://platformapi/startApp?name=tom&age=18′;
实例中会提交name和age值
在activity中可以取到通过浏览器传递的值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Intent.ACTION_VIEW.equals(getIntent().getAction())){
Intent intent = getIntent();
String scheme = intent.getScheme();
Uri uri = intent.getData();
Log.e(tag, “scheme: “+scheme);
Log.e(tag, “path: “+uri.getPath());
Log.e(tag, “Host: “+uri.getHost());
Log.e(tag, “name: “+uri.getQueryParameter(“name”));
Log.e(tag, “age: “+uri.getQueryParameter(“age”));
}
}
可以取到scheme、 url、参数列表等信息
PS:浏览器实际上没有办法判断到本地是否安装了对应的APK文件,支付宝的web前端实现实际上了打开了一个隐藏的url地址,该url如果被本地apk拦截,则启动本地apk,如果url没有被拦截,则在1S后删除添加的’iframe’,跳转到下载页面。(不管url是否被本地拦截成功,1S后都会跳转下载页面,只不过拦截成功,本地APK启动页面会遮住浏览器的下载页面)
参考其它人用window.location 或 window.open标签也可以启动本地APK,但没有处理url跳转不存在的问题。(window.open未测试成功)
window.location实现方式:
AndroidManifest.xml配置
web页面添加
alert(“启动APK”);
window.location=”testjs://demo.testjs”;