为解决通过一个链接直接访问到App应用里的内容,就有了deep link,最常见的用处就是点击h5上的按钮能直接调起App并能跳转到对应的功能页面,或者是扫码调起App并自动领奖励或者签到之类。安卓和iOS都有deep link的支持。
因为deep link是非常开放的设计,理论上任意一个uri格式的字符串都行,比如xxx://yyy,当然设计者是建议各自应用设计自己的uri,不要互相干扰,比如你是微信应用,就设计weixin://打头的字符串,你是支付宝就设计alipay://打头的字符串,但实际上一方面App开发者有可能无意用到了雷同的scheme前缀,比如应用市场App都以market://打头,再或者有恶意开发者故意使用其他App的deep link,导致用户会出现误操作。当同一个链接会有多个App响应时,系统会默认弹出列表选项,让用户选择是要用哪个App打开,这也让用户的使用变得麻烦和不安全,为此就产生了App link,在iOS上专门叫做Universal link。
App link只在deep link之上限定了必须使用https作为scheme,而且要使用一个正常可使用的域名作为路径开头,这其实就是一个正常的网站地址了。考虑到域名是唯一所属于开发者的,所以不会出现冲突的情况,另一方面,如果App没有被正常调走(比如App并没有安装),https打头的链接系统会自动打开浏览器进行网页加载,这也给开发者提供了展示App或者说明原因的机会。
比如需要通过myapp://com.example.app/来调起App,只需要在android/app/src/main/AndroidManifest.xml里配置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="com.example.app"
android:scheme="myapp" />
</intent-filter>
测试时,可以写一个简单的h5页面,将<a>的href写上目标链接即可。也可以更简单的使用如下命令:
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d myapp://com.example.app/
iOS上只需要在Info里添加即可:
或者手动编辑plist文件,添加如下:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.example.app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
验证是否生效有三种方法,第一种是写一个带<a>标签的h5页面,第二种是使用命令:
xcrun simctl openurl booted myapp://com.example.app/
多安卓多一种方式,即第三种也是最方便的一种:使用备忘录(即 Notes)输入myapp://com.example.app/,输入之后再回车换行,就会被自动识别为可点击链接,点击该链接,看是否可以调起目标App,也可以长按该链接看是否会弹出菜单显示在目标App中打开的选项。
安卓的App Link与Deep link类似,只是scheme为https。
安卓的App link使用并不广泛,特别是在国内,一方面,因为在验证域名所属权这块是必须要用到谷歌服务的,需要在服务器上部署/.well-known/assetlinks.json文件,此文件是在App安装之后通知谷歌服务器去读取。另一方面,各安卓手机的生产厂商都对系统做了定制化,有各家自己的App link格式要求,如此将控制权掌控在厂商自己手中。
关于/.well-known/assetlinks.json的格式内容本文不作记录。
验证链接有效性的命令也类似:
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d https://app.example.com/xxx/
也是一样需要验证域名的所属权,验证链接是完全公开的,以微信为例子,链接路径为:https://mp.weixin.qq.com/.well-known/apple-app-site-association
其内容为:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "88L2Q4487U.com.tencent.mp",
"paths": [ "/mpapp/*" ]
},
{
"appID": "HKB8WPFBR9.com.tencent.mp.db",
"paths": [ "/mpapp/*", "/db/mpapp/*" ]
}
]
}
}
appID为teamId + bundleId组成,路径当以星号结尾时指定了Universal Link生效的前缀。多个App使用同一个域名,可以details里写多个,如上所示。
这个/.well-known/apple-app-site-association部署之后,什么时候会被苹果服务器请求呢?是在相关App被安装之时通知苹果服务器,苹果服务器会在接下来的三天内请求,也就是说如果部署的apple-app-site-association内容有调整,并不会立马生效,生效时间最久可能需要三天。不过,自己实测,一般24小时内会被请求。
接着是在App中如何注册Universal Link,第一步是登录苹果开发者账号,确认下App使用的Identifier包含了Associated Domains功能:
第二步是在xcode中项目的capability里添加Associated Domains,applinks:打头,示例如下:
完成以上步骤之后,就可以在真机上运行了,不过在域名被验证之前,universal link并不会生效,需等一段时间,可以通过后端日志监控一下apple-app-site-association被抓取的时间。
验证是否生效,跟iOS的deep link验证三种方式一样。命令方式如下:
xcrun simctl openurl booted https://app.example.com/xxx
当未生效时执行以上命令,iOS系统会自动打开safari并加载该页面。如果生效时,那么就会直接调起目标App了。