用户在设备上访问链接是为了浏览他们期望访问的内容,通常的网页就是这种形式,可以通过 HTTP/HTTPS 链接直接访问到某个页面,而在 Android 平台,也提供了将页面直接跳转到链接指定的特定内容的能力,称之为 App links。
通过访问不同类型的链接,可以跳转不同的应用、网页,实现 H5 跳转 App、App 之间的页面跳转等效果。
链接的类型
在 Android 平台,可以将链接划分为三类:
- Deep links:深度链接,能处理所有协议的链接;
- Web links:网页链接,处理 HTTP/HTTPS 协议的链接;
- App links:应用链接,Android 应用程序链接在 Android 6.0(API 级别 23)及更高版本上可用,是使用 HTTP 和 HTTPS 方案并包含 autoVerify 属性的网页链接。
它们的关系如下图所示,三者属于包含关系:
深度链接 Deep Links
深度链接指的是支持任意的 scheme 协议的 URI 格式的链接,可将用户直接带到应用程序的特定页内容或逻辑;开发者可以自定义协议头(scheme),只要遵循 URI 标准格式即可。
通过在 AndroidManifest.xml
文件中的 <activity>
中配置 intent filter,将用户界引导到对应的 Activity:
xml
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<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="geo" />
</intent-filter>
</activity>
当用户单击或访问深度链接时,可能会出现一个对话框。 此对话框会列举出能够处理给定深度链接的多个应用程序列表,并让用户选择其中一个程序对深度链接进行处理。
例如,下图显示了用户单击地图链接后的对话框,询问是否在地图或 Chrome 中打开该链接。
网页链接 Web Links
Web 链接是使用 HTTP 和 HTTPS 协议的深度链接。在 Android 12 及更高版本中,点击网络链接(不是 Android 应用链接)始终会在网络浏览器中显示内容。
在运行早期版本 Android 的设备上,如果您的应用或用户设备上安装的其他应用也可以处理 Web 链接,则用户可能不会直接访问浏览器。 相反,他们会看到一个类似于图 2 中显示的选择处理程序的对话框。
以下代码片段显示了 Web 链接过滤器的示例:
xml
<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:host="myownpersonaldomain.com" />
</intent-filter>
应用链接 Android App Links
Android 应用程序链接在 Android 6.0(API 级别 23)及更高版本上可用,是使用 HTTP 和 HTTPS 方案并包含 autoVerify
属性的 Web 链接。autoVerify
属性的作用是将应用程序指定为特定类型链接的默认处理程序。当使用者点击这种类型的链接时,会向网站进行验证,验证通过,若已安装该应用程序,会默认启动该应用而不是出现可选程序对话框。
如果用户不希望您的应用程序成为默认处理程序,用户可以从应用程序的设置中覆盖此行为。
以下代码片段显示了 Android 应用程序链接过滤器的示例:
xml
<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" />
<data android:scheme="https" />
<data android:host="myownpersonaldomain.com" />
</intent-filter>
Android 应用程序链接具有以下优点:
- 安全且具体:Android 应用程序链接使用链接到您拥有的网站域的 HTTP URL,因此其他应用程序无法使用您的链接。 Android 应用程序链接的要求之一是您通过我们的网站关联方法之一验证您的域的所有权。
- 无缝的用户体验:由于 Android 应用程序链接对您的网站和应用程序中的相同内容使用单个 HTTP URL,因此未安装该应用程序的用户只需访问您的网站而不是应用程序 --- 没有 404,也没有错误。
- Android 即时应用程序支持:借助 Android 即时应用程序,您的用户无需安装即可运行您的 Android 应用程序。 要将 Instant App 支持添加到您的 Android 应用程序,请设置 Android 应用程序链接并访问 g.co/InstantApps。
使用指南
深度链接
通过在 AndroidManifest.xml
文件中的 <activity>
中配置 intent filter,将用户界引导到对应的 Activity:
xml
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<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="geo" />
</intent-filter>
</activity>
在浏览器或其他应用程序中访问满足处理条件的 URI,即可识别并跳转打开应用的指定内容。
网页链接
应用配置了HTTP/HTTPS 协议对特定域的响应,当访问特定域名的链接时,根据当前系统的版本会出现两种情况:
- 在 Android 12 及更高版本中,点击网络链接(不是 Android 应用链接)始终会在网络浏览器中显示内容。
- 在运行早期版本 Android 的设备上,如果您的应用或用户设备上安装的其他应用也可以处理 Web 链接,则用户可能不会直接访问浏览器。 相反,他们会看到一个类似于下图中显示的选择处理程序的对话框。
虽然默认会启动浏览器,但仍可使用 adb shell 来进行验证:
shell
adb shell am start
-W -a android.intent.action.VIEW
-d "http://myownpersonaldomain.com" yourpackagename
应用链接
应用链接是一种需要进行验证的网页链接,即在 中增加 autoVerify 属性,然后,在您的网站上发布 Digital Asset Links JSON 文件,以通过 Google Search Console 验证所有权。
第一步,配置 App 的清单文件:
xml
<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" />
<data android:scheme="https" />
<data android:host="myownpersonaldomain.com" />
</intent-filter>
第二步,配置 Digital Asset Links JSON 文件。
Digital Asset Links JSON 文件使用下列字段标识关联的应用:
package_name
:在应用的build.gradle
文件中声明的应用 ID。sha256_cert_fingerprints
:应用的签名证书的 SHA256 指纹。您可以利用 Java 密钥工具,通过以下命令生成该指纹:$ keytool -list -v -keystore my-release-key.keystore
。sha256_cert_fingerprints
字段支持多个指纹,这些指纹可用于支持不同版本的应用,例如调试版 build 和正式版 build。
以下 assetlinks.json
示例文件可为 com.example
Android 应用授予链接打开权限:
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"]
}
}]
可以在同一 assetlinks.json
文件内声明与多个应用的关联性。以下文件清单展示了一个声明示例文件,该文件分别声明了与两个应用的关联,并且位于 https://www.example.com/.well-known/assetlinks.json
中:
json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.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": "com.example.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"]
}
}]
最后部署到服务器指定目录下:
http
https://domain.name/.well-known/assetlinks.json
请确保以下几点要求:
- 使用内容类型
application/json
发布assetlinks.json
文件。 - 无论应用的 intent 过滤器是否将数据架构声明为 HTTPS,都必须可通过 HTTPS 连接访问
assetlinks.json
文件。 assetlinks.json
文件必须无需重定向即可访问(无 301 或 302 重定向),且可由漫游器访问(您的robots.txt
必须允许抓取/.well-known/assetlinks.json
)。- 如果您的应用链接支持多个主机域名,您必须在每个域名上分别发布
assetlinks.json
文件。 - 请勿发布清单文件中的开发/测试网址无法供公众访问的应用(例如,任何只可通过 VPN 访问的应用)。作为这种情况下的应急措施,您可以配置编译变体以针对开发编译版本生成不同的清单文件。
使用部分总结
创建 Android App 可处理链接的一般步骤如下:
- 创建指向应用中特定内容的深度链接:在应用的
AndroidMenifest.xml
中,为您的网站 URI 创建 IntentFilter,并将您的应用配置为使用 Intent 中的数据将用户引导至应用中的正确内容。
当用户点击链接或通过编程逻辑请求调用 Web URI 时,Android 系统会按顺序尝试以下每个操作,直到请求成功:
- 打开可以处理 URI 的用户首选应用程序(如果已指定)。
- 打开唯一可以处理 URI 的可用应用程序。
- 允许用户从对话框中选择应用程序。
注意:从 Android 12(API 级别 31)开始,仅当您的应用获得批准用于该 Web Intent 中包含的特定域名时,通用 Web Intent 才会解析为应用中的 Activity。 如果您的应用未获域名批准,则 Web 意图将解析为用户的默认浏览器应用(应用链接的验证部分)。
配置 Intent Filter
要创建指向应用内容的链接,请在清单中添加包含以下元素和属性值的 Intent Filter:
-
<action>
:指定为android.intent.action.VIEW
。 -
<data>
:添加一个或多个<data>
标签,每个标签代表解析为 Activity 的 URI 格式。<data>
标记必须包含android:scheme
属性。您可以添加更多属性来进一步细化 Activity 接受的 URI 类型。 例如,您可能有多个接受类似 URI 的 Activity,但它们的不同之处仅在于 path。 在这种情况下,请使用android:path
属性或其 pathPattern 或 pathPrefix 变体来区分系统应为不同的 URI 路径打开哪个 Activity。
-
<category>
:包括android.intent.category.BROWSABLE
。为了能够从 Web 浏览器访问 Intent Filter,这是必需的。如果没有它,单击浏览器中的链接将无法解析到您的应用程序;还包括android.intent.category.DEFAULT
,这允许您的应用程序响应隐式 Intent。如果没有这个,只有当意图指定您的应用程序组件名称时才能启动 Activity。
以下 XML 代码段显示了如何在清单中指定深度链接的 Intent Filter。 URI"example://gizmos"和"www.example.com/gizmos"均解析为... Activity:
xml
<activity
android:name="com.example.android.GizmosActivity"
android:label="@string/title_gizmos" >
<intent-filter android:label="@string/filter_view_http_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://www.example.com/gizmos" -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
</intent-filter>
<intent-filter android:label="@string/filter_view_example_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmos" -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
请注意,两个 Intent 过滤器仅在 元素上有所不同。 尽管可以在同一个过滤器中包含多个 元素,但当您打算声明唯一的 URL(例如方案和主机的特定组合)时,创建单独的过滤器非常重要,因为 相同的 Intent Filter 实际上合并在一起,以考虑其组合属性的所有变化。 例如,请考虑以下情况:
xml
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
<data android:scheme="app" android:host="open.my.app" />
</intent-filter>
看起来好像只支持 www.example.com 和 app://open.my.app。然而,它实际上支持这两个之外,也支持app://www.example.com 和 open.my.app 。
从 Intent 中读取数据
一旦系统通过 Intent 过滤器启动您的 Activity,您就可以使用 Intent 提供的数据来确定需要渲染的内容。 调用 getData() 和 getAction() 方法来检索与传入 Intent 关联的数据和操作。 您可以在 Activity 生命周期中的任何时间调用这些方法,但通常应该在早期回调(例如 onCreate() 或 onStart())期间执行此操作。
下面的代码片段展示了如何从 Intent 中检索数据:
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
val action: String? = intent?.action
val data: Uri? = intent?.data
}
测试
您可以将 Android 调试桥与活动管理器 (am) 工具结合使用来测试您为深度链接指定的意图过滤器 URI 是否解析为正确的应用活动。 您可以针对设备或模拟器运行 adb 命令。
使用 adb 测试意图过滤器 URI 的一般语法是:
shell
$ adb shell am start
-W -a android.intent.action.VIEW
-d <URI> <PACKAGE>
例如,以下命令尝试查看与指定 URI 关联的目标应用程序活动。
shell
$ adb shell am start
-W -a android.intent.action.VIEW
-d "example://gizmos" com.example.android
总结
深层链接 | 网页链接 | 应用链接 | |
---|---|---|---|
intent 网址架构 | http、https 或自定义架构 | 需要 http 或 https | 需要 http 或 https |
intent 操作 | 任何操作 | 需要 android.intent.action.VIEW | 需要 android.intent.action.VIEW |
intent 类别 | 任何类别 | 需要 android.intent.category.BROWSABLE 和 android.intent.category.DEFAULT | 需要 android.intent.category.BROWSABLE 和 android.intent.category.DEFAULT |
链接验证 | 无 | 无 | 需要通过 HTTPS 协议在您的网站上发布 Digital Asset Links 文件 |
用户体验 | 可能会显示一个消除歧义对话框,以供用户选择用于打开链接的应用 | 在 Android 12 及后续版本,仅能打开浏览器访问链接。 | 无对话框;您的应用会打开以处理您的网站链接 |
兼容性 | 所有 Android 版本 | Android 12.0 及更高版本为浏览器;低于 12,可能会打开对话框选择。 | Android 6.0 及更高版本 |