Assetlinks.json 中的应用链接意图过滤器在 Android 上不起作用
Posted
技术标签:
【中文标题】Assetlinks.json 中的应用链接意图过滤器在 Android 上不起作用【英文标题】:App links intent filters in assetlinks.json not working on Android 【发布时间】:2016-06-01 19:13:16 【问题描述】:我的应用定义了意图过滤器来处理来自我的站点的 URL,由
<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:host="www.host.com" android:scheme="http"/>
</intent-filter>
<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:host="www.host.com" android:scheme="https"/>
</intent-filter>
应用程序正确检测到正确主机的 URL,但询问用户是在应用程序还是浏览器中打开它们。我尝试使用此处指定的应用链接验证:https://developer.android.com/training/app-links/index.html
从我的服务器日志中可以看出,在安装应用程序时,设备会查询 /well-known/assetlinks.json 并以 200 状态响应。使用
测试数字资产文件https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://<domain1>:<port>&relation=delegate_permission/common.handle_all_urls
API 并没有发现错误。
assetlinks.json 文件中的 SHA256 是使用
获取的keytool -list -v -keystore my-release-key.keystore
与应用签名相同的 .keystore。
运行adb shell dumpsys package d
返回链接验证状态为“询问”,表示验证失败。为什么验证会失败?
【问题讨论】:
嗨@mohamed.ahmed 你能解决这个问题吗?我有类似的问题。在上传到 Play 商店之前,我的 android 应用程序链接适用于已签名的 apk。将其带到游戏商店后停止工作。请参阅链接以获取更多信息***.com/questions/57959217/… 也许您已将本地证书中的 SHA256 放入您的资产文件(在服务器中)。您需要将 SHA256 从 playGoogle 放入。 ***.com/a/61204765/496637 【参考方案1】:对我们来说,这是 Windows 行尾!
使用“https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://domain1:port&relation=delegate_permission/common.handle_all_urls”进行测试证明是无价的,因为它给了我们“无法解析语句列表(无效 JSON)”错误,导致我们遇到了问题。
提示:最好使用 Android Studio App Links Assistant 中的“保存文件”按钮,而不是像我们所做的那样复制和粘贴 - 这样它会自行生成文件并保证不会出现此问题。
【讨论】:
这个答案让我走上了正确的道路,但对我来说,它实际上是字节顺序标记 (BOM),而不是行尾。我删除了 BOM,文件在 Windows 行结尾处工作得很好。有关如何删除 BOM 的详细信息,请参阅我的回答。 我先将它剪切并粘贴到记事本中,它为我解决了这个问题。找不到保存文件按钮。【参考方案2】:有一些常见的陷阱你应该检查两次(我不是说你做错了。这只是一个检查清单):
-
验证
assetlinks.json
是否有效并存储可从https://example.com/.well-known/assetlinks.json
访问,您需要访问https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site= https://example.com&relation=delegate_permission/common.handle_all_urls
,必须没有错误。
如果您一次链接多个域,请检查所有域是否都按照步骤 1 正确设置。
确保那些包含<data>
标签的<intent-filters>
具有android:autoVerify="true"
属性。
验证您的<application>
标记中是否包含所需的<meta-data>
标记:
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements"/>
asset_statements
字符串的内容必须是:
<string name="asset_statements" translatable="false">[\"include\": \"https://example.com/.well-known/assetlinks.json\"]
还用于调试发布签名证书(不要害怕您不能意外上传)在您的build.gradle
中使用它:
buildTypes
release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
debug
debuggable true
signingConfig signingConfigs.release
【讨论】:
另外,我还要补充一点,如果您有相同的根主机,但具有指向同一活动的不同路径值(如果您使用 .well-known 流程实现它),则应用程序链接将不起作用。我需要这个来同时在我的测试服务器和生产环境中测试我的功能。@string/asset_statements
将如何提供帮助?特别是如果它只有一个 URL,而在 AndroidManifest
我们有多个。
奇怪,但是当我将两个域(从 AndroidManifest
)添加到 asset_statements
时它有所帮助。但是后来又不行了,所以我删除了<meta-data>
。【参考方案3】:
对我来说,它归结为检查所有基础知识:
-
使用此工具验证我的assetLinks 文件是否良好:(将 domain1:port 替换为您的域)
https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://domain1:port&relation=delegate_permission/common.handle_all_urls
始终使用签名的 APK 进行测试
确保测试设备运行的是 Android 6.0 或更高版本(这是因为我忘记了它而让我苦恼的设备 - 在旧版本的 android 上,您总是会收到用户提示)
【讨论】:
非常感谢,这指出了问题所在。【参考方案4】:查看j__m的评论,我发现了这个。
在AndroidManifest
这样写:
<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" />
<!-- Write <data> tags with one attribute, if you use several domains. -->
<data android:scheme="https" />
<data android:host="example.com" />
</intent-filter>
<!-- Other domains-->
<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="https" />
<data android:host="server.com" />
</intent-filter>
应用链接需要android:autoVerify="true"
。
使用Tools > App Links Assistant
创建assetlinks.json
。然后按Open Digital Asset Links File Generator
,输入域,应用程序ID,选择release
签名配置并按Generate Digital Asset Links File
。然后您可以保存文件或复制到剪贴板。
您可以创建多个 assetlinks.json
文件(用于多个应用程序)并将它们连接到一个 JSON 中。在我看来,它不依赖于 Windows 行尾(我使用记事本连接 JSON)。第一次我用 Ctrl + Alt + L 自动格式化它,上传到域后,App Link 不起作用(可能是因为AndroidManifest
中的后来错误),所以第二次尝试我没有格式化 JSON。我为应用程序的release
和debug
构建创建了assetlinks.json
。
将assetlinks.json
上传到https://example.com/.well-known/assetlinks.json
(在此答案中,我写的是:example.com
,表示您的域,如company.name
)。使用https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls
进行检查。该文件和域有一些restrictions。就我而言,一切都很简单,我们没有更改设置。
在您的DeepLinkActivity
中,您可以使用正则表达式解析 URL。使用JUnit
创建测试。从onCreate()
调用这个方法:
private fun processDeepLink()
if (intent?.data?.isHierarchical == true)
val data = intent?.dataString
if (intent?.action == Intent.ACTION_VIEW && data != null)
when
REGEX.matches(data) -> // Get id and open some screen.
else -> // Either open MainActivity or skip this URL (open web browser instead).
finish()
companion object
val REGEX = "^https://example.com/some_request/(\\d+).*".toRegex()
警告!如果您从应用程序打开网络浏览器,您将陷入循环。在应用程序中单击指向您的域的链接时,不会出现浏览器,但您的应用程序会自动打开!多么惊喜!因此,在processDeepLink
中,您应该检查 URL 并在 URL 与您的掩码之一匹配时打开 MainActivity
。跳过其他人。现在用户将看到一个包含浏览器列表和您的应用程序的对话框(就像在 Deep Link 中一样)。发生这种情况是因为您的应用程序还处理指向您的域的链接,例如浏览器。
您也可以使用WebView
代替浏览器(不是一个好的解决方案),打开Chrome Custom Tabs
或Chrome
。
使用搭载 Android 6 或更高版本的设备。
如果https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls
没有返回错误,则构建应用程序。创建包含指向您的域的链接的电子邮件、短信、二维码或其他应用程序。单击它,App Link 将打开您的应用程序,或者 Deep Link 将显示一个对话框以选择应用程序。
如果 App Link 不起作用,请稍后阅读。
在LogCat
中选择No Filters
并在搜索框中输入IntentFilter
。应该有:
I/IntentFilterIntentOp: Verifying IntentFilter. verificationId:2 scheme:"https" hosts:"example.com" package:"com.my_package".
I/IntentFilterIntentOp: Verification 0 complete. Success:true. Failed hosts:.
你可能会得到:
I/IntentFilterIntentOp: Verifying IntentFilter. verificationId:0 scheme:"https" hosts:"example.com server.com" package:"com.my_package".
I/IntentFilterIntentOp: Verification 0 complete. Success:false. Failed hosts:server.com.
稍后您将尝试修复应用程序中的域,因此有时您可以启动以进行全新安装:
adb shell pm clear com.android.statementservice
启动 adb shell dumpsys package d
并找到您的域。应该有:
Package Name: com.my_package
Domains: example.com server.com
Status: always : 200000000
但可能会是:
Package Name: com.my_package
Domains: example.com server.com
Status: ask
另见https://chris.orr.me.uk/android-app-linking-how-it-works/。奇怪,但在模拟器中它写道:always
,而 App Link 不起作用。
我也试过adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://example.com"
在没有浏览器的情况下测试App Link,但后来还是不行。
如果您有多个域,请评论(或删除)AndroidManifest
中的其他域(仅保留一个域,例如“example.com”)。然后单击 URL https://example.com/something 并检查它是否使用 App Link。
就我而言,我检查了应用程序的 release
和 debug
构建。 debug
构建与 App Link 一起使用,release
没有(有时反之亦然)。我用rekire的解决方案:
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements"/>
它帮助了 2 个域,但后来停止了,所以我删除了它。最后我在AndroidManifest
<data>
标签中写了一个属性为j__m说的。
即使只有一个域出现故障,App Link 也不适用于其他域。您可以在AndroidManifest
中逐个检查域,每次只保留一个域。
另见http://androidideas.com/handling-app-links-in-android/、https://willowtreeapps.com/ideas/a-better-user-experience-for-deep-linking-on-android、https://developer.android.com/training/app-links/verify-site-associations、
【讨论】:
【参考方案5】:对我来说,我的 assetlinks.json
文件是 UTF-8 并且包含 字节顺序标记 (BOM),这是一个位于向消费程序发送编码信号的文件。 BOM 是可选的,显然 Google/Android 工具不喜欢看到它。当它出现时,Google 的数字资产链接验证器(下面的 URL)给了我一个“格式错误的 JSON”错误。
如果您使用的是 Visual Studio,以下是如何确定您的文件中是否有 BOM,并在必要时将其删除:
-
右键单击您的assetlinks.json 文件。
从上下文菜单中选择“打开方式...”。
在“打开方式”对话框中选择“二进制编辑器”。
检查文件字节。如果文件以
EF BB BF
开头,那就是问题所在。
删除这些字符(您可以通过任一列执行此操作)并保存文件。
重新上传文件并使用 Google 工具(以下网址)对其进行测试,它应该可以正常工作。
这是您可以用来检查文件的 URL(将 example.com 替换为您的实际 URL):
https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls
【讨论】:
【参考方案6】:更新
所以我解决了我的问题。不确定是哪一个(可能是组合),但这就是我所做的:
已卸载“即时应用程序的 Google Play 服务”:我之前曾修改过即时应用程序,所以我认为可能一些旧配置可能会像调试包名称一样保留,但这不太可能。 已停止使用代理:代理有助于调试网络调用,但我使用的工具可能不完全支持 HTTP/2。 删除旧子域的意图过滤器:这是一个重要的。我的一个子域已被弃用,不再可用。在 AndroidManifest 中,如果您为包含至少一个 autoVerify 意图过滤器的活动声明了多个主机名,则会检查每个主机的数字资产链接 JSON 文件。 如果自动验证对于一个主机都失败了,那么所有主机都不会被自动验证。原创
当我第一次遇到这个问题时,是因为我的网络阻止了对 Google 服务器的调用以验证应用链接。
正如 OP 和其他答案所涉及的那样,通常 API 调用端点:
digitalassetlinks.googleapis.com
必须成功绕过选择器对话框。 这是 Android 系统为验证数字资产链接 JSON 文件而进行的网络调用,似乎是在应用安装/更新时进行的。一个有用的地方是 Logcat,它搜索带有文本“I/SingleHostAsyncVerifier:”的项目。如果您在日志末尾看到“--> true”,则表明您的应用
但最近,由于最近可能引入了一些错误,这些调用对我来说一直失败。设备正在接收来自上述 API 调用的响应:
错误:不可用:从 host/.well-known/assetlinks.json 获取语句时 HTTP 响应标头中的内容类型错误(相当于“host/.well-known/assetlinks.json”) :预期“内容类型:应用程序/json”,但在从 host./.well-known/assetlinks.json 获取 Web 语句时找到了 text/html [11]
自从我上次查看这些请求以来已经有一段时间了,所以我不记得它们之前的样子了。但似乎最近可能有一些涉及 App Links 或 Android 网络框架的更新,他们切换到此功能的协议缓冲区(并忘记在另一个中支持它)。
另一个表明事情可能已经改变的迹象是,今天的请求路径与之前的答案中提到的不同:
https://digitalassetlinks.googleapis.com/google.digitalassetlinks.v1.AssetLinks/Check
【讨论】:
【参考方案7】:对我来说,不要更改 assetlinks.json
的任何内容,包括修剪 blanks 和 line-breaks。
【讨论】:
【参考方案8】:在我们的例子中,我们的清单中有 2 个带有应用链接的意图过滤器:一个带有 autoVerify="true"
,一个没有。
因此验证程序尝试验证第二个意图过滤器的域并失败,并将我们所有的应用链接视为“未验证”。您可以在this question找到更多详细信息。
您必须确保可以验证每个应用链接(这意味着为每个要验证的域添加 assetlinks.json
)。
【讨论】:
【参考方案9】:我确定这不能回答最初的问题,因为我认为它早于 Android App Bundles,但最终导致我失败的是我启用了 Google Play Console 重新签名的应用程序(AAB 需要),因此我从 keytool
获得的 SHA-256 指纹与下载的应用程序的数字签名不匹配。
使用控制台中的指纹更新我的assetlinks.json
解决了这个问题。
【讨论】:
【参考方案10】:在我的例子中,adb shell dumpsys package d
显示 packageName
在 assetlinks.json
中的配置不正确。我在AndroidManifest.xml
中使用了manifest
标记的package
属性值,但我应该在build.gradle
文件中使用android.defaultConfig.packageId
值。
【讨论】:
【参考方案11】:系统应用选择窗口两种情况
1) 用户通过进入设置>应用>齿轮图标>打开链接>选择一个应用>打开支持的链接>每次选择提示来更改设置相关的打开链接。
2) 用户未设置默认应用,并且在支持的应用链接之一中未启用自动验证
我认为在您的情况下启用了自动验证,因此请检查用户设置。
【讨论】:
【参考方案12】:感谢这里的所有其他答案,我能够找到我的问题。尽管做的一切都是正确的。这是我的问题。
如果您的项目很大,您可能有多个 android 模块依赖项。检查合并的清单以查找所有带有意图过滤器的活动(使用 autoverify = true)。这怎么会出错很简单。如果一个项目有多个自动验证 url,那么操作系统会尝试全部验证。即使一个失败,操作系统也无法验证每个 URL。
在您的主应用模块中打开清单文件,然后从底部选项卡中选择合并清单选项。现在检查右侧的清单源(列表)并手动查找每个库项目的清单文件。
就我而言,启用了第三方库的自动验证标志。我为期两天的搜索结束了。祝你好运。
【讨论】:
以上是关于Assetlinks.json 中的应用链接意图过滤器在 Android 上不起作用的主要内容,如果未能解决你的问题,请参考以下文章