这两天在给我们的app设计一个统一的外部流量入口,用了Android App Links技术(iOS是Universal Links)。入口Activity加好了,intent-filter也按照Google官方文档设置好了,但在测试时却仍然会弹出选择框,让用户选择用哪个app打开,仍然停留在deep link层面。解决这个问题花了我一些时间,这里总结一下,希望能让大家少走弯路。

选择框里有多个应用,用户可能并不知道用哪个,这就大大增加了流失率
Google如何关联我们的网站和app
当我们在intent-filter里声明android:autoVerify="true”(只需要声明一个)后,安装app的时候,Android系统会验证所有我们声明的host。它会去https://hostname/.well-known/assetlinks.json 这个地方下载文件,然后做校验。

只需要声明一个
为什么会验证不成功
检查assetlinks.json文件是否存在
一个典型的assetlinks.json文件大概这样:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
}
}]
在命令行执行curl https://hostname/.well-known/assetlinks.json ,看能否显示assetlinks.json文件的内容。如果浏览器能打开,curl命令不行,则是因为该网站设置了防爬策略,不让机器人访问,需找web端开发解决一下。

package_name是否正确
因为我们可能会在build.gradle文件里通过Flavor声明构建多种包,所以你首先需要检查当前打包的包名和assetlinks.json文件里是否一样。
sha256_cert_fingerprints是否正确
通过keytool -list -v -keystore my-release-key.keystore命令生成签名证书的SHA hash值时,keystore文件的路径一定不要搞错了,去你的build.gradle文件里找。开发时可考虑用debug包的keystore。
虽然这些字段都反复确认了没问题,但还是验证不成功。
过滤关键字
这个时候我们需要去Logcat里搜索验证相关的日志,在Logcat里过滤关键字verify(有的博客里说要过滤SingleHostAsyncVerifier和IntentFilterIntentSvc关键字,但我Android 9的系统并没有):
I/IntentFilterVerificationReceiver: Verifying IntentFilter. verificationId:35 scheme:"https" hosts:"native.m.aaaa.com
m.bbbb.com h5.m.cccc.com” package:"com.sss.abc.dev".
虽然日志并没有告诉我们是否成功,但从上面这条日志,我们可以知道竟然多了native.m.aaaa.com和h5.m.cccc.com的验证。这2个网站都没有.well-known/assetlinks.json这个文件,所以验证失败。因为只要有一个host验证失败就所有的都失败,所以需要继续排查这个两个host是在哪声明的。native.m.aaaa.com比较简单,通过全局搜索就可以搜到声明的地方,然后做相应的处理。而h5.m.cccc.com在工程里却搜不到。

必须所有的host都验证成功,系统才会建立关联
搜索apk文件里的AndroidManife文件
在Android Studio里打开编译出的apk文件,打开AndroidManifest文件,搜索h5.m.cccc.com即可搜到在哪个Activity里声明的。这时你会搜到一个陌生的Activity,因为它是在依赖库里声明的。打开这个类,我们便知道它属于哪个库了。

查看依赖树
在工程根目录执行如下命令即可打印出依赖树:
./gradle app:dependencies

在打印出的内容里搜索依赖库,便可知道最上层是哪里依赖了这个库。如果不需要这个库,可以在引用的地方用exclude将其排除。如果需要这个库,我们在确认不需要这个外部入口后,可以在上层AndroidManifest里声明一个一模一样的Activity,然后通过tools:node="remove"将其intent-filter去掉:
<activity
android:name="com.ttt.android.xxx.MainActivity"
android:exported="false">
<intent-filter tools:node="remove">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="h5.m.cccc.com"
android:path=“/xxx/main.html" />
</intent-filter>
</activity>
App Links Assistant
这个文档教你用Android Studio的App Links Assistant工具设置和验证App Links
https://developer.android.com/studio/write/app-link-indexing.html
推荐用这个图形化的工具来做host的验证,有错误提示:


这个工具也有bug,多点几次会出现不一样的错误提示。当后端以文件的方式返回assetlinks.json文件时,工具会提示如下错误:
It looks like you are hosting the Digital Asset Links file with a wrong Content-Type. Please make sure the Content-Type is application/json.
但是手机上是可以验证成功的。
References:
https://developer.android.com/training/app-links
https://developer.android.com/training/app-links/deep-linking
https://developer.android.com/training/app-links/verify-site-associations
https://developer.android.com/studio/write/app-link-indexing.html
本文详细介绍了在实现Android App Links过程中遇到的自动验证不成功的问题,包括assetlinks.json文件检查、package_name和sha256_cert_fingerprints验证、Logcat日志分析以及依赖树排查等步骤,旨在帮助开发者解决App Links的配置问题。
4592

被折叠的 条评论
为什么被折叠?



