应用程序链接无法在Android

时间:2016-02-20 02:31:13

标签: android android-6.0-marshmallow applinks

我的应用定义了意图过滤器,用于处理

定义的网站中的网址
<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>

该应用正确检测到正确主机的网址,但会询问用户是否在应用或浏览器中打开它们。我尝试使用此处指定的应用链接验证。 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://&lt;域1&GT;:其中端口&GT;&安培;关系= delegate_permission / common.handle_all_urls

API,它没有发现任何错误。

assetlinks.json文件中的SHA256是使用

获得的
keytool -list -v -keystore my-release-key.keystore 

应用程序签名的.keystore。

运行adb shell dumpsys package d会返回链接验证状态为&#34;问&#34;意味着验证失败。为什么验证会失败?

12 个答案:

答案 0 :(得分:11)

对我们来说,它是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中的“保存文件”按钮,而不是像我们一样复制和粘贴 - 这样就可以自行生成文件并保证不会出现此问题。

答案 1 :(得分:8)

对我而言,它归结为检查所有基础知识:

  1. 使用此工具验证我的assetLinks文件是否合适:(将domain1:port替换为您的域) https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://domain1:port&relation=delegate_permission/common.handle_all_urls
  2. 始终使用已签名的APK进行测试
  3. 确保测试设备运行的是Android 6.0或更高版本(这是因为我忘记了它 - 在旧版本的android上,你总是得到用户提示)

答案 2 :(得分:6)

看着j__m条评论,我发现了这一点。

  1. 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"是应用程序链接所必需的。

  1. 使用assetlinks.json创建Tools > App Links Assistant。然后按Open Digital Asset Links File Generator,输入域,应用程序ID,选择release签名配置,然后按Generate Digital Asset Links File。然后,您可以保存文件或将其复制到剪贴板。

  2. 您可以创建多个assetlinks.json文件(用于多个应用程序)并将它们加入一个JSON中。在我看来,它不依赖于Windows行尾(我使用记事本来连接JSON)。第一次,我使用Ctrl + Alt + L对其进行自动格式化,并且在将其上传到域后,App Link无法正常工作(可能是由于AndroidManifest中的以后错误),因此在第二次尝试中,我没有格式化JSON 。我为应用程序的assetlinks.jsonrelease构建了debug

  3. 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进行检查。该文件和域具有一些restrictions。就我而言,一切都很简单,我们没有更改设置。

  4. 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 TabsChrome

  1. 在Android 6或更高版本上使用设备。

  2. 如果https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls没有返回错误,请构建应用程序。创建电子邮件,SMS,QR码或带有指向您的域的链接的其他应用程序。单击它,App Link将打开您的应用程序,或者Deep Link将显示一个对话框以选择一个应用程序。 如果App Link无效,请稍后阅读。

  3. 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.
  1. 稍后,您将尝试修复应用程序中的域,因此有时可以启动全新安装:

    adb shell pm clear com.android.statementservice
    
  2. 启动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,但后来却无法正常工作。

  1. 如果您有多个域,请注释(或删除)AndroidManifest中的其他域(仅保留一个域,例如“ example.com”)。然后单击URL https://example.com/something,并检查它是否使用App Link。 就我而言,我检查了应用程序的releasedebug构建。尽管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-androidhttps://developer.android.com/training/app-links/verify-site-associations

答案 3 :(得分:5)

有一些常见的陷阱你应该检查两次(我不是说你做错了。它只是一个检查清单):

  1. 验证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,以便您访问<intent-filters>,必须没有错误。
  2. 如果您一次链接多个域,请检查是否已按照步骤1正确设置了所有域。
  3. 确保包含<data>代码的android:autoVerify="true"<meta-data>属性为<application>
  4. 确认您的<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
        }
    }
    
  5. 用于调试也是发布签名证书(不要害怕你不能意外上传)在你的function getValue(obj){ alert(obj);// check if obj has something in it before proceeding to "value" alert(obj.value); } 中使用它:

    {{1}}

答案 4 :(得分:3)

更新

所以我解决了我的问题。不知道是谁做的(可能是组合的),但这是我做的:

  • 卸载了“适用于Instant Apps的Google Play服务”:我之前曾尝试过使用Instant Apps,所以我想也许有些旧的配置可能仍然存在,例如调试包名称,但这不太可能。
  • 停止使用代理:代理对于调试网络呼叫很有帮助,但是我使用的工具可能不完全支持HTTP / 2。
  • 删除旧版子域的Intent过滤器:这是重要的。我的一个子域已被弃用,不再可用。在AndroidManifest中,如果为一个活动声明了多个主机名,其中至少包含一个 autoVerify目的过滤器,则将检查每个主机的Digital Asset Link JSON文件。 如果即使其中一台主机的 autoVerify失败<< / strong>,那么所有主机都不会自动进行验证。

原始

当我第一次遇到此问题时,是因为我的网络阻止了对Google服务器的调用,以验证应用程序链接。

在触摸OP和其他答案后,通常对端点的API调用:

  

digitalassetlinks.googleapis.com

必须成功绕过选择器对话框。 这是Android系统进行的网络调用,用于验证Digital Asset Link JSON文件,并且似乎是在应用程序安装/更新时进行的。 Logcat是一个有用的地方,它搜索带有文本“ I / SingleHostAsyncVerifier:”的项目。如果您在日志末尾看到“-> true”,则您的应用程序

不过,由于似乎是最近引入的一些错误,这些调用对我来说一直失败。设备正在从上面的API调用中收到此响应:

  

错误:不可用:从{host} /。well-known / assetlinks.json(等同于'{host} /。well-known / assetlinks.json')中获取语句时,HTTP响应标头中的内容类型错误。 :预期为“内容类型:应用程序/ json”,但在从{host}获取Web语句时找到了text / html [11]。/。well-known / assetlinks.json

自从我上次查看这些请求以来已经有一段时间了,所以我不记得他们以前的样子。但是,似乎有可能最近进行了一些涉及App Link或Android网络框架的更新,在这些更新中,他们切换到了此功能的协议缓冲区(并忘记了在另一个版本中支持该功能)。

另一个可能已发生变化的迹象是,今天的请求路径看起来不同于先前答案中提到的路径:

  

https://digitalassetlinks.googleapis.com/google.digitalassetlinks.v1.AssetLinks/Check

答案 5 :(得分:1)

对我而言,我的assetlinks.json文件是UTF-8,并且包含字节顺序标记(BOM),这是一个三字节的幻数。将编码信号通知给消耗程序的文件头。 BOM是可选的,显然Google / Android工具不喜欢看到它。当它出现时,谷歌的数字资产链接验证程序(下面的URL)给了我一个错误的JSON&#34;错误。

如果您正在使用Visual Studio,请按照以下步骤确定您的文件中是否包含BOM,并在必要时将其删除:

  1. 右键单击assetlinks.json文件。
  2. 选择&#34;打开...&#34;从上下文菜单中。
  3. 选择&#34;二进制编辑器&#34;在&#34;打开&#34;对话框。
  4. 检查文件字节。如果文件以EF BB BF开头,那就是问题所在。
  5. 删除这些字符(您可以通过任一列执行此操作)并保存文件。
  6. 重新上传文件并使用Google工具(以下网址)对其进行测试,它应该可以正常使用。
  7. 以下是您可以用来检查文件的网址(将example.com替换为您的实际网址):

    https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls

答案 6 :(得分:0)

就我而言,adb shell dumpsys package d显示packageName中的assetlinks.json配置错误。我在package中使用了manifest标记的AndroidManifest.xml属性值,但我应该在android.defaultConfig.packageId文件中使用build.gradle值。

答案 7 :(得分:0)

两种情况下的系统应用选择窗口

1)用户通过转到设置来更改与设置相关的开放链接&gt;应用&gt;齿轮图标&gt;打开链接&gt;选择一个应用&gt;打开支持的链接&gt;每次都选择提示。

2)默认应用未由用户设置,并且其中一个应用链接支持的应用未启用自动验证

我认为在你的情况下启用了自动验证,所以请检查用户设置。

答案 8 :(得分:0)

对我来说,请勿更改assetlinks.json的任何内容,包括修剪空白换行符

答案 9 :(得分:0)

感谢这里的所有其他答案,我能够找到我的问题。尽管一切正确。这是我的问题。

  • 如果您的项目很大,则可能您有多个android模块依赖项。检查合并的清单以查找所有具有意图过滤器的活动(autoverify = true)。

这怎么会出错很简单。如果项目有多个自动验证网址,则操作系统会尝试对其进行全部验证。即使失败,操作系统也会无法验证每个URL。

在主应用程序模块中打开清单文件,然后从底部选项卡中选择“合并清单”选项。现在,检查右侧的清单源(列表),并手动查找每个库项目的清单文件。

在我的情况下,启用了第三方库的自动验证标志。我为期两天的搜索结束了。祝你好运。

答案 10 :(得分:0)

在我们的案例中,清单中有2个带有应用程序链接的意图过滤器:一个带有autoVerify="true"的意图过滤器,另一个没有。

因此,验证者尝试验证第二个意图过滤器的域并失败,并将我们所有的应用链接视为“未验证”。您可以在this question中找到更多详细信息。

您必须确保可以验证每个应用链接(这意味着要为每个要验证的域添加assetlinks.json)。

答案 11 :(得分:0)

我确定这无法回答最初的问题,因为我认为它早于Android应用程序捆绑包,但最终导致我失败的原因是我启用了Google Play控制台重新签名的应用程序(对于AAB是必需的),因此我从keytool获得的SHA-256指纹与下载的应用程序的数字签名不匹配。

使用控制台中的指纹更新我的assetlinks.json即可解决