H5页面打开应用的几种方式

最近调研了在Android上打开H5页面的方式,本文做一下汇总。

Deep Link 就是在 Activity 中声明Intent Filters的方式告诉系统,该应用可以打开特定规则的内容。缺点是当系统中出现多个可以处理相同 Intent 的应用,需要用户进行手动选择,并且在一些 rom 下,用户可以勾选永远不用不适用我们的 app 打开。

使用方式

例如我们希望处理scheme 为deeplink,host 为applink.saymagic.cn的请求。

<activity
    android:name=".ItemListActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <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="deeplink" android:host="applink.saymagic.cn"/>
    </intent-filter>
</activity>
private fun parseIntent() {
    val uri = intent.data
    val scheme = uri.scheme
    val host = uri.host
    val path = uri.path
    val query = uri.query  
    Log.d("ParseIntent", "scheme = $scheme, host = $host, path = $path, query = $query")
}
adb shell am start -W -a android.intent.action.VIEW -d deeplink://applink.saymagic.cn

Activity成功启动.

因为使用Deep Links 有时会弹出一个对话框让用户选择是否在APP中打开。这会让用户困惑,对产品自身而言也会存在丢失用户的可能。为此, Android在Android 6.0 (API level 23) 及以后加入了App Links , 当用户点击对应的URI 时,会直接启动对应的APP,不会再有对话框出现。那系统是如何唯一确定一个 App的呢?

那就需要我们来证明一个 Uri 完全的归我们的应用所有。本例中applink.saymagic.cn域名归我们所有。我们希望当用户点击applink.saymagic.cn域名时可以跳转到我们的应用。

注:如果读者不方便构造 App Link 的环境,可以直接使用applink.saymagic.cn域名。这个域名下的数据不会被我删除,同时,对应完整的 app 和签名的地址在:https://coding.net/u/saymagic/p/AppLink。读者可以 clone 下来进行实验。

使用方式

与 Deep Link 一样,需要通过声明intent-filter:

<activity
    android:name=".ItemListActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
    
        <data android:scheme="http" android:host="applink.saymagic.cn"/>
        <data android:scheme="https" android:host="applink.saymagic.cn"/>
    </intent-filter>
</activity>
  1. 获取我们应用签名文件的sha256值,本例中签名文件是 app 目录下的 secret 文件,在根目录下执行:
keytool -list -v -keystore ./app/secret

密钥库口令为applink,执行结果:

image

红色框出的就是我们需要的信息

2.前往https://developers.google.com/digital-asset-links/tools/generator ,然后填写host,package,fingerprint: image

然后点击GENERATE STATEMENT,生成一段json字符串:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target" : { "namespace": "android_app", "package_name": "cn.saymagic.applink",
               "sha256_cert_fingerprints": ["3B:52:97:83:CD:92:7D:50:AA:70:94:62:B2:80:F3:AC:6D:B7:DE:E9:52:D5:7F:BD:5A:3B:8B:75:C1:A9:F0:94"] }
}]

将该 json 字符串拷贝下来,存放在名称为assetlinks.json的文件中。

assetlinks.json部署到applink.saymagic.cn/.well-known目录下。部署成功后,可以点击Test Statement按钮来验证:

image

使用adb shell dumpsys package d命令可以查看系统中支持 App Link 的应用,以我自己的手机为例,在安装前:

image

可以看到,大多数国外的应用还是对App Link都做了支持。国内的应用中,只看到淘宝声明了一系列的域名。

安装时,如果我们截包的话,会看到系统发出对https://applink.saymagic.cn/.well-known/assetlinks.json地址的请求:

image

安装结束后,再次使用adb shell dumpsys package d命令,就会看到我们的应用:

image

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "https:/applink.saymagic.cn"

应用成功启动

微信环境

大多数想要在 H5中打开应用都可能希望通过微信来引流。但奈何微信对 Depp LinkApp Link的支持都很差。网上很多文章提供的其它方式大多都已过时或者兼容性很差。如果您的应用支持App Link,可行的方案是引导用户选择使用浏览器打开,这时,就会直接跳转到我们的应用了。下面是在微信浏览器中访问https:/applink.saymagic.cn, 然后选择使用浏览器打开的效果:

image

如果应用支持的是Deep Link,使用浏览器打开时就会出现多个应用的选择窗口。这里不再展示。

但这里有个问题是,如果用户没有选择我们的应用或者用户压根没有安装我们的应用该怎么办呢?我的想法是,当一个 url 不是在微信环境下打开的话,服务器直接重定向到应用下载页面。这样,相当于用户在浏览器中打开下载页面。

那微信上有没有更好的导流方案呢?腾讯全家桶中有一个叫应用宝的应用,它提供了微下载功能。支持在应用不存在时跳转应用宝下载,应用存在时启动应用或者打开指定页面。详细信息见:http://wiki.open.qq.com/index.php?title=mobile/%E5%BA%94%E7%94%A8%E5%AE%9D%E5%BE%AE%E4%B8%8B%E8%BD%BD

综上,我这边绘制了一个H5页面内打开应用的一个相对完整的流程图:

image

其它说明

  1. Deep Link支持自定义 scheme,而App Link 只支持 https 与 http 协议
  2. 在Chrome 浏览器中点击一个网址,Chrome会优先查找是否含有支持打开此网址的App Link 应用。有的话会直接通过应用打开。而国内的浏览器大多都没看到这个特性

参考资料

Create Deep Links to App Content

Verify Android App Links

Handling Android App Links