应用程序链接无法在Android上运行

moh*_*med 35 android applinks android-6.0-marshmallow

我的应用程序定义了意图过滤器来处理来自我的网站定义的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>
Run Code Online (Sandbox Code Playgroud)

该应用程序正确检测正确主机的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 
Run Code Online (Sandbox Code Playgroud)

应用程序签名的.keystore.

运行https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://<domain1>:<port>&relation=delegate_permission/common.handle_all_urls返回链接验证状态为"ask",表示验证失败.为什么验证会失败?

Mar*_*chy 12

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


Kei*_*ith 9

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

  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上,你总是得到用户提示)


Coo*_*ind 9

看着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>
    
    Run Code Online (Sandbox Code Playgroud)

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 自动格式化它,上传到域后应用链接不起作用(可能是因为后来的错误AndroidManifest),所以在第二次尝试时我没有格式化 JSON。我assetlinks.json为应用程序创建releasedebug构建。

  3. 上传assetlinks.jsonhttps://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。文件和域有一些限制。就我而言,一切都很简单,我们没有更改设置。

  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()
    }
    
    Run Code Online (Sandbox Code Playgroud)

警告!如果您从应用程序打开 Web 浏览器,您将陷入循环。在应用程序中单击指向您的域的链接时,不会出现浏览器,但您的应用程序会自动打开!多么惊喜!因此,processDeepLink您应该检查 URL 并MainActivity在 URL 与您的掩码之一匹配时打开。跳过其他人。现在,用户将看到一个包含浏览器和应用程序列表的对话框(如 Deep Link)。发生这种情况是因为您的应用程序还处理指向您的域的链接,例如浏览器。

您也可以使用WebViewopenChrome 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没有返回错误,则构建应用程序。创建电子邮件、短信、二维码或其他带有您的域链接的应用程序。单击它,App Link 将打开您的应用程序,或者 Deep 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:.
    
    Run Code Online (Sandbox Code Playgroud)

可能你会得到:

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.
Run Code Online (Sandbox Code Playgroud)
  1. 稍后您将尝试修复应用程序中的域,因此有时您可以启动以进行全新安装:

    adb shell pm clear com.android.statementservice
    
    Run Code Online (Sandbox Code Playgroud)
  2. 开始adb shell dumpsys package d并找到您的域。应该有:

    Package Name: com.my_package
    Domains: example.com server.com
    Status:  always : 200000000
    
    Run Code Online (Sandbox Code Playgroud)

但可能会是:

Package Name: com.my_package
Domains: example.com server.com
Status: ask
Run Code Online (Sandbox Code Playgroud)

另请参阅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"/>
    
    Run Code Online (Sandbox Code Playgroud)

它对 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


rek*_*ire 6

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

  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,必须没有错误。
  2. 如果您一次链接多个域,请检查是否按照步骤1正确设置了所有域。
  3. 确保<intent-filters>包含您的<data>标签的标签具有属性android:autoVerify="true"
  4. 验证<meta-data>标签中是否包含必需的<application>标签:

    <meta-data
        android:name="asset_statements"
        android:resource="@string/asset_statements"/>
    
    Run Code Online (Sandbox Code Playgroud)

    asset_statements字符串的内容必须为:

    <string name="asset_statements" translatable="false">[{\"include\": \"https://example.com/.well-known/assetlinks.json\"}]
    
    Run Code Online (Sandbox Code Playgroud)
  5. 也可用于调试发行签名证书(不要担心您不会意外上传它)在您的中使用此证书build.gradle

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
        debug {
            debuggable true
            signingConfig signingConfigs.release
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Bri*_*Rak 6

对我来说,事实是我的assetlinks.json文件是 UTF-8 并且包含字节顺序标记(BOM),它是文件头部的一个三字节幻数,向使用程序发出编码信号。BOM 是可选的,显然 Google/Android 工具不喜欢看到它。当它出现时,Google 的数字资产链接验证器(下面的 URL)给了我一个“格式错误的 JSON”错误。

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

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

以下是可用于检查文件的 URL(将 example.com 替换为您的实际 URL):

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


use*_*751 5

更新

所以我解决了我的问题。不确定是哪一个(可能是组合),但这就是我所做的:

  • 卸载“Google Play 即时应用程序服务”:我之前对即时应用程序进行了修补,所以我认为可能一些旧配置可能会像调试包名称一样存在,但这不太可能。
  • 停止使用代理:代理有助于调试网络调用,但我使用的工具可能不完全支持 HTTP/2。
  • 删除旧子域的意图过滤器:这是最大的一个。我的一个子域已被弃用,不再可用。在 AndroidManifest 中,如果您为至少包含一个autoVerify 意图过滤器的活动声明了多个主机名,则会检查每个主机的数字资产链接 JSON 文件。如果即使其中一台主机的autoVerify 失败,则不会自动验证任何主机。

原来的

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

正如 OP 和其他答案所涉及的那样,通常对端点的 API 调用:

digitalassetlinks.googleapis.com

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

但是最近,由于最近可能引入的一些错误,这些调用对我来说一直失败。设备正在从上面的 API 调用接收此响应:

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

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

事情可能已经发生变化的另一个迹象是,今天的请求路径似乎与之前答案中提到的不同:

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