js与android交互难点 == js唤起app
16lz
2021-01-26
最近写项目,遇到一个比较有意思的需求,涉及到公司所有前端工作,H5,Android,IOS
需求是这样的,
公司运营推广APP,对外分享一个链接,这个链接由h5写成,主要就是用来介绍APP的,蛋疼的是,在末尾加了两个按钮,一个用来下载IOS的app,一个用来下载android的app,重点来了啊,在点击按钮之前先判断手机中是否有该APP,有的话,直接打开,没有的话,就直接下载!
听着需求挺简单的,我当时一听也挺简单的,第一反应想的是:遍历,遍历检索app,识别包名,但是做着做着,就感觉不对了,为什么呢?回头仔细想想!因为啊,这个链接是有运维人员发的分享,这个分享我们压根就不知道会被发到什么地方去,有可能是qq好友,有可能是qq空间,微信,新浪,甚至各种社交平台,那么也就是说这个h5页面已经脱离了我们android的控制范围了,控制不了那还怎么与js交互啊,不能交互,还怎么通过android来进行遍历检索app啊,瞬间就懵逼了!!
苦苦思索啊,最后还是在百度的帮助下解决问题,不得不说,百度的强大啊!这里先给出两个链接吧:
https://blog.csdn.net/u010394015/article/details/51444744
https://blog.csdn.net/liulinghuidage/article/details/53906813
我就是通过这两篇文章解决的问题,有兴趣的可以先去了解一下!
这两篇文章中都提到了一个关键词:Scheme (方案),这个属性及其重要,他可以实现app的内部跳转,外部唤起,最重要的是js也可以通过他
仔细想想,仔细琢磨,惊然发现,app跳转页面竟然有多种方式,
最常见的一种:
Intent intent = new Intent(Entrust_CP_Activity.this, Entrust_SQ_Activity.class);
startActivityForResult(intent, DashApplication.CP_TO_SQ_req);
或者
Intent intent = new Intent(activity, Login_New_Activity.class);
startActivity(intent);
还有一种,也是常常被我们忽略的一种,就是通过Scheme来实现跳转:
PackageManager packageManager = getPackageManager();
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("xl://goods:8888/goodsDetail?goodsId=10011002"));
List activities = packageManager.queryIntentActivities(intent, 0);
boolean isValid = !activities.isEmpty();
if (isValid) {
startActivity(intent);
}
boolean isValid = !activities.isEmpty();
if (isValid) {
startActivity(intent);
}
其中 xl://goods:8888/goodsDetail?goodsId=10011002 是一种内部约定的协议,需要遵守它的顺序结构:在 https://blog.csdn.net/liulinghuidage/article/details/53906813 这个链接中有提到,讲的很详细,他是这样说的:
URL Scheme协议格式:
先来个完整的URL Scheme协议格式:
xl://goods:8888/goodsDetail?goodsId=10011002
通过上面的路径 Scheme、Host、port、path、query全部包含,基本上平时使用路径就是这样子的。
- xl代表该Scheme 协议名称
- goods代表Scheme作用于哪个地址域
- goodsDetail代表Scheme指定的页面
- goodsId代表传递的参数
- 8888代表该路径的端口号
URL Scheme如何使用:
1.)在AndroidManifest.xml中对标签增加
这样配置一番的话,是不是就有一种眼前一亮的感觉,如果还是持有怀疑态度的话,也不要紧,我们还有一套检测的代码:
4.)如何判断一个Scheme是否有效
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { PackageManager packageManager = getPackageManager(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("xl://goods:8888/goodsDetail?goodsId=10011002")); Listactivities = packageManager.queryIntentActivities(intent, 0); boolean isValid = !activities.isEmpty(); if (isValid) { startActivity(intent); } }});
将这段代码粘入同一model下的另一个activity的点击事件中,运行看看能不能调起那个被配置的activity,能的
话就说明配置没有问题,不能就说明配置错误,反正我试了,是没问题的。。。
以上说了那么多,还是没有具体的来解决我项目中的问题,不要急,好戏才刚开始~
当配置成功后,我们只需要将这个协议发给js人员就ok了,
这里再附上一份js的代码:
//打开(下载)Appfunction dian(){ var ua = window.navigator.userAgent.toLowerCase(); //微信 if(ua.match(/MicroMessenger/i) == 'micromessenger'){ window.location.href='downLoadForPhone'; }else{//非微信浏览器 if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i)) { var loadDateTime = new Date(); window.setTimeout(function() { var timeOutDateTime = new Date(); if (timeOutDateTime - loadDateTime < 5000) { window.location = "";//ios下载地址 } else { window.close(); } },2000); window.location = "schema://"; }else if (navigator.userAgent.match(/android/i)) { var state = null; try { window.location = 'xl://goods:8888/goodsDetail?goodsId=10011002'; // 这个协议可以随便换 setTimeout(function(){ window.location= ""; //android下载地址 },500); } catch(e) {} }}
最后将这份js代码打上服务器版本,用浏览器运行一下,完美收工!!
这里提醒一下,android人员不要自作聪明,以为将h5页面放到本地,通过webview运行就能跑通,明确的告诉你,不可能,跑不通,因为我试过!!具体为什么,还在研究中!百度上倒是给了一个说法,好像是要将apk以及h5放在同一服务器下的,具体怎么弄的,我也没实践过,留着以后补吧~~~
更多相关文章
- [置顶] 我的Android进阶之旅------>Android基于HTTP协议的多线程
- Android(安卓)Studio 开发配置(一)
- macOS中配置Flutter开发环境(使用AndroidStudio开发)傻瓜版教程
- Android中遍历View的几种方式
- android在更新ADT以后报java.lang.NoClassDefFound的解决办法
- Android查找未用类和方法
- Android系统搜索对话框(浮动搜索框)的使用
- android adb的配置以及 java环境变量的配置
- Android(安卓)Studio的一些配置(去拼写检查、自动import、大小写