zoukankan      html  css  js  c++  java
  • 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,如果安装了就唤起,否则引导下载。对于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.跳转指定页面,有的页面需要登录才能进入,没有登录则先跳转登录页面,登录了才跳转指定页面,这种如何操作?
    • 什么是DeepLink
      • 移动端深度链接,简称deeplink。这是一种通过uri链接到app特定位置的一种跳转技术,不单是简单地通过网页、app等打开目标app,还能达到利用传递标识跳转至不同页面的效果。
    • 什么是Deferred DeepLink
      • 相比DeepLink,它增加了判断APP是否被安装,用户匹配的2个功能;
        • 1.当用户点击链接的时候判断APP是否安装,如果用户没有安装时,引导用户跳转到应用商店下载应用。
        • 2.用户匹配功能,当用户点击链接时和用户启动APP时,分别将这两次用户Device Fingerprint(设备指纹信息)传到服务器进行模糊匹配,使用户下载且启动APP时,直接打开相应的指定页面。
    • 什么是AppLink
      • AppLink相对复杂,需要App与Web协作完成系统验证,但可以保证直接唤起目标App,无需用户二次选择或确认。

    05.DeepLink和AppLink核心技术

    • DeepLink和AppLink不同点。下面这个总结很重要!
      不同点DeepLinkAppLink
      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.关于我的博客

    开源推荐:https://github.com/yangchong211/YCPhotoCover

  • 相关阅读:
    一件重要的事想要告诉大家 AlexCool
    经典永不过时!重温设计模式 AlexCool
    腾讯云网络核心技术演进实践|好文推荐 AlexCool
    经典永驻,重温设计模式 |硬核! AlexCool
    linux网络全景指南 AlexCool
    Linux调度系统全景指南(终结篇) AlexCool
    大厂的面试官是如何挑人的? AlexCool
    中国大学MOOC数据结构基础习题集、023、求前缀表达式的值
    中国大学MOOC数据结构基础习题集、041、Root of AVL Tree
    中国大学MOOC数据结构基础习题集、052、Saving James Bond Easy Version
  • 原文地址:https://www.cnblogs.com/yc211/p/12012859.html
Copyright © 2011-2022 走看看