Deeplink实践原理分析
目录介绍
- 01.先看一个场景
- 02.什么是DeepLink
- 03.什么是Deferred DeepLink
- 04.什么是AppLink
- 05.DeepLink和AppLink核心技术
- 06.DeepLink实践方案
- 07.AppLink实践方案
- 08.部分问题思考总结
- 09.DeepLink原理分析
- 10.AppLink原理分析
01.先看一个场景
- 假设一个场景:
- 小明告诉小杨,一鹿有车APP上有一个很有创意的抽奖活动,小新想要参与这个活动
- 如果小杨已经安装了APP,他需要找到且打开APP,然后找到相应的活动,共计2步;
- 如果小杨没有安装APP,他需要在应用市场搜索一鹿有车APP、下载、打开APP且找到相应的活动,共计4步;
- 关于那些途径实现
- 通过短信息,比如收到脉脉好友信息,通过短信息打开app跳转制定页面。
- 通过短信息,比如收到天猫推荐消息,通过短信息打开浏览器,然后通过浏览器跳转指定页面。
- 通过分享到微信中h5页面,在微信中打开app(这个需要到微信开放平台做配置,其实是微信——>应用宝——>app指定页面)。
- 小明告诉小杨,一鹿有车APP上有一个很有创意的抽奖活动,小新想要参与这个活动
- 提出的需求:
- 在浏览器或者短信中唤起APP,如果安装了就唤起,否则引导下载。对于Android而言,这里主要牵扯的技术就是deeplink,也可以简单看成scheme,Android一直是支持scheme的,本文只简单分析下link的原理,包括deeplink,也包括Android6.0之后的AppLink。
- 其实,AppLink就是特殊的deeplink,只不过它多了一种类似于验证机制,如果验证通过,就设置默认打开,如果验证不过,则退化为deeplink,如果单从APP端来看,区别主要在Manifest文件中的android:autoVerify="true"。
- 既而,在微信中,也可以作出这样操作。如果用户已经安装app,点击跳转app则会通过应用宝,打开该应用并且跳转到相应的页面。这种也是一种AppLink。
- 然后看看下面截图
- 提出的问题
- 1.如何实现点击自己的网站跳到我们的App而不是任意的链接?
- 2.通过链接跳转到App中不同的页面,应该怎么做?某些页面需要参数,如何携带参数?
- 3.短信中,有时候看到的链接并非http或者https开头,短信息是如何识别这是一个链接,而不是一个字符串?具体看上面的短信截图……
- 4.出现了一个弹框让我二次确认(一般是选择浏览器,只要是浏览器,都会相应http或者http开头的shceme,如果你的APP安装了多个浏览器,都会出现在这个弹框的选项中),如何去掉这个恶心的选择浏览器的的弹框?
- 5.短信息中常见的非http或者https开头的链接,究竟是如何生成的,是怎么来的?
- 6.scheme协议跳转的原理是什么?微信打开app的原理是什么?
- 7.跳转指定页面,有的需要传递参数,有的参数是url,如何避免被非法篡改?
- 8.跳转指定页面,有的页面需要登录才能进入,没有登录则先跳转登录页面,登录了才跳转指定页面,这种如何操作?
02.什么是DeepLink
- 什么是DeepLink
- 移动端深度链接,简称deeplink。这是一种通过uri链接到app特定位置的一种跳转技术,不单是简单地通过网页、app等打开目标app,还能达到利用传递标识跳转至不同页面的效果。
03.什么是Deferred DeepLink
- 什么是Deferred DeepLink
- 相比DeepLink,它增加了判断APP是否被安装,用户匹配的2个功能;
- 1.当用户点击链接的时候判断APP是否安装,如果用户没有安装时,引导用户跳转到应用商店下载应用。
- 2.用户匹配功能,当用户点击链接时和用户启动APP时,分别将这两次用户Device Fingerprint(设备指纹信息)传到服务器进行模糊匹配,使用户下载且启动APP时,直接打开相应的指定页面。
- 相比DeepLink,它增加了判断APP是否被安装,用户匹配的2个功能;
04.什么是AppLink
- 什么是AppLink
- AppLink相对复杂,需要App与Web协作完成系统验证,但可以保证直接唤起目标App,无需用户二次选择或确认。
05.DeepLink和AppLink核心技术
- DeepLink和AppLink不同点。下面这个总结很重要!
不同点 DeepLink AppLink Intent scheme 任意 要求http或https Intent action 任意Action 要求配置andorid.intent.action.VIEW Intent category 任意Category 要求配置android.intent.category.BROWSABLE和android.intent.category.DEFAULT 链接认证 无需验证 要求进行Digital Asset Links文件验证 用户体验 可能展示一个多选项弹窗或确认弹窗,用户需要二次选择或确认 无弹窗,直接由App处理链接 兼容性 所有版本 Android6.0及以上版本 - DeepLink和AppLink用到的核心技术
- URL SCHEMES。不论是IOS还是Android。
- 比如微信:URL Schemes:weixin://dl/moments(打开微信朋友圈)
- DeepLink与AppLink,本质上都是基于Intent框架,使App能够识别并处理来自系统或其他App的某种特殊URL,在原生App之间相互跳转,实现良好的用户体验
06.DeepLink实践方案
- 1.指定scheme跳转规则,关于scheme的协议规则,这里不作过多解释,[scheme]://[host]/[path]?[query]。比如暂时是这样设定的:yilu://link/?page=main。
- 2.被唤起方,客户端需要配置清单文件activity。关于SchemeActivity注意查看下面代码:
- 为什么要配置intent-filter,它是针对你跳转的目标来讲的,比如你要去某个朋友的家,就类似于门牌的修饰,他会在门牌上定义上述介绍的那些属性,方便你定位。当有intent发送过来的时候,就会筛选出符合条件的app来。
- action.VIEW是打开一个视图,在Android 系统中点击链接会发送一条action=VIEW的隐式意图,这个必须配置。
- category.DEFAULT为默认,category.DEFAULT为设置该组件可以使用浏览器启动,这个是关键,从浏览器跳转,就要通过这个属性。
- 解析数据的操作
- 3.唤起方也需要操作
- 4.关于问题疑惑点解决方案
- 配置了scheme协议,测试可以打开app,但是想跳到具体页面,携带参数,又该如何实现呢?
- 比如则可以配置:yilu://link/?page=car&id=520,则可以跳转到汽车详情页面,然后传递的id参数是520。
- 5.跳转页面后的优化
- 通过以上规则匹配上,你点击跳转以后,如果用户结束这个Activity的话,就直接回到桌面了,这个是比较奇怪的。参考一些其他app,发现不管是跳转指定的几级页面,点击返回是回到首页,那么这个是如何做到的呢?代码如下所示
- 6.短信息竟无法识别scheme协议?
- 把yilu://link/?page=main以短信息发送出去,然后在短信息里点击链接,发现在短信里面添加的链接自定义的scheme被认为不是一个scheme……可见终究跳不开的http/https访问。
- 7.如何将一个http或https链接生成短链接
- 这个很容易,直接找个短链接生成的网站,然后把链接转化一下就可以。至于转化的原理,我暂时也不清楚……
07.AppLink实践方案
- 1.Android App Links是一种特殊的Deep Links
- 它使Android系统能够直接通过网站地址打开应用程序对应的内容页面,而不需要用户选择使用哪个应用来处理网站地址。
- 要添加Android App Links到应用中,需要在应用里定义通过Http(s)地址打开应用的intent filter,并验证你确实拥有该应用和该网站。如果系统成功验证到你拥有该网站,那么系统会直接把URL对应的intent路由到你的应用。
- 2.和Deep Link对比多些约束条件
- APP Link 多了许多约束条件,比如scheme必须是http或者https的,但是体验更好,没有用户选择弹框,(实测下来,原生系统直接唤起来,大部分定制系统会提示是否打开链接,如果用户确认以后,就直接跳到APP)调起APP之后逻辑都一样,可以用同样的方式取数据等。
- 3.Manifest文件中添加配置如下
- 最关键的是这个:android:autoVerify="true"。那这个属性是干嘛的呢?是为了验证我们点击的链接和我们的APP是否有关联。具体如何验证呢?接着往下看:
- 当android:autoVerify="true"出现在你任意一个intent filter里,在Android6.0及以上的系统上安装应用的时候,会触发系统对APP里和URL有关的每一个域名的验证。验证过程设计以下步骤:
- 系统会检查所有包含以下特征的intent filter:Action为 android.intent.action.VIEW、Category为android.intent.category.BROWSABLE和android.intent.category.DEFAULT、Data scheme为http或https
- 对于在上述intent filter里找到的每一个唯一的域名,Android系统会到对应的域名下查找数字资产文件,地址是:https://域名/.well-known/assetlinks.json
- 只有当系统为AndroidManifest里找到的每一个域名找到对应的数字资产文件,系统才会把你的应用设置为特定链接的默认处理器。
- 4.需要添加验证操作
- 为了验证你对应用和网站的所有权,以下两个步骤是必须的:
- 1.在AndroidManifest里要求系统自动进行App Links的所有权验证。这个配置会告诉Android系统去验证你的应用是否属于在intent filter内指定的URL域名。
- 2.在以下链接地址里,放置一个数字资产链接的Json文件,声明你的网址和应用之间的关系。需要一个服务端文件让APP知道关联关系,APP,在安装的时候会去校验这个文件,校验文件上声明的应用包名、文件所在的域名、以及文件声明的APP密钥,是否能和app中的配置匹配上,如果匹配上了,在点击该域名下的任何链接的时候,都会直接定向到我们的APP。
- 关于json文件的内容如下所示:
- package_name:在build.gradle里定义的application ID
- sha256_cert_fingerprints:应用签名的SHA256指纹信息。你可以用下面的命令,通过Java keytool来生成指纹信息:$ keytool -list -v -keystore my-release-key.keystore
- json文件的注意点
- 这个文件的格式的content-type必须是application/json
- 这个文件只能放在https的链接中,不管你之前在action中声明的是http或者https
- 这个文件不能有任何重定向,并且必须是以/.well-known/assetlinks.json 后缀结尾
- 你也可以在这个文件上声明多个APP,注意看它的格式,是一个list
09.DeepLink原理分析
- deeplink的scheme相应分两种:一种是只有一个APP能相应,另一种是有多个APP可以相应,比如,如果为一个APP的Activity配置了http scheme类型的deepLink,如果通过短信或者其他方式唤起这种link的时候,一般会出现一个让用户选择的弹窗,因为一般而言,系统会带个浏览器,也相应这类scheme。这里就不举例子了,因为上面已经已经提到呢。当然,如果私有scheme跟其他APP的重复了,还是会唤起APP选择界面(其实是一个ResolverActivity)。下面就来看看scheme是如何匹配并拉起对应APP的。
- startActivity入口与ResolverActivity
- 无论APPLink跟DeepLink其实都是通过唤起一个Activity来实现界面的跳转,无论从APP外部:比如短信、浏览器,还是APP内部。通过在APP内部模拟跳转来看看具体实现,写一个H5界面,然后通过Webview加载,不过Webview不进行任何设置,这样跳转就需要系统进行解析,走deeplink这一套:
- 点击Scheme跳转,一般会唤起如下界面,让用户选择打开方式:
- 通过adb打印log,你会发现ActivityManagerService会打印这样一条Log:
- 其实看到的选择对话框就是ResolverActivity
- 不过我们先来看看到底是走到ResolverActivity的,也就是这个scheme怎么会唤起App选择界面,在短信中,或者Webview中遇到scheme,他们一般会发出相应的Intent(当然第三方APP可能会屏蔽掉,比如微信就换不起APP),其实上面的作用跟下面的代码结果一样:
- 那剩下的就是看startActivity,在源码中,startActivity最后会通过ActivityManagerService调用ActivityStatckSupervisor的startActivityMayWait
- startActivityMayWait会通过resolveActivity先找到目标Activity,这个过程中,可能找到多个匹配的Activity,这就是ResolverActivity的入口:
- 可以认为,所有的四大组件的信息都在PackageManagerService中有登记,想要找到这些类,就必须向PackagemanagerService查询
- PackageManagerService会通过queryIntentActivities找到所有适合的Activity,再通过chooseBestActivity提供选择的权利。这里分如下三种情况:
- 仅仅找到一个,直接启动
- 找到了多个,并且设置了其中一个为默认启动,则直接启动相应Acitivity
- 找到了多个,切没有设置默认启动,则启动ResolveActivity供用户选择
- 关于如何查询,匹配的这里不详述,仅仅简单看看如何唤起选择页面,或者默认打开,比较关键的就是chooseBestActivity
- 其实上述流程比较复杂,这里只是自己简单猜想下流程,找到目标Activity后,无论是真的目标Acitiviy,还是ResolveActivity,都会通过startActivityLocked继续走启动流程,这里就会看到之前打印的Log信息:
- 如果是ResolveActivity还会根据用户选择的信息将一些设置持久化到本地,这样下次就可以直接启动用户的偏好App。其实以上就是deeplink的原理,说白了一句话:scheme就是隐式启动Activity,如果能找到唯一或者设置的目标Acitivity则直接启动,如果找到多个,则提供APP选择界面。
10.AppLink原理分析
- 之前分析deeplink的时候提到了ResolveActivity这么一个选择过程,而AppLink就是自动帮用户完成这个选择过程,并且选择的scheme是最适合它的scheme(开发者的角度)。因此对于AppLink要分析的就是如何完成了这个默认选择的过程。
- 目前Android源码提供的是一个双向认证的方案:在APP安装的时候,客户端根据APP配置像服务端请求,如果满足条件,scheme跟服务端配置匹配的上,就为APP设置默认启动选项,所以这个方案很明显,在安装的时候需要联网才行,否则就是完全不会验证,那就是普通的deeplink,既然是在安装的时候去验证,那就看看PackageManagerService是如何处理这个流程的,具体找到installPackageLI方法:
- 可以看到发送了一个handler消息,那么消息里做了什么呢?看一下startIntentFilterVerifications发送一个消息开启验证,随后调用verifyIntentFiltersIfNeeded进行验证,代码如下所示:
- 以看出,验证就三步:检查、搜集、验证。在检查阶段,首先看看是否有设置http/https scheme的Activity,并且是否满足设置了Intent.ACTION_DEFAULT与Intent.ACTION_VIEW,如果没有,则压根不需要验证
- 具体看一下hasDomainURLs到底做了什么?
- 检查的第二步试看看是否设置了autoverify,当然中间还有些是否设置过,用户是否选择过的操作,比较复杂,不分析,不过不影响对流程的理解:
- 只要找到一个满足以上条件的Activity,就开始验证。如果想要开启applink,Manifest中配置必须像下面这样
- 搜集其实就是搜集intentfilter信息,下面直接看验证过程
- 目前Android的实现是通过发送一个广播来进行验证的,也就是说,这是个异步的过程,验证是需要耗时的(网络请求),所以安装后,一般要等个几秒Applink才能生效,广播的接受处理者是:IntentFilterVerificationReceiver
- IntentFilterVerificationReceiver收到验证消息后,通过start一个DirectStatementService进行验证,兜兜转转最终调用IsAssociatedCallable的verifyOneSource
- IsAssociatedCallable会逐一对需要验证的intentfilter进行验证,具体是通过DirectStatementRetriever的retrieveStatements来实现:
- AndroidAppAsset好像是Google的另一套assetlink类的东西,好像用在APP web登陆信息共享之类的地方 ,不看,直接看retrieveFromWeb:从名字就能看出,这是获取服务端Applink的配置,获取后跟本地校验,如果通过了,那就是applink启动成功:
- 其实就是通过UrlFetcher获取服务端配置,然后发给之前的receiver进行验证:
- 看到这里的HttpURLConnection就知道为什么Applink需在安装时联网才有效,到这里其实就可以理解的差不多,后面其实就是针对配置跟App自身的配置进行校验,如果通过就设置默认启动,并持久化,验证成功的话可以通过。
01.关于博客汇总链接
02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
开源推荐:https://github.com/yangchong211/YCPhotoCover
Deeplink实践原理分析的更多相关文章
- Guava Cache 原理分析与最佳实践
前言 目前大部分互联网架构 Cache 已经成为了必可不少的一环.常用的方案有大家熟知的 NoSQL 数据库(Redis.Memcached),也有大量的进程内缓存比如 EhCache .Guava ...
- 转载:solr MoreLikeThis的原理分析
转载地址:http://blog.sina.com.cn/s/blog_5ddc071f0101muos.html 在solr中有两种方式实现MoreLikeThis:MoreLikeThisHand ...
- Handler 原理分析和使用(一)
我为什么写Handler,原因主要还在于它在整个 Android 应用层面非常之关键,他是线程间相互通信的主要手段.最为常用的是其他线程通过Handler向主线程发送消息,更新主线程UI. 下面是一个 ...
- HashMap 与 ConcrrentHashMap 使用以及源码原理分析
前奏一:HashMap面试中常见问题汇总 HashMap的工作原理是近年来常见的Java面试题,几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和Has ...
- drizzleDumper的原理分析和使用说明
https://blog.csdn.net/qq1084283172/article/details/53561622 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...
- Holt-Winters模型原理分析
Holt-Winters模型原理分析及代码实现(python) from:https://blog.csdn.net/u010665216/article/details/78051192 引言 最近 ...
- PhpStorm Xdebug远程调试环境搭建原理分析及问题排查
2017年05月26日 经验心得 目录 一. 环境介绍 二. 远程环境配置 2.2 Xdebug安装 2.3 配置 三. 本地phpstorm配置 3.1 下载远程代码 3.2 添加php解释器 ...
- Tree-Shaking性能优化实践 - 原理篇
Tree-Shaking性能优化实践 - 原理篇 一. 什么是Tree-shaking 先来看一下Tree-shaking原始的本意 上图形象的解释了Tree-shaking 的本意,本文所说的前 ...
- 基于Lucene查询原理分析Elasticsearch的性能
前言 Elasticsearch是一个很火的分布式搜索系统,提供了非常强大而且易用的查询和分析能力,包括全文索引.模糊查询.多条件组合查询.地理位置查询等等,而且具有一定的分析聚合能力.因为其查询场景 ...
- AIDL原理分析
季春初始,天气返暖,新冠渐去,正值学习好时机.在Android系统中,AIDL一直在Framework和应用层上扮演着很重要的角色,今日且将其原理简单分析.(文2020.03.30) 一.开篇介绍 1 ...
随机推荐
- FireDac 连接 SQL SERVER 2014 - LocalDB
易博龙官方的文档没有更新,官方的文档只能连接local-db2012 微软官方关于local-db 2012的描述 如下: 但是现在我开始使用SQL SERVER LOCAL-DB 2014了,因为今 ...
- Oracle-ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
问题描述 ORA-12505, TNS:listener does not currently know of SID given in connect descriptorORA-12505: TN ...
- NC20684 wpy的请求
题目链接 题目 题目描述 "题目名称只是吸引你来做题的啦,其实和题目没什么卵关系:o(* ̄▽ ̄*)o" -- 历史--殿堂 wpy移情别恋啦,他不喜欢spfa了,现在他喜欢使用di ...
- Ubuntu下SSH管理及SFTP下载工具Muon(Snowflake)
简介 Muon其实更像是一个基于ssh的服务器管理工具, 界面中有PAC Manager的影子, 集成了文件管理, ssh命令行, 服务器性能监测和工具包等功能. 因为这个工具的编写语言是Java, ...
- Swoole从入门到入土(11)——HTTP服务器[Request]
http服务器的本质是应答式的服务器.我们只需关注onRequest事件中的request(请求)和response(响应)对象.让我们一起回顾一下onRequest事件: $http->on( ...
- 单例模式五种实现方式以及在JDK中的体现
单例模式五种实现方式以及在JDK中的体现 一.五种实现方式 1.饿汉式 构造私有 提供一个静态私有的成员常量,类型就是单例类型,值是用私有构造创造出来的唯一实例 提供公共的静态方法获取上述的静态成员常 ...
- Vue实现简单计算器功能
知识点: v-model双向绑定 v-on事件绑定 实现效果 源码 <!DOCTYPE html> <html lang="en"> <head> ...
- 双哈希_Birthday_Cake
Birthday Cake 思路:找到每个串的公共前后缀,统计公共前后缀之间的字符串的hash值,并判断所给n个串中是否存在符合条件的串 eg:abbddab 对于该串,我们不难发现,公共前后缀是ab ...
- 如何设置 vcpkg 依赖特定编译器
最近项目要部署到 gitlab-ci 上,所以远程机器上也要安装好编译环境 在相关的环境安装完后,发现编译项目时提示找不到三方库的符号文件 看到这个错误的第一反应就是依赖库的版本不对,因为远程机器上不 ...
- 细说Spring框架之核心01-概述
官网:https://spring.io/projects/spring-framework 文档:https://docs.spring.io/spring-framework/docs/curre ...