DeepLink的实现原理

Android 专栏收录该内容
123 篇文章 1 订阅

前言

之前我们又是看源码又是研究动画,今天分享一个比较简单的技术点:DeepLink。

DeepLink,深度链接技术,主要应用场景是通过Web页面直接调用Android原生app,并且把需要的参数通过Uri的形式,直接传递给app,节省用户的注册成本。简单的介绍DeepLink概念之后,我们看一个实际的例子:

朋友通过京东分享给我一个购物链接:

于是我通过微信打开了这条链接:

在微信中打开这个网址链接,提示我打开京东app,如果我点击了允许,就会打开我手机中的京东app,并且跳转到这个商品的详情页:

通过这种形式,我可以快速的找到需要查看的商品,并且完成购买相关的操作。是不是非常方便,这就是DeepLink。

正文

这么流弊的DeepLink是不是非常的难?其实DeepLink的基本实现是简单到不可思议,他的核心思想实际上是Android的隐式启动。我们平时的隐式启动主要是通过Action和Category配合启动指定类型的Activity:

<activity
      android:name=".SecondActivity"
      android:exported="true">
      <intent-filter>
           <action android:name="com.lzp.deeplinkdemo.SECOND" />
           <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
</activity>
val intent = Intent("com.lzp.deeplinkdemo.SECOND")
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)

除了action和category,还有一种隐式启动的用法是配置data:

<data
     android:scheme="xxxx"
     android:host="xxxx"
     android:port="xxxx"
     android:path="xxxx"
     android:pathPattern="xxxx"
     android:pathPrefix="xxxx"
     android:mimeType="xxxx"/>

scheme:协议类型,我们可以自定义,一般是项目或公司缩写,String

host:域名地址,String

port:端口,int。

path:访问的路径,String

pathPrefix:访问的路径的前缀,String

pathPattern:访问路径的匹配格式,相对于path和pathPrefix更为灵活,String

mimeType:资源类型,例如常见的:video/*, image/png, text/plain。

通过这几个配置项,我们发现data实际上为当前的页面绑定了一个Uri地址,这样就可以通过Uri直接打开这个Activity。

复习一下Uri的结构:

<scheme> :// <host> : <port> / [ <path> | <pathPrefix> | <pathPattern> ]

示例:https://zhidao.baidu.com/question/2012197558423339788.html

scheme和host不可缺省,否则配置无效;path,pathPrefix,pathPattern一般指定一个就可以了,pathPattern与host不可同时使用;mimeType可以不设置,如果设置了,跳转的时候必须加上mimeType,否则不能匹配到Activity。

现在我们修改SecondActivity的intent-filer:

<activity
    android:name=".SecondActivity"
    android:exported="true">

        <intent-filter>
            <action android:name="com.lzp.deeplinkdemo.SECOND" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

        <intent-filter>              

            <data
                android:scheme="lzp"
                android:host="demo"
                android:port="8888"
                android:path="/second"
                android:pathPattern="/second"
                android:pathPrefix="/second"
                android:mimeType="text/plain"/>

        </intent-filter>
</activity>

打开SecondActivity:

val intent = Intent()
intent.setDataAndType(Uri.parse("lzp://demo:8888/second"), "text/plain")
startActivity(intent)

现在在App中已经可以打开页面了,那么用web能不能正常打开呢?首先配置MainActivity的intent-filter:

<activity
    android:name=".MainActivity"
    android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <intent-filter>
            <data
                android:scheme="lzp"
                android:host="demo"
                android:path="/main"/>
        </intent-filter>

</activity>

Web需要打开url链接,所以我们不需要配置mimeType,

手写一个简单的Html页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <title></title>
  <meta name="Generator" content="Cocoa HTML Writer">
  <meta name="CocoaVersion" content="1561.4">
  <style type="text/css">
    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 17.0px; font: 12.0px 'Songti SC'; color: #000000; -webkit-text-stroke: #000000; min-height: 17.0px}
    span.s1 {font-kerning: none}
  </style>
</head>
<body>
<a href="lzp://demo/main">打开main</a>
</html>

Html页面添加了一个链接,点击打开lzp://demo/main这个地址。把html导入到手机中,用浏览器打开,点击“打开app”,毫无反应!!!

没错,如果只是配置了data,Web还是没办法通过url地址打开我们的Activity,那怎么解决这个问题呢?

/**
     * Activities that can be safely invoked from a browser must support this
     * category.  For example, if the user is viewing a web page or an e-mail
     * and clicks on a link in the text, the Intent generated execute that
     * link will require the BROWSABLE category, so that only activities
     * supporting this category will be considered as possible actions.  By
     * supporting this category, you are promising that there is nothing
     * damaging (without user intervention) that can happen by invoking any
     * matching Intent.
     */
    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";

我们还需要配置

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

从官方的注释上写明:需要浏览器打开Activity,需要设置这个分类。例如邮件,只有设置了这个分类的Activity才会考虑被打开。加上这个配置后,再次点击看看有没有效果。

如果你真的亲自尝试了,你会发现还是没有效果。这个时候我们需要回顾一下action和category的用法:

首先需要尝试匹配action,action匹配成功了之后,才会继续匹配设置的category,所以单独匹配category是没有任何效果的。

因为我们要打开的仅仅是一个页面,所以我们设置

/**
     * Activity Action: Display the data to the user.  This is the most common
     * action performed on data -- it is the generic action you can use on
     * a piece of data to get the most reasonable thing to occur.  For example,
     * when used on a contacts entry it will view the entry; when used on a
     * mailto: URI it will bring up a compose window filled with the information
     * supplied by the URI; when used with a tel: URI it will invoke the
     * dialer.
     * <p>Input: {@link #getData} is URI from which to retrieve data.
     * <p>Output: nothing.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_VIEW = "android.intent.action.VIEW";

官方的注释说明ACTION_VIEW表示展示数据的页面,系统默认的Action就是ACTION_VIEW。添加上ACTION_VIEW,再次点击打开app。

还是不行,但是跟之前不同的是,这次出现了启动app的提示窗口,但是app却闪退了,看一下崩溃日志:

09-06 14:35:15.459 1216-3270/? W/IntentResolver: resolveIntent failed: found match, but none with CATEGORY_DEFAULT
09-06 14:35:15.473 26708-26708/? E/AKAD: thread:Thread[main,5,main]
    android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=lzp://demo/main?id=111 flg=0x10000000 (has extras) }
        at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
        at android.app.Activity.startActivityIfNeeded(Activity.java:4420)
        at android.app.Activity.startActivityIfNeeded(Activity.java:4367)
        at org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl$3.onClick(ExternalNavigationDelegateImpl.java:239)
        at com.qihoo.browser.dialog.CustomDialog$3.onClick(CustomDialog.java:274)
        at android.view.View.performClick(View.java:5267)
        at android.view.View$PerformClick.run(View.java:21249)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)

日志上写的很明确,虽然找到了匹配的页面,但是没有设置CATEGORY_DEFAULT。看来Web通过url来打开链接,必须要求设置CATEGORY_DEFAULT,添加上后,看一下我们完整的xml配置:

<activity
    android:name=".MainActivity"
            android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <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="lzp"
                android:host="demo"
                android:path="/main"/>
        </intent-filter>
</activity>

最后看一下效果:

那么如何在通过url给app传递参数呢?要实现这个也很简单,首先我们知道要想给url添加参数,直接在url后拼接key=value就可以了,例如:

http://www.baidu.com/s?wd=android

其中wd=android就是我们要添加的参数,现在假设我们需要为Activity传递一个参数id,我们就可以修改uri为:

lzp://demo/main?id=111

客户端接收key为id的参数的方法:

if (intent != null && intent.data != null) {
       Log.e("lzp", intent.data.getQueryParameter("id"))
}

如果只是接收参数的话,客户端不需要进行任何修改,但是这里有一种情况,如果我们Activity必须传递id,如果不传递id不允许跳转怎么办呢?我们有两种办法解决这个问题:

1、在刚才的if语句增加else判断,当参数为空的时候,进行finish操作。

2、通过pathPattern,通过通配符设置必须有参数。

我们看一下第二种的实现方式:

<data
    android:pathPattern="lzp://demo/main?id=*"
    android:scheme="lzp" />

之前已经说过,pathPattern不能和host同时使用,所以我们只能删除host,pathPattern匹配的是整个Uri,这样我们还可以指定多个参数。但是AndroidManifest.xml会报错,我们忽略就可以了

总结

其实DeepLink的实现原理就是这么简单,只是我们对于隐式启动理解的不够。是不是也想给自己的App加上DeepLink呢?赶快尝试一下吧~

 

  • 4
    点赞
  • 1
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

详解MATLAB图形绘制技术》首先介绍MATLAB的基本知识及基本运算,使读者对MATLAB有一个概略的了解,然后系统论述图形绘制技术的基本概念、工作原理及在工程中的应用。书中精选科学和工程中常用的多个算法,全部采用MATLAB语言编程实现,并结合实例对算法程序进行验证和分析。其中详细讲解了MATLAB的基本知识、二维图形的绘制、三维图形的绘制、高级图形绘制技术、动画与视频、几何造型及GUI的程序设计等内容。   《详解MATLAB图形绘制技术》以精缩的理论知识、实践教学和工程训练相结合,可以作为相关专业学生及工程技术人员学习MATLAB图形绘制或图形可视化技术的指导书,也可作为高年级本科生和研究生的教材或教参。 第1章 MATLAB的基本知识 1.1 MATLAB的认识 1.2 MATLAB的特点 1.2.1 MATLAB的普遍特点 1.2.2 MATLAB R2009a的新特点 1.3 MATLAB的工作环境 1.3.1 MATLAB R2009a的安装 1.3.2 MATLAB的命令窗口 1.3.3 MATLAB的工作空间 1.3.4 MATLAB的浏览窗口 1.3.5 MATLAB的“命令历史”窗口 1.3.6 MATLAB的“当前路径”窗口 1.4 MATLAB的数据类型 1.4.1 变量与常量 1.4.2 双精度型 1.4.3 字符串 1.4.4 cell结构 1.4.5 标点符号 1.4.6 结构型 1.5 M文件的编译调试环境 1.5.1 编译器的安装和配置 1.5.2 编译器的使用 1.6 矩阵 1.6.1 矩阵的产生 1.6.2 矩阵的运算 1.6.3 矩阵的查询和赋值 1.6.4 矩阵计算的基本函数 1.7 MATLAB的控制语句 1.7.1 循环结构 1.7.2 选择结构 1.7.3 递归结构 1.7.4 程序流控制 1.8 文件的相关操作 1.8.1 文件的调用与保存 1.8.2 文件的打开与关闭 1.8.3 文件的输入与输出 1.9 联机帮助 1.9.1 联机帮助系统 1.9.2 联机演示系统 1.9.3 命令查询系统 1.10 GUI界面基础 1.10.1 GUI基本概念 1.10.2 图形用户接口 第2章 二维图形的绘制 2.1 二维图形的基本绘图 2.1.1 高级绘图 2.1.2 低级绘图 2.1.3 多轴曲线图 2.2 二维图形的修饰 2.2.1 legend函数 2.2.2 title函数 2.2.3 gtext函数 2.2.4 text函数 2.2.5 坐标轴标题 2.2.6 控制图轴大小 2.3 填充图形的绘制 2.4 精确绘图 2.5 图形的分割窗口 2.6 特殊二维图形 2.6.1 极坐标图 2.6.2 玫瑰图 2.6.3 概述分布图 2.6.4 饼图 2.6.5 条形图 2.6.6 误差条图 2.6.7 面积图 2.6.8 阶梯图 2.6.9 等高线图 2.6.10 散点图 2.6.11 柄图 2.6.12 罗盘图 2.6.13 羽毛图 2.6.14 彗星图 2.6.15 向量场图 2.7 符号绘图 2.7.1 ezplot函数 2.7.2 ezpolar函数 2.7.3 ezcontour函数 2.8 手工绘图 第3章 三维图形的绘制 3.1 基本的三维绘图 3.1.1 栅格数据点的产生 3.1.2 三维曲线 3.1.3 三维网格图 3.1.4 三维曲面图 3.2 三维的透明作图 3.3 三维图形的调控 3.3.1 设置视角位置 3.3.2 设置坐标轴 3.3.3 灯光效果设置 3.3.4 颜色的渲染 3.4 特殊的三维图形 3.4.1 三维离散序列图 3.4.2 三维填充多边形图 3.4.3 三维等高线 3.4.4 流水效果曲面图 3.4.5 圆柱体 3.4.6 球面图 3.4.7 立体切片图 3.4.8 三维饼图 3.4.9 柱状图 3.4.10 三角网目图 3.5 简易函数绘图 3.6 三维图形的修饰 3.6.1 三维图形函数组合 3.6.2 图形的剪切 3.6.3 图形的镂空 3.6.4 图形的裁切 3.6.5 图形的平滑处理 3.7 三维流场绘图 3.7.1 流线图 3.7.2 流锥图 3.7.3 流带图 3.7.4 流管图 第4章 MATLAB图形技术 4.1 图形可视化技术 4.1.1 基本概念 4.1.2 三维图形可视化基本流程 4.2 颜色图及颜色条 4.2.1 控制着色的方法 4.2.2 控制图形亮度 4.2.3 图形的映像数据表 4.2.4 绘制色轴 4.2.5 色轴刻度 4.2.6 RGB真彩着色 4.3 MATLAB颜色空间转换 4.3.1 HSV空间与RGB空间转换 4.3.2 YIQ空间与RGB空间转换 4.3.3 YcbCr空间与RGB空间
©️2021 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值