许久没有写博客了,最近有个H5启动APP原生页面的需求,中间遇上一些坑,看了些网上的实现方案,特意来总结下

一、需要判断客户端的平台以及是否在微信浏览器中访问

1、客户端判断

在启动APP时,Android和IOS系统处理的方式是不一样的,Android这边由于开放,可以在浏览器中通过<a>标签以及meta标签的方式,让浏览器app获取手机打开应用的权限进而启动APP。

而在IOS这边,IOS9以后的系统,则可以在APP开发过程中加入配置和逻辑代码编写,系统在浏览器即将访问到某个域名前就把这个域名对应的APP打开,这个有点闪,封闭还是有封闭的好处。

所以首先要在客户端判断,是Android系统还是IOS系统,判断代码如下

function isInIos(){
var userAgentInfo = navigator.userAgent ,
Agents = ["iPhone" , "iPad", "iPod"];
for(var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
return true;
}
}
return false;
}

2、是否在微信内置浏览器中

无论是在哪个平台的客户端Android/IOS,在微信的平台上访问都有一个问题,那就是无法启动客户端,这是微信为了安全性考虑的限制,android这边屏蔽schema协议,除非公司是微信的伙伴加入了白名单才能

使用,IOS系统可以去访问app对应appstore的下载页,但是微信经常屏蔽appstore的这个网址,进而访问不到。比较方便的做法就是在微信浏览器中,无论是IOS还是android都去应用宝的下载(IOS 这边最后会到

appstore中)页面打开。我这边的需求是提示用户点击“...”用默认浏览器打开。

判断是否是在微信中,代码如下:

function isInWx(){
var agent = window.navigator.userAgent.toLowerCase();
return agent.match(/MicroMessenger/i) == 'micromessenger';
}

二、原理

首先无论是andorid还是IOS端,在浏览器中通过JS都是无法判断该手机是否装有某APP的,即使这个浏览器有权限读取手机应用列表,也没有一个固定的对外API让咱们进行查询。而H5启动APP本质上是通过

URL scheme打开APP,一个APP可以设置一个或多个打开自己的URL scheme,浏览器去访问某一个APP的URL scheme,然后若系统安装有这个APP,则会请求权限去打开这个APP。其实也算是浏览器app

打开另一个app,iOS就可以使用 UIApplication 的 canOpenUrl 方法来检测URL scheme 是否能打开对应的APP,而android也是类似的方式。当然如果JS跳转URL scheme没有反应,也意味着这个手机没有

装这个app。

三、android平台

首先编辑AndroidManifest.xml,主要是增加第二个<intent-filter>

<activity android:name=".activity.LoadingActivity"
android:label="${APP_NAME}"
android:screenOrientation="portrait"
android:theme="@style/FirstActivityTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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="android"
android:scheme="wushang" />
</intent-filter>
</activity>

比如此处wushang就是scheme,这个最好是app的唯一标识符,要不然在H5唤醒时,会出现一个选择框,选择启动哪一个APP。而host表示启动该页面,其实这个更应该用com.android.sky这样的包名来替代更好。

这样的情况完整的URL就是wushang://android?data=sky,后面是参数传递。在Activity中可以用如下代码获取参数

public void onCreate(Bundle savedInstanceState) {
Uri uridata = this.getIntent().getData();
String mydata = uridata.getQueryParameter("data");
}

之后在进行字符串截取还是什么鬼的都随意啦。

接下来来谈谈前端代码,这里有两种情况

1、页面在刷新进入时,请求权限唤起APP

这个比较简单,就只用在页面的顶部head中加入meta标签即可

<meta http-equiv="refresh" content="0;url=wushang://android?data=sky">

这个标注当页面刷新即去访问这个链接,进而启动APP。但是存在一个问题,如果是苹果系统的Safari浏览器的话,访问有这个meta的头,会给出错误提示,所以这个头部可以在后端进行页面渲染时通过客户端的

总类在加上去。

2、通过点击事件唤起APP

最简单的办法当然是直接使用a标签,如下

<a href="wushang://android">open Android app</a>

但是在实际使用时,是需要对客户端的平台类型还有是否在微信内置浏览器中进行判断的,所以这样的做法肯定是不行的。

接下来谈谈在开发过程中,遇到的一个问题,记录下。因为这边移动端使用的工具库库是zepto,采用的点击事件是tap,但是在用tap进行处理是经常要点很多下,才能唤起APP

<script type="text/javascript">
$('#go').tap(function(){
window.location.href = "wushang://android";
});
</script>

具体原因不知,可能是tap事件采用的是轻点触碰。然后摸索了下,才用click事件,或者直接在a标签上标注处理函数就没有这问题

<a id="go" >
open Android app
</a>
<a href="javascript:startApp()">
open
</a>
<script src="../res/lib/zepto.min.js"></script>
<script src="../res/lib/public.js"></script>
<script>
$('#go').click(function () {
if(publicFun.isIos()){
alert('it is IOS')
}else{
window.location.href = "wushang://android";
}
}); function startApp(){
if(publicFun.isIos()){
alert('it is IOS')
}else{
window.location.href = "wushang://android";
}
}
</script>

所以决定以后遇到这类问题,就用这两种方式了。下面是实际的处理函数

 window.startApp = function(){     //启动APP
if(publicFun.isInWx()){ //微信中
alert("请在浏览器中打开");
}else{ //非微信中
if(publicFun.isIos()){    //IOS系统,直接去itunes中,既可以下载也可以打开
window.location.href = "https://itunes.apple.com/cn/app/[name]/id[id]";
}else{ //android系统,通过定时器的方式,判断是否安装有APP
var hasApp = true , t = 1000;
setTimeout(function () { //没有安装APP则跳转至应用宝下载,延时时间设置为2秒
if(!hasApp) window.location.href = "http://a.app.qq.com/o/simple.jsp?pkgname=[name]";
} , 2000);
var t1 = Date.now();
window.location.href = "wushang://android";
setTimeout(function () { //t的时间就是出发APP启动的时间,若APP启动了,再次返回页面时t2这行代码执行,hasApp即为true。反之若APP没有启动即为false
var t2 = Date.now();
hasApp = !(!t1 || t2 - t1 < t + 150);
} , t);
}
}

其实有个非常简单的办法,就是直接跳转应用宝。无论是在android还是IOS,以及微信非微信。应用宝的下载页面都有下载和打开两个功能(如果是在IOS平台,它是通过连接app store的方式)

四、IOS平台

针对ios9及以上的打不开问题,实际上ios9提供了更好的解决方案————通用链接。

这是iOS9推出的一项功能,如果你的应用支持Universal Links(通用链接),那么就能够方便的通过传统的HTTP链接来启动APP(如果iOS设备上已经安装了你的app,不需要额外做任何判断等),或者打开网页(iOS设备上没有安装你的app)。或许可以更简单点来说明,在iOS9之前,对于从各种从浏览器,Safari、UIWebView或者 WKWebView中唤醒APP的需求,我们通常只能使用scheme。

以上来自网上关于通用链接的介绍,对于前端简单点讲就是你访问一个http的url,如果这个url带有你提交给开发平台的配置文件中匹配规则的内容,ios系统会去尝试打开你的app,如果打不开,系统就会在浏览器中转向你要访问的链接。很好的一个属性,因为通过这个属性在ios9上我们能够绕过微信的拦截从而打开app。

所以上面的点击事件,仅仅是去访问app store,因为若app已安装,在浏览器访问时,就已经去到APP中了。

这些都是IOS配置上的东西,就不多写了。至于传参,以及页面定向,其实也就是相当于在UIWebView中获取当前连接的URL,然后进行字符串拆分以及校验,即可判断去哪个页,以及获取参数值。

h5启动原生APP总结的更多相关文章

  1. H5和原生APP之间的区别

    最近项目中因各种客观因素,移动端都是默认用的纯H5 APP,感受最深的就是各种坑啊,好大的坑啊.产品上线后,带着各种坑后的总结原因方发现很多人都说纯H5 APP一次编写就能支持android和IOS两 ...

  2. h5 与原生 app 交互的原理

    现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次就来捋 ...

  3. 客户端相关知识学习(二)之h5与原生app交互的原理

    前言 现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次 ...

  4. H5、原生app、混合开发三者比较

    一.概念 a) H5:即Html5,接触过互联网的都知道html,所以很明显h5是html的第5次重大修改的一项超文本标记语言的标准协议. b) 原生:使用原生制作APP(Native app),即在 ...

  5. uni-app强大的前端框架,h5,原生app(两大系统),微信小程序

    最近发现一款强大的前端框架,它叫uni-app 这是一款通用的框架可以打包app,h5,微信小程序, 说说要弄这个工具需要会那些技能吧, 要熟悉vue,微信小程序.这样这个框架用的就是很快上手了 模块 ...

  6. OVGap iOS与Javascript交互(H5与原生APP交互)

    源代码:https://github.com/windshg/OVGap OVGap:一个轻量级的类库,能够让iOS应用和远程网页的 Javascript 代码进行通信,也就是说,远程的 Javasc ...

  7. iOS原生App与H5页面交互笔记

    文/MikeZhangpy(简书作者)原文链接:http://www.jianshu.com/p/4ed3e5ed99c6著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 最近在做一个项 ...

  8. APP中的 H5和原生页面如何分辨、何时使用

    一.APP内嵌H5和原生的区别 1.原生的页面运行速度快,比较流畅. H5页面相对原生的运行性能低,特别是一些动画效果有明显卡顿. 2.H5页面的很多交互都没有原生的好,比如弹层.输入时候的页面滑动 ...

  9. 移动web、webApp、混合APP、原生APP、androd H5混合开发 当无网络下,android怎么加载H5界面

    PhoneGap是一个采用HTML,CSS和JavaScript的技术,创建移动跨平台移动应用程序的快速开发平台.它使开发者能够在网页中调用IOS,Android,Palm,Symbian,WP7,W ...

随机推荐

  1. 简明python教程七----面向对象的编程

    根据操作数据的函数或语句块来设计程序的,被称为面向过程的编程. 把数据和功能结合起来,用称为对象的东西包裹起来的组织程序的方法,称为面向对象的编程理念. 类和对象是面向对象编程的两个主要方面.类创建一 ...

  2. laravel command命令行

    生成类 为了创建一个新命令,你可以使用Artisan中的 command:make 命令生成一个骨架作为你的起点: 生成一个命令类 php artisan command:make FooComman ...

  3. Django-model基础(Day69)

    阅读目录 ORM 创建表(建立模型) 添加表记录 查询表记录 F查询与Q查询 修改表记录 删除表记录 数据库回顾:http://www.cnblogs.com/yuanchenqi/articles/ ...

  4. 基本运算符与流程控制(Day5)

    一  运算符 1.算数运算 2.比较运算 3.赋值运算 4.逻辑运算 and注解: 在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值:而是,返回它们实际 ...

  5. PHP iconv函数

    最近在做一个程序,需要用到iconv函数把抓取来过的utf-8编码的页面转成gb2312, 发现只有用iconv函数把抓取过来的数据一转码数据就会无缘无故的少一些. iconv函数库能够完成各种字符集 ...

  6. Codeforces Round #396 (Div. 2) C. Mahmoud and a Message

    地址:http://codeforces.com/contest/766/problem/C 题目: C. Mahmoud and a Message time limit per test 2 se ...

  7. SQL 函数以及SQL 编程

    1.数学函数:操作一个数据,返回一个结果 --去上限: ceiling ☆select --去下限:floor ☆select floor(price) from car --ABS 绝对值 --PI ...

  8. RPC数据通信

    RPC全称为Remote Procedure Call,翻译过来为“远程过程调用”.目前,主流的平台中都支持各种远程调用技术,以满足分布式系统架构中不同的系统之间的远程通信和相互调用.远程调用的应用场 ...

  9. C#求百分比

    public string integralpercentage; integralpercentage = ((double)user.Credits / integralmax).ToString ...

  10. java 标识符

    java 所有的组成部分都需要名字.类名.变量名以及方法名都被称为标识符. java 标识符 1.所有的标识符都应该以字母(A-Z或者a-z),特殊符号(美元符$).或者下划线(_)开始 2.首字母之 ...