web页面判断是否安装某app,从web启动app应用



web页面判断手机里是否安转应用的原理就是:首先试着打开手机端某个app的本地协议;如果超时就转到app下载页,下载该app。



URL scheme 的作用

客户端应用可以向操作系统注册一个 URL scheme,该 scheme 用于从浏览器或其他应用中启动本应用。通过指定的 URL 字段,可以让应用在被调起后直接打开某些特定页面,比如车辆详情页、订单详情页、消息通知页、促销广告页等等。也可以执行某些指定动作,如订单支付等。也可以在应用内通过 html 页来直接调用显示 app 内的某个页面。


URL scheme 的格式



客户端自定义的 URL 作为从一个应用调用另一个的基础,遵循 RFC 1808 (Relative Uniform Resource Locators) 标准。这跟我们常见的网页内容 URL 格式一样。


一个普通的 URL 分为几个部分,scheme、host、relativePath、query。


比如:http://www.baidu.com/s?rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709,这个URL中,scheme 为 http,host 为www.baidu.com,relativePath 为 /s,query 为 rsv_bp=1&rsv_spt=1&wd=NSurl&inputT=2709。


一个应用中使用的 URL 例子(该 URL 会调起车辆详情页):uumobile://mobile/carDetail?car_id=123456,其中 scheme 为 uumobile,host 为mobile,relativePath 为 /carDetail,query 为 car_id=123456。


Scheme定义Activity


1)在androidmanifest.xml中定义scheme

<!-- 启动页 -->
<activity
android:name="com.qiyuan.congmingtou.activity.SplashActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>
<!-- 要想在别的App上能成功调起App,必须添加intent过滤器 -->
<intent-filter>
<!-- 协议部分,随便设置 -->
<data android:scheme="cmt" android:host="splash"/>
<!-- 下面这几行也必须得设置 -->
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>



这样我们便定义了能够接受scheme请求的activity实例,当网页或者是android代码发送这种规则scheme的请求的时候就能够吊起SplashActivity了。

2.网页中Html代码和js代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>从web启动app</title>
<script src="/h5/Js/jquery-1.11.0.min.js" type="text/javascript"></script>

<!--禁止屏幕缩放-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.2,user-scalable=no" />

</head>
<body>
<div id="newscontent" style="text-align: center;">
<p>
<a id="webtoapp" href="">启动app</a>
</p>
<br>
<p>
<a id="webtoapp2" href="">启动app跳转到新闻 39066</a>
</p>
<br>
<p>
<a id="webtoapp3" href="">启动app跳转到论坛 104960</a>
</p>
<br>
</div>

<script>
(function() {
var ua = navigator.userAgent.toLowerCase();
var t;
var config = {
/*scheme:必须*/
scheme_IOS: 'gdrs://test.com/index',
scheme_Adr: 'gdrs://test.com/index',
download_url: 'http://a.app.qq.com/o/simple.jsp?pkgname=aa.bbxxx',
timeout: 3000
};

function openclient() {
var startTime = Date.now();

var ifr = document.createElement('iframe');
ifr.src = ua.indexOf('os') > 0 ? config.scheme_IOS : config.scheme_Adr;
ifr.style.display = 'none';
document.body.appendChild(ifr);

var t = setTimeout(function() {
var endTime = Date.now();

if (!startTime || endTime - startTime < config.timeout + 200) {
window.location = config.download_url;
} else {

}
}, config.timeout);

window.onblur = function() {
clearTimeout(t);
}
}

window.addEventListener("DOMContentLoaded", function() {
document.getElementById("webtoapp").addEventListener('click', openclient, false);
}, false);
})()
</script>

<script>
(function() {
var ua = navigator.userAgent.toLowerCase();
var t;
var config2 = {
/*scheme:必须*/
scheme_IOS: 'gdrs://test.com/news?id=39066',
scheme_Adr: 'gdrs://test.com/news?id=39066',
download_url: 'http://a.app.qq.com/o/simple.jsp?pkgname=aa.bbxxx',
timeout: 3000
};

function openclient2() {
var startTime = Date.now();

var ifr = document.createElement('iframe');
ifr.src = ua.indexOf('os') > 0 ? config2.scheme_IOS : config2.scheme_Adr;
ifr.style.display = 'none';
document.body.appendChild(ifr);

var t = setTimeout(function() {
var endTime = Date.now();

if (!startTime || endTime - startTime < config2.timeout + 200) {
window.location = config2.download_url;
} else {

}
}, config2.timeout);

window.onblur = function() {
clearTimeout(t);
}
}

window.addEventListener("DOMContentLoaded", function() {
document.getElementById("webtoapp2").addEventListener('click', openclient2, false);

}, false);
})()
</script>

<script>
(function () {
var ua = navigator.userAgent.toLowerCase();
var t;
var config3 = {
/*scheme:必须*/
scheme_IOS: 'gdrs://test.com/talk?id=104960',
scheme_Adr: 'gdrs://test.com/talk?id=104960',
download_url: 'http://a.app.qq.com/o/simple.jsp?pkgname=aa.bbxxx',
timeout: 3000
};

function openclient3() {
var startTime = Date.now();

var ifr = document.createElement('iframe');
ifr.src = ua.indexOf('os') > 0 ? config3.scheme_IOS : config3.scheme_Adr;
ifr.style.display = 'none';
document.body.appendChild(ifr);

var t = setTimeout(function () {
var endTime = Date.now();

if (!startTime || endTime - startTime < config3.timeout + 200) {
window.location = config3.download_url;
} else {

}
}, config3.timeout);

window.onblur = function () {
clearTimeout(t);
}
}
window.addEventListener("DOMContentLoaded", function () {
document.getElementById("webtoapp3").addEventListener('click', openclient3, false);

}, false);
})()
</script>
</body>
</html>



  如果我们要用于实现对scheme的解析,然后做出相应的动作,比如请求scheme跳转登录页面,要在SplashActivity中做写相应的代码:


public class SplashActivity extends Activity{
public Activity mContext = null;

public void onCreate(Bundle b)
{
super.onCreate(b);
mContext = this;
Uri uri = getIntent().getData();
if (uri != null)
{
List<String> pathSegments = uri.getPathSegments();
String uriQuery = uri.getQuery();
Intent intent;
if (pathSegments != null && pathSegments.size() > 0) {
// 解析SCHEME
if (someif) {
dosomething();
}
else {
// 若解析不到SCHEME,则关闭NativeAppActivity;
finish();
}
} else {
finish();
}
} else {
finish();
}
}
}


这里简单说一下,我们可以通过Intent对象获取调用的scheme的host等信息



this.getIntent().getScheme();//获得Scheme名称  


this.getIntent().getDataString();//获得Uri全部路径 



通过服务器下发跳转路径跳转相应页面



startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("uumobile://yongche/123123123")));



这里的”uumobile://yongche/123123123”就是服务器下发的跳转路径,当我们执行startActivity的时候就会调起SpalshActivity,然后我们通过在SpalshActivity解析scheme的内容,跳转相应的页面



总结: 

android中的scheme是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面; 


通过scheme协议,服务器可以定制化告诉App跳转那个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面等。


问题: 但如果是在微信浏览器打开这个,android目前启动app没问题,跳转到指定activity不行,ios则完全不行,但如果是在其它浏览器打开则没有问题;