当前位置: 首页 > news >正文

Android进阶之路 - 从 URL Scheme 到 Deep Link 与 App Link

看很多人分享了 Deep Link 、App Links 的官方文档,发现挺多都看不了,大家有兴趣的话也可以直接前往 官方首页,国内适用 查询相关文档

Deep Link、Deep Links、App Link、App Links 有没有什么区别?其实区别不大,只是一个单复数概念,因为它们的配置项可兼容场景较多,所以自行根据场景定义就好

关联篇

  • Android进阶之路 - 从 URL Scheme 到 Deep Link 与 App Link
  • Android实战进阶 - 通过Scheme和App Link响应外部调用

快速度过认生期

    • Scheme 基础
    • Deep Link 、App Link
      • 基础共性
      • Deep Links
      • App Link
    • 三方唤起App方式
      • 浏览器调用
      • 原生调用

在官方文档中看到这样一张图,大家可以简单看一下它们之间的关系

在这里插入图片描述

你遇到了什么业务需求(应用场景)才来了解 Deep Link 、App Link? 如果想要支持以下类似场景,那么就需要我们App予以支持

通过AI直接搜的应用场景,我就不画蛇添足了

  • 在抖音、微博或朋友圈看到了一个广告,点击后不是跳转到浏览器,而是直接打开对应App的商品详情页、活动页或视频页
  • 从App A(如邮箱客户端)点击一个特定链接,直接跳转到App B(如你的应用)的某个页面。或者在你公司旗下的多个App之间相互跳转
  • 向沉默用户推送一条PUSH消息,内容是其收藏商品降价了。用户点击通知栏消息,直接跳转到App内的商品页
  • 线下海报、商品包装上印有一个二维码。用户用手机相机或扫码工具扫描后,直接打开App对应页面(如领取优惠券、查看产品信息)
    社交媒体营销与广告投放
  • 给用户发送一条营销短信,里面包含一个链接。用户点击后,如果安装了App则直接打开,否则跳转到应用市场或备用网页
  • 用户在Google搜索结果、Gmail邮件或Chrome浏览器中点击一个属于你App的链接(如https://www.myapp.com/product/123)。系统会直接打开你的App,而不会弹出选择器询问用户(App Link 特性
  • 你拥有一个网站 www.myapp.com 和一个对应的Android App。你希望确保所有指向你网站的链接,在用户安装了App的情况下,都由你的App来处理,而不是浏览器。(App Link 特性
  • 用户经常通过搜索引擎访问你的移动版网站。当用户安装了App后,所有来自搜索、社交分享的你网站的链接,都会直接在你的App中打开,从而将Web流量转化为App的活跃度(App Link 特性

Scheme 基础

不论是 Deep Link 还是 App Link 都涉及到了 schame 基础,所以整体都梳理一次,统一下我自己的答疑解惑

我们以 https://blog.csdn.net/qq_20451879 来分析下Scheme组成

  • Scheme(协议):常见的有 http、https协议;(此处: https 协议)
  • Host(主机、域名):三方的域名基本不同,一般属于类似网络身份证;(此处:blog.csdn.net)
  • Path(路径):在很多场景中我们需要定义到具体页面(目标页面),这里一般都是通过path来进行定位的;(此处:qq_20451879)
  • Query(参数):传递数据的键值对(可以参考 https://blog.csdn.net/qq_20451879/article/details/151584530?spm=1001.2014.3001.5501 ,其中 ?spm=1001.2014.3001.5501 就是所携带的参数)
  • Port(端口):默认端口可不做特殊声明,一般不用关注
<activityandroid:name=".SchemeActivity"android:theme="@style/AppTheme"><!--要想在别的App上能成功调起App,必须添加intent过滤器--><intent-filter><!--协议部分,随便设置--><dataandroid:scheme="https" android:host="blog.csdn.net" android:path="/qq_20451879" /><!--通用设置,主要是支持游览器、新开界面、以及一些默认配置--><category android:name="android.intent.category.DEFAULT"/><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.BROWSABLE"/></intent-filter></activity>

Deep Link 、App Link

Deep LinkApp Link 更适用于 Android 端,之前看别人Blog下的评论,如果公司要走android、ios、web等多个平台,大多会使用三方框架,其中提到了 Firebase Dynamic Link 框架,有兴趣的可以去了解

关于怎么理解俩者之间的关系,很多人有不同的看法,在我看来你可以把它们看做独立的个体,也可以把它们看成历史的迭代

基础共性

之所以将 Deep LinkApp Link 放在一起讲解,个人认为主要是他们就像是新老版本的迭代,有点像 ListView vs RecyclView 历史关系,又有点像父子之间的继承关系,又有点像策略模式的实现方式?

其实在实战开发中,我们通常都会同步配置 Deep LinkApp Link!而之所以这样做的原因是当 App Link 验证失败的情况下,Deep Link 可进行兜底处理

Deep Link 调起流程
在这里插入图片描述
App Link 调起流程

在这里插入图片描述

首先通过实现 Deep LinkApp Link 都可以响应外部调用,不过具体选用哪一个?还有要根据场景来看,我们先从不同维度看一下它们的区别

区别Deep LinkApp Link
适用版本Android 全系列版本Android 6.0之后
适用协议支持自定义scheme仅支持 http、https协议
安全验证不做验证需要客户端生存安全稳健存储于,验证所有权
用户体验通常会弹框,让用户选择打开方式默认直接启动我们目标App(体验更好

关于 AndoirdMainfest 中的 action、category 配置项,建议统一加入

  <action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" />

那么为什么Android 6.0 特意推出了 App Link ?继续使用 Deep Link 不好吗?意义是什么? 我们继续换个角度来研究下

App Link 优点Deep Link 不足
用户体验支持App直接打开中间多一步选择操作,体验不足
安全验证加入了验证机制,更安全不具备该项保护

我多次提到了用户体验,直接看图就可以明白 Deep LinkApp Link 俩者调起区别(因为没有写完整demo,篇中直接拿了几张 别人的效果图用一下…)

Deep Link 调起结果

在这里插入图片描述
App Link 调起结果
在这里插入图片描述

课外学堂

不知道你会不会有以下这种配置方式的想法?通常情况下浏览器都会监听全部的http和https协议的链接,但是App这样做的意义好像并不大

<intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><dataandroid:host="*"android:scheme="http" /><dataandroid:host="*"android:scheme="https" />
</intent-filter>

关于源码部分,我们就先不追了,有兴趣的可以直接去看 Android DEPPLINK、APPLink原理简析


Deep Links

关于Deep Links的官方文档,没找到太多,大家可以先看这个 Create Deep Links to App Content

DeepLink 是 Android系统最基础、最普遍、最广泛的外部唤起App的方式,不受系统版本限制,支持当用户点击一个链接时,系统默认按以下顺序打开:

  • 如果你设置了默认打开应用,则优先使用该应用打开
  • 如果只有一个应用能打开,则直接用该应用打开
  • 如果有多个应用能打开,才会弹出应用选择框

Deep Link 支持自定义scheme协议,类似以下配置

        <!-- DeepLink适用所有版本,支持自定义协议 --><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><!-- 自定义协议 --><dataandroid:host="l.nian.com"android:scheme="ly" /><dataandroid:host="l.nian.com"android:scheme="custom" /><!--常见协议 --><dataandroid:host="l.nian.com"android:scheme="http" /><dataandroid:host="l.nian.com"android:scheme="https" /></intent-filter>

App Link

Android App Links 是指可将用户直接带往 Android 应用内特定内容的 HTTP 网址。帮助您发现最常用的应用内容,并让用户更轻松地在已安装的应用中查找和分享内容。

Tip:关于 App Link 的部分解析,摘自官方文档;如有疑问,可直接前往 添加 Android App Links 、验证 Android 应用链接

Android 应用链接是一种特殊类型的深层链接,可让您的网站网址直接在您的 Android 应用中打开相应内容,无需用户选择应用。

Android 应用链接使用 Digital Asset Links API 来建立信任关系,表明您的应用已获得网站的批准,可以自动打开相应网域的链接。如果系统成功验证您是网址所有者,则会自动将这些网址 intent 路由到您的应用。

个人经验,以下几点 AndroidMainfest 中 Link 类 配置需要注意

  • 设置 exported="true" ,需要支持被外部调用
  • App Links 设置 android:autoVerify="true",安全校验
  • App Links 仅支持 http、https 协议

若要添加对 Android App Links 的支持,请执行以下操作:

  • :在清单中创建 intent 过滤器

关于这一点,其实俩种实现方式,当然最后结果是一样的

第一种:通过 Android Studio > Tools > App Links Assistant 生成 相应的 intent-filter 信息(关于这种方式,如果以后有机会的话,我会记一下,因为目前项目成型,缺少整体实战,所以相应延后…)

在这里插入图片描述

生成的类似结果(如果设置了 host 之类,应该会更详细一些,这里抄自)

<!-- Make sure you explicitly set android:autoVerify to "true". -->
<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" /><!-- If a user clicks on a shared link that uses the "http" scheme, yourapp should be able to delegate that traffic to "https". --><!-- Do not include other schemes. --><data android:scheme="http" /><data android:scheme="https" /><!-- Include one or more domains that should be verified. --><data android:host="..." />
</intent-filter>

第二种直接开卷抄一下,改一改,用起来(比较建议)

  • :将代码添加到应用的 activity 中以处理传入链接

最终结果(实战篇),类似如下

        <activityandroid:name=".SchemeActivity"android:exported="true" android:theme="@style/SplashTheme"><!-- DeepLink适用所有版本,支持自定义协议 --><intent-filter><dataandroid:host="l.nian.com"android:scheme="ly" /><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /></intent-filter><!-- App Links (autoVerify必加,安全验证)适用于6.0之后--><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" /><!-- App Links 支持仅http、https协议,一般都会做兼容处理--><dataandroid:host="l.nian.com"android:scheme="http" /><dataandroid:host="l.nian.com"android:scheme="https" /></intent-filter></activity>

在址映射正常运行后,请添加逻辑以处理您创建的 intent(这其实我们接收到三方调用后的处理逻辑了)

  1. 点击 App Links Assistant 中的 Select Activity
  2. 从列表中选择一个 activity,然后点击 Insert Code

根据上方操作生成的伪代码

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)...// ATTENTION: This was auto-generated to handle app links.val appLinkIntent: Intent = intentval appLinkAction: String? = appLinkIntent.actionval appLinkData: Uri? = appLinkIntent.data...
}

稍微正常点的伪代码,需要自己根据业务做逻辑处理

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)...handleIntent(intent)
}override fun onNewIntent(intent: Intent) {super.onNewIntent(intent)handleIntent(intent)
}private fun handleIntent(intent: Intent) {val appLinkAction = intent.actionval appLinkData: Uri? = intent.dataif (Intent.ACTION_VIEW == appLinkAction) {appLinkData?.lastPathSegment?.also { recipeId ->Uri.parse("content://com.recipe_app/recipe/").buildUpon().appendPath(recipeId).build().also { appData ->showRecipe(appData)}}}
}
  • :使用 Digital Asset Links 将应用与网站相关联

在此之前的操作,都可以算是基础配置,重要的还是要 将应用与网站相关联

在为您的应用设置网址支持后,App Links Assistant 会生成一个 Digital Asset Links 文件,您可以使用该文件将网站与应用相关联。

提示 - 国内可忽略:除了使用 Digital Asset Links 文件,您还可以在 Search Console 中将您的网站与应用相关联(GSC,谷歌搜索控制台)

必须在网站上发布 Digital Asset Links JSON 文件,以指示与网站相关联的 Android 应用并验证应用的网址 intent ,发布 JSON 验证文件有以下几点需要注意

  • 使用内容类型 application/json 发布 assetlinks.json 文件。
  • 无论应用的 intent 过滤器是否将数据架构声明为 HTTPS,都必须可通过 HTTPS 连接访问 assetlinks.json 文件。
  • assetlinks.json 文件必须可直接访问,没有任何重定向(无 301 或 302 重定向)。
  • 如果您的应用链接支持多个主机网域,您必须在每个网域上分别发布 assetlinks.json 文件。请参阅支持多个主机的应用链接。
  • 请勿发布清单文件中的开发/测试网址无法供公众访问的应用(例如,任何只可通过 VPN 访问的应用)。作为这种情况下的应急措施,您可以配置 build 变体以针对开发 build 生成不同的清单文件

assetlinks.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 中:

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

不同的应用可以处理同一网络主机下的不同资源对应的链接。例如,应用 1 可能声明了一个对应于 https://example.com/articles 的 intent 过滤器,而应用 2 可能声明了一个对应于 https://example.com/videos 的 intent 过滤器。

  • 将多个网站与同一应用相关联
    多个网站可在各自的 assetlinks.json 文件中声明与同一应用的关联性。以下文件列表示例展示了如何声明 example.com 和 example.net 与 app1 的关联性。第一个列表展示了 example.com 与 app1 的关联性:

https://www.example.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"]}
}]

下一个列表展示了 example.net 与 app1 的关联性。唯一的区别是托管这些文件的位置不同(.com 和 .net):

https://www.example.net/.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"]}
}]

Android App Links 验证

当应用的至少一个 intent 过滤器中存在 android:autoVerify="true" 时,在搭载 Android 6.0(API 级别 23)或更高版本的设备上安装应用会导致系统自动验证与应用 intent 过滤器中的网址相关联的主机。在 Android 12 及更高版本中,您还可以手动调用验证流程来测试验证逻辑(手动验证不如直接用Android Studio提供的工具,有机会再讲,主要看自动验证)

系统的自动验证涉及以下方面:

  1. 系统会检查所有包含以下任意项的 intent 过滤器
    • 操作:android.intent.action.VIEW
    • 类别:android.intent.category.BROWSABLE 和 android.intent.category.DEFAULT
    • 数据架构:http 或 https
  2. 对于在上述 intent 过滤器中找到的每个唯一主机名,Android 会在 https://hostname/.well-known/assetlinks.json 查询 Digital Asset Links 文件的相应网站。

三方唤起App方式

这里指的主要是在不同场景下,三方 如何调用我们写的 Deep LinkApp Link

浏览器调用

如果采用的是 Deep Link 的自定义scheme,可能会导致部分浏览器不支持,同时存在信息泄漏安全风险

<a href="https://blog.csdn.net/qq_20451879">Blog主页</a>

原生调用

  Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("https://blog.csdn.net/qq_20451879"));startActivity(intent);

在实际使用中,或许你会用到以下几个小方法

  1. 关于 App 获取三方传值的方式都基本类似,可以先参考以下伪代码
val data:Uri? = intent.data // https://yuwen.ggl.cn/app?a=123&b='ggl'
val scheme:String? = data?.scheme // https
val host:String? = data?.host // yuwen.ggl.cn
val path:String? = data?.path // /app
val valueA:String? = data?.getQueryParameter("a") // 123
val valueB:String? = data?.getQueryParameter("b") // 'ggl'
  1. 获取Scheme跳转的参数(Java版本)
Uri uri = getIntent().getData();
if (uri != null) {// 完整的url信息String url = uri.toString();Log.e(TAG, "url: " + uri);// scheme部分String scheme = uri.getScheme();Log.e(TAG, "scheme: " + scheme);// host部分String host = uri.getHost();Log.e(TAG, "host: " + host);//port部分int port = uri.getPort();Log.e(TAG, "host: " + port);// 访问路劲String path = uri.getPath();Log.e(TAG, "path: " + path);List<String> pathSegments = uri.getPathSegments();// Query部分String query = uri.getQuery();Log.e(TAG, "query: " + query);//获取指定参数值String goodsId = uri.getQueryParameter("goodsId");Log.e(TAG, "goodsId: " + goodsId);
}
  1. 如何判断一个Scheme是否有效
PackageManager packageManager = getPackageManager();
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://blog.csdn.net/qq_20451879"));
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
boolean isValid = !activities.isEmpty();
if (isValid) {startActivity(intent);
}
http://www.dtcms.com/a/389197.html

相关文章:

  • MySQL监控Shell脚本实战指南
  • 【Android】Jetpack Media3 如何播放音频文件 实现视频播放器
  • Android 开发 集成 uni 小程序,并实现相互通信
  • 【office】怎么设置第一章二级标题为1.1 1.2 1.3然后第二章为2.1 2.2 2.3这样子
  • JVM的垃圾回收机制(一次完整的GC流程)
  • 拥抱新一代 Web 3D 引擎,Three.js 项目快速升级 Galacean 指南
  • Linux 内核裁剪与功能扩展实验报告
  • Qt QVCandlestickModelMapper详解
  • LeetCode:20.旋转图像
  • 网络协议深度解析:从OSI七层模型到现代互联网通信的技术实战
  • 慈明学校以孝治家阳光家庭教育中心 学以致用践行以孝治家幸福万家
  • 开心实习之 深度学习之多层感知机
  • 前端构造数据格式及表格添加行
  • 深度学习-神经网络(上篇)
  • 【脑电分析系列】第18篇:传统机器学习在EEG中的应用 — SVM、LDA、随机森林等分类器
  • 理解长短期记忆神经网络(LSTM)
  • Kurt-Blender零基础教程:第2章:建模篇——第1节:点线面的选择与控制与十大建模操作
  • 鸿蒙5.0应用开发——V2装饰器@Monitor的使用
  • 八、Java-XML
  • 计算机在医疗领域应用的独特技术问题分析
  • HTB Intentions writeup(SQL二次注入也是注入)
  • 第一章 预训练:让模型“博闻强识”
  • 【数组】求两个匀速运动质点的相交或最小距离
  • 新手向:Python爬虫原理详解,从零开始的网络数据采集指南
  • OKZOO进军HealthFi:承接AIoT,引领Health-to-Earn
  • Halcon 相机标定
  • 腾讯混元发布集成翻译模型Hunyuan-MT-Chimera-7B,已开放体验
  • mybatis-plus扩展
  • 从x.ai到VSCode:一个AI编程助手的意外之旅
  • SQLite vs MySQL:核心SQL语法差异全面解析