「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
之前无意间听别人提到DeepLink这个名词一脸懵逼,完全没听说过啊,很汗颜。因为一直从事Android TV开发,很少接触类似的概念,所以补充下下相关知识吧。
不同于WEB端通过Http链接就可以跳转到任意界面,出于各种各样的原因在移动端,不同App间和App与浏览器间是不能自由跳转的。这使得移动端APP成为一个个孤岛般的存在,为了将APP链接起来,使之可以在不同APP和APP与浏览器之间自由跳转,故退出了DeepLink相关技术。
Android原生跳转
在了解DeepLink之前我们先来看一下Android原生的页面跳转实现:
- 显式跳转
- 隐式跳转
显式跳转
-
声明
<activity android:name=".main.MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
-
跳转
val intent = Intent(this,MainActivity::class.java) intent.putExtra("param", "传值") startActivity(intent)
这种跳转是Android中最基础也最常用的页面跳转方式,通过指定目标Activity class对象或者指定完成的包名和类路径,实现页面跳转。这种方式显然不适合用在App间的自由跳转。
隐式跳转
-
声明
<activity android:name=".main.MainActivity" android:exported="true"> <intent-filter> <!-- 声明自定义Action --> <action android:name="com.zhong.action.TEST"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
-
跳转
val intent = Intent() intent.action = "com.zhong.action.TEST" intent.putExtra("param", "传值") startActivity(intent)
这种跳转方式不需要直接对目标Activity进行引用或者指定完整的类路径,只需要指定自定义的意图,系统就可以完成页面间的跳转。但是App中通常有多个页面,多个页面的Action的定义与维护就会成为问题,而且不同App之间的Action定义千差万别,依然不能很好的实现APP间的自由跳转。
DeepLink
深层链接,是一种使用Uri链接实现跳转到APP任意界面的技术,可以实现在网页和app间自由跳转。
为了更好的理解,我们在看几个常见的适用场景:
-
场景一
当我们在淘宝/京东等电商app中进行商品分享,通常会在app复制商品链接,然后通过微信/短信等通讯工具,分享给对方。如何实现对方打开链接之后直接跳转到电商app而不是打开网页或者进入电商app手动搜索呢?
-
场景二
我们发动分享链接之后,如果对方没有安装对应的app,我们希望可以跳转到应用市场进行下载,并且在下载完成之后启动app直接跳转到分享商品的界面,有如何实现呢?
-
场景三
我们通过浏览器搜索商品后,点击商品可以自动打开电商app并展示商品页面,或者在商品网页上显示“用app打开页面”,点击后跳转app并展示商品页面,又如何实现呢?
上述三种都是DeepLink方案的适用场景。
适用DeepLink可以带来以下好处:(直接引用Google官方的说明,并不很准确了,基本意思理解到就可以了)
- 安全且具体:Android 应用链接使用链接到您自己的网站网域的 HTTP 网址,因此其他应用都无法使用您的链接。Android 应用链接的要求之一,就是您要通过我们的某个网站关联方法验证您对网域的所有权。
- 顺畅的用户体验:由于 Android 应用链接针对您的网站和应用中的相同内容使用单个 HTTP 网址,因此未安装应用的用户会直接转到您的网站(而不是应用),不会显示 404,也不会出现错误。
- Android 免安装应用支持:借助 Android 免安装应用,用户无需安装即可运行您的 Android 应用。如需向您的 Android 应用添加免安装应用支持,请设置 Android 应用链接并访问 g.co/InstantApps。
- 通过 Google 搜索吸引用户:用户可以通过在移动浏览器、Google 搜索应用、Android 中的屏幕搜索中或通过 Google 助理点击来自 Google 的网址,直接打开应用中的特定内容。
DeepLink实现
<activity
android:name=".main.SecondActivity"
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="zhong"
android:host="www.zhong.com"
android:pathPrefix="/second" />
</intent-filter>
</activity>
-
Action
为了响应系统跳转意图,需要将Action指定为
android.intent.action.VIEW
。 -
category
添加
android.intent.category.DEFAULT
来响应系统隐式跳转请求。添加
android.intent.category.BROWSABLE
是为了响应浏览器跳转请求,如果需要从浏览器中启动app,或者支持点击http链接跳转app,需要添加此category。 -
data
-
android:scheme——URI 的架构部分。
- 必须指定,要不然后面的属性无效。
- 指定的架构应不带尾随冒号(例如,应指定
http
,而不是http:
),通常使用小写。 - 支持自定义或者使用http/https,如果想实现在浏览器中点击url跳转,需要指定http/https。
-
android:host——URI 授权方的主机部分.
- 必须指定,要不然后面的属性无效。
- 支持第一个属性使用(*)做通配符,如:
*.google.com
- 支持自定义,如果scheme是http/https需要指定有意义的域名。
-
android:port URI 授权方的端口部分。
- 可省略
- 指定端口,不解释
-
android:path/pathPrefix/pathPattern
-
都是指定匹配路的。
-
必须以
/
开头。 -
path
- 匹配完整路径
-
pathPrefix
- 只与 Intent 对象中的路径的初始部分匹配的部分路径
-
pathPattern
- 匹配完成路径,但支持通配符(
*
) - 星号(“
*
”)匹配出现零次到多次的紧邻前面的字符的一个序列。 - 句点后跟星号(“
.*
”)匹配零个到多个字符的任意序列。
- 匹配完成路径,但支持通配符(
-
好像有点绕,举个例子:
intent跳转路径
http://www.zhong.com/second/test
,三种类型模式需要匹配需要写成:-
path ——
/second/test
-
pathPrefix ——
/second
-
pathPattern ——
/second/*
-
-
-
有时候我们可能需要指定多组intent过滤器,比如想同时支持android:scheme
使用自定义和http,需要定义多组<intent-filter>
,而不能在一组<intent-filter>
定义多个<data>
。
<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>
直接应用官方解释吧:
请注意,
<data>
元素是这两个 intent 过滤器的唯一区别。虽然同一过滤器可以包含多个<data>
元素,但如果您想要声明唯一网址(例如特定的scheme
和host
组合),则创建单独的过滤器很重要,因为同一 intent 过滤器中的多个<data>
元素实际上会合并在一起以涵盖合并后属性的所有变体。例如,请参考以下示例:
<intent-filter> ... <data android:scheme="https" android:host="www.example.com" /> <data android:scheme="app" android:host="open.my.app" /> </intent-filter>
看起来这似乎仅支持
https://www.example.com
和app://open.my.app
。但是,实际上除了这两种之外,它还支持app://www.example.com
和https://open.my.app
。
参数接收与跳转
-
参数接收,通过intent接收参数
val appLinkAction = intent.action val appLinkData: Uri? = intent.data if(appLinkAction == Intent.ACTION_VIEW){ val lastPathSegment = appLinkData?.lastPathSegment val host = appLinkData?.host val scheme = appLinkData?.scheme val params = appLinkData?.pathSegments Log.d(TAG, "parseUri: lastPathSegment " + lastPathSegment + " host = " + host + " scheme = " + scheme) }
-
跳转
val intent = Intent() intent.setCalss() intent.data = Uri.parse("http://wwww...../aa") startActivity(intent)
adb跳转:
adb shell am start -a android.intent.action.VIEW -d "http://www...../aa"
AppLink
通过上面的方法我们定义了如下的DeepLink:
<activity
android:name=".main.SecondActivity"
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="http"
android:host="www.zhong.com"
android:pathPrefix="/second" />
</intent-filter>
</activity>
当在浏览器或者短信中点击链接http://www.zhong.com/second
系统会弹出应用选择对话框(也称为消除歧义对话框),来让用户选择处理此内容的app是哪个。这样使得用户操作流程不顺畅,为了避免这个问题,Google在Android 6.0之后提供AppLink功能(只支持Android 6.0+设备)。
AppLink会在应用安装时,去指定scheme和hots的地址查询对应的配置文件,如果匹配成功,会把此应用作为此URL的默认打开应用,也就是说之后打开上面链接不会在弹出应用选择对话框,而是直接用app打开URL,当然用户可以在设置中手动修改默认打开应用。
如果应用安装时,验证失败、设备未联网或者设备是Android 6.0以下,AppLink会自动退化为DeepLink,而不影响使用。
AppLink相比DeepLink添加了更多约束条件:
-
android:scheme必须是http或者https
-
android:host必须是有效的服务器域名
-
添加
android:autoVerify="true"
属性<intent-filter android:autoVerify="true" > <!-- ... --> </intent-filter>
AppLink的相关配置方法参考官方链接:添加 Android 应用链接
参考链接: