Handling App Links

参考https://developer.android.com/about/versions/marshmallow/android-6.0.html
参考https://developer.android.com/training/app-links/index.html

当我们在应用中点击一个链接,通常会提示我们选择合适的浏览器或者app去打开它。
从Android6.0开始,你可以让你的app作为对给定类型链接的默认处理者。当然,如果用户不想你的app作为默认处理者,他们可以在设置中修改。

自动处理链接需要app开发者和网页所有者的共同协作。app开发者需要通过配置来声明处理哪些链接,同时需要系统验证这些链接。网站所有者需要发布一个Digital Asset Links文件来提供验证。Handling App Links通常的步骤包括:
1、app开发者:在app的manifest文件中,创建包括网站uri的intent filter。
2、app开发者:配置app,请求验证app links。
3、网站所有者:在网站上发布一个Digital Asset Links JSON文件,用于提供验证。


一、Understand URI Request Handling

android6.0提供的app links特点,能够让你的app作为特定网站uri的默认处理者,即使用户从没有设置过默认的处理者。
当用户点击一个链接,或者程序启动一个网页uri意图,android系统按照以下顺序决定如何处理它们:
1、用户设置了此链接处理者:如果用户设置了哪个app处理,系统把网页的uri传递给此app。用户设置有两种方式:
-在曾经点击此链接弹出的app选择对话框中勾选了“总是”’;
-在设置-应用-应用链接中选择一个app,设置这个app的“app links”属性为打开这个app。
2、用户没有设置此链接处理者,并且有一个支持处理此链接的app:系统自动传递网页uri给这个app。
3、用户没有设置此链接处理者,并且有多个支持处理此链接的app:系统会显示一个app选择对话框,提示用户选择最合适的app。


二、Create an Intent Handler for URIs

App links基于Intent框架,它允许app去处理来自系统或其它app的请求。
多个app可以在intent filter中声明一样的uri模式,当用户点击一个链接并且没有设置默认的处理者时,系统会弹出app选择对话框让用户去选择。
想要让你的app处理链接,需要在manifest文件中使用intent filter来声明app需要处理的uri模式。下面的例子,声明了一个intent filter能够处理http://www.android.comhttps://www.android.com

<activity …>
    <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:scheme="http" />
        <data android:scheme="https" />
        <data android:host="www.android.com" />
    </intent-filter>
</activity>

请看上面这个例子,处理链接的intent filter中必须声明android:scheme的值为“http”、“https”或者两者,并且不能声明其它的schemes。intent filter必须声明name为android.intent.action.VIEW的action和name为android.intent.category.BROWSABLE的category。
这个manifest中的intent filter声明就让你的app和网站建立了联系,为了让系统使用你的app作为你声明的uri的默认处理者,你需要请求系统验证这种联系。请看下一节如何实现这种验证。


除了使用intent filter声明你的app和网站之间的联系,你的manifest文件还需要额外声明:请求自动验证。
当这个声明之后,在你的app安装后,android系统会尝试验证你的app。如果验证成功,并且用户没有设置处理你声明的uri的app,系统自动传递这些uri请求给你的app。
系统通过对比你声明的intent filter中data元素的host name和每个网站的Digital Asset Links files (assetlinks.json)来进行验证。为了触发系统进行验证,请确保intent filter中包括android.intent.action.VIEW intent action和android.intent.category.BROWSABLE intent category。

3.1、Enabling automatic verification

为了触发系统自动验证,需要设置intent filter的android:autoVerify为true,请看下面的例子

<activity ...>
    <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="http" android:host="www.android.com" />
        <data android:scheme="https" android:host="www.android.com" />
    </intent-filter>
</activity>

当android:autoVerify设置为true后,android系统会自你的app安装后进行验证,验证所有声明的uri和对应的网站。如果你声明的所有uri都验证成功,系统会把你的app作为这些uri的默认处理者。

3.2、Supporting app linking for multiple hosts

系统会验证intent filter中声明的每个host和每个网站中的Digital Asset Links,如果任何一组验证失败,你的app都不会作为任何一个你声明的uri的默认处理者。请看下面的例子,如果在https://www.domain1.com/.well-known/assetlinks.json和and https://www.domain2.com/.well-known/assetlinks.json都没有找到assetlinks.json文件,那么就验证失败。

<application>

  <activity android:name=”MainActivity”>
    <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="http" android:host="www.domain1.com" />
      <data android:scheme="https" android:host="www.domain1.com" />
    </intent-filter>
  </activity>

  <activity android:name=”SecondActivity”>
    <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:scheme="https" android:host="www.domain2.com" />
    </intent-filter>
  </activity>

</application>

3.3、Supporting app linking for multiple subdomains

Digital Asset Links协议把subdomains看作是唯一的、单独的host。如果你的intent filter包括www.example.com和mobile.example.com,你必须为每个subdomain提供一份单独的assetlink.json。请看下面的例子,只有网站所有者在https://www.example.com/.well-known/assetlinks.jsonhehttps://mobile.example.com/.well-known/assetlinks.json都提供了合法的assetlinks.json文件,验证才能通过。json文件必须通过加密的HTTPS连接获取,请看下一节。

<application>

  <activity android:name=”MainActivity”>
    <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="http" android:host="www.example.com" />
      <data android:scheme="https" android:host="mobile.example.com" />
    </intent-filter>
  </activity>

</application>

四、Declare Website Associations

要使得验证成功,网站所有者必须声明和app的联系。网站所有者通过持有一个名为assetlinks.json的Digital Asset Links JSON文件来声明与一个app的联系,它在domain的well-known位置:https://domain[:optional_port]/.well-known/assetlinks.json

注意:系统通过加密的HTTPS协议来验证json文件,所以不管intent filter中是否声明了https,请确保json文件能够通过HTTPS连接来获取。

Digital Asset Links JSON文件声明了与此网站关联的app,下面的示例assetlinks.json文件允许包名为com.example的app打开链接:

[{
  "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"]
  }
}]

json文件使用package_name和sha256_cert_fingerprints来标示一个app。

package_name:为app的包名;
sha256_cert_fingerprints:是app签名证书的SHA256 fingerprints,它支持多个fingerprints,用于支持你的app的多个版本(debug、release)。

你可以使用java的keytool命令来获取fingerprints:$ keytool -list -v -keystore my-release-key.keystore。

4.1、Associating a website with multiple apps

一个网站可以使用一份assetlinks.json文件来声明与多个app的联系。下面的文件位于https://www.example.com/.well-known/assetlinks.json,它单独声明了与两个app的联系:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "example.com.puppies.app",
    "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"]
  }
  },
  {
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "example.com.monkeys.app",
    "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"]
  }
}]

不同的app能够处理同一个host下面的不同的资源,比如app1声明处理https://example.com/articles的intent filter,app2声明处理https://example.com/videos的intent filter。

注意:与同一个网站建立联系的多个app,可以用相同/不同的证书签名。

4.2、Associating multiple websites with a single app

多个网站可以使用单独的assetlinks.json文件声明与同一个app建立联系。下面的两个assetlinks.json文件显示了如果让domain1、domain2都与app1建立联系。

https://www.domain1.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "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"]
  }
}]

https://www.domain2.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "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"]
  }
}]

当实现了上述app linking功能后,需要进行测试,确保android系统能够关联你的app和网站、处理uri请求。

5.1、Confirm the list of hosts to verify

首先,列出系统需要验证的与你的app关联的网站uri,列出包括如下属性、元素的intent filter中的uri:

<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host=“一个domain uri" />

然和使用列出的uri去检查每个host、subdomain是否有一个Digital Asset Links JSON文件。

使用Digital Asset Links API去检查每个网站的json文件是否存在并定义正确,将下方的source.web.site替换成你的app关联的网站,然后在浏览器输入即可验证。

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

比如输入:

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

可以看到如下结果,说明包名为com.google.android.calendar的app关联了www.google.com。

{
  "statements": [
    {
      "source": {
        "web": {
          "site": "https://www.google.com."
        }
      },
      "relation": "delegate_permission/common.handle_all_urls",
      "target": {
        "androidApp": {
          "packageName": "com.google.android.calendar",
          "certificate": {
            "sha256Fingerprint": "F0:FD:6C:5B:41:0F:25:CB:25:C3:B5:33:46:C8:97:2F:AE:30:F8:EE:74:11:DF:91:04:80:AD:6B:2D:60:DB:83" }
        }
      }
    }
  ],
  "maxAge": "59.998761836s",
  "debugString": "********************* ERRORS *********************\nNone!\n********************* INFO MESSAGES *********************\n* Info: The following statements were considered when processing the request:\n\n---\nSource: Web asset with site https://www.google.com. (which is equivalent to 'https://www.google.com')\nRelation: delegate_permission/common.handle_all_urls\nTarget: Android app asset with package name com.google.android.calendar and certificate fingerprint F0:FD:6C:5B:41:0F:25:CB:25:C3:B5:33:46:C8:97:2F:AE:30:F8:EE:74:11:DF:91:04:80:AD:6B:2D:60:DB:83\nWhere this statement came from:\n  Origin of the statement: Web asset with site https://www.google.com. (which is equivalent to 'https://www.google.com')\n  Include directives followed (in order):\n    \u003cNone\u003e\nMatches source query: Yes\nMatches relation query: Yes\nMatches target query: Yes\n\n--- End of statement list. ---\n\n\n"
}

5.3、Testing a web URI intent

在确认了与你的app关联的网站并验证了网站的json文件之后,把app安装在你的手机上。然后等待至少20秒,使得异步的验证过程得以完成。
然后,使用以下命令判断系统是否已经验证了你的app并正确设置了link handling机制:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "http://<domain1>:<port>"

你还可以检测当前系统的link handling设置,使用以下命令可以获取当前系统对所有app的link handling设置:

adb shell dumpsys package domain-preferred-apps
 --or--
adb shell dumpsys package d

命令行返回的结果类似:

App linkages for user 0:

Package: com.android.vending
Domains: play.google.com market.android.com
Status: always : 200000002

结果展示了对于哪个用户而言,哪个app关联了哪个网站。

Package:app的包名
Domains:以空格分隔的此app能够处理的uri
Status:此app当前的link handling设置,如果通过了验证并且manifest文件包括android:autoVerify=true”,会显示“always”。后面的16进制数与系统记录用户app linkpage设置有关,不能表明验证的结果。

注意:如果用户在验证完成之前更改app link设置,那么不管验证结果,你都会看到成功。即使失败,也不会影响用户使用此app打开uri。这是因为用户设置优先于程序验证。

5.5、Test example

看下面的intent filters,

<application>

    <activity android:name=”MainActivity”>
        <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="http" android:host="www.example.com" />
            <data android:scheme="https" android:host="mobile.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="http" android:host="www.example2.com" />
        </intent-filter>
    </activity>

    <activity android:name=”SecondActivity”>
        <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:scheme="http" android:host="account.example.com" />
        </intent-filter>
    </activity>

      <activity android:name=”ThirdActivity”>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http" android:host="map.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="market" android:host="example.com" />
        </intent-filter>
      </activity>

</application>

根据Confirm the list of hosts to verify这一小节内容,其中只有几个host会被系统验证:

www.example.com
mobile.example.com
www.example2.com
account.example.com

不会被验证的原因是:

map.example.com (没有android.intent.category.BROWSABLE)
market://example.com (没有“http”或者“https” scheme)

六、广告

  • 手机如何连电脑?
  • 如何与电脑互发文件?
  • 如何与电脑互发文字?
  • 如何推送通知到电脑?
  • 电脑如何远程控制手机的相机?

快牙网传——全部搞定!

不想试试吗?
在豌豆荚等应用商店搜索“快牙网传“,或立即下载 Apk,也可以扫码下载。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值