文章

DeepLink

DeepLink

唤端技术背景

在日常开发中,往往需要通过唤端改善用户体验。比如一个常见的场景:用户通过链接分享或其他途径,在端外访问 H5 活动页面,与页面发生交互后,需要实现以下功能:

  • 功能 A:对于已安装 APP,唤起 APP,并跳转到对应的活动页
  • 功能 B:对于未安装 APP,唤起的应用商店(APP 主页)
  • 功能 C:基于功能 B,在下载安装完成,打开 APP 后,跳转到对应的活动页

功能 A 和 B 可通过 DeepLink 或 AppLink 实现;功能 C 可通过 Deferred DeepLink 实现。
有了这项技术我们就可以实现 H5 唤起 APP 应用、Facebook App 的广告到自己的 App 了,现阶段的引流方式大都得益于这种技术,比如广告投放、用户拉新等
目前主要有这几种技术:

  1. Deeplink 用于 APP 间的跳转,如果是浏览器,可能会有二次弹窗确认;如果有多个组件能处理该 deeplink,都会弹窗列举出来供你选择
  2. Applinks(Universal Link) 用于消除 Deeplink 的二次弹窗选择,直接到达你的 APP
  3. Defered DeepLink 延迟的 deeplink,首次安装会去拉一个接口返回一些安装来源信息或 deeplink;一般用于首次安装确认来源的,如Google install referer,Facebook ad defered deeplinkgoogle ad deferer deeplink, appsflyer deferer deeplink

Deeplink

URL Scheme,多一次二次弹窗选择

平时说的 Deeplink,在 Android 上就是 URL Scheme。

添加 Intent-Filter

  1. 定义 URI Scheme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<activity
  android:name=".ui.activity.SplashActivity"
  android:exported="true"
  android:screenOrientation="portrait"
  android:theme="@style/NormalSplash">

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

  <!--DeepLink h5唤醒app配置-->
  <intent-filter>
    <!--ACTION_VIEW:支持被检索-->
    <action android:name="android.intent.action.VIEW" />
    <!--CATEGORY_DEFAULT:响应隐式Intent-->
    <category android:name="android.intent.category.DEFAULT" />
    <!--CATEGORY_BROWSABLE:可被Web浏览器唤起-->
    <category android:name="android.intent.category.BROWSABLE" />
    <!--data:一个或多个,必须含有scheme标签,决定被唤起的URL格式-->
    <data
      android:host="me.hacket"
      android:scheme="hacket" />
    <!--    
    <data
    android:host="me.hacket"
    android:scheme="hacket" 
    android:pathPrefix="/pxwx"/>
    <data
    android:host="me.hacket"
    android:scheme="hacket" 
    android:path="/pxwx/user"/>
    -->
  </intent-filter>
</activity>
  • App 可以配置多个支持唤起的 Activity
  • Activity 可以支持被多个 URL 唤起
  • 若一个 App 配置了多个支持唤起的 Activity,它们的 scheme 和 host 一般一致,然后通过 path、pathPrefix 等进行定向区分
  1. Uri 数据的解析可以在你的 SlashActivity 中通过 getIntent().getData() 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override 
public void onCreate(Bundle savesInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
    
    // 尝试获取WebApp页面上过来的URL
    Uri uri = getIntent().getData();
    if (uri != null) {
        // scheme部分
        String scheme=data.getScheme();
        // host部分
        String host=data.getHost();
        // 访问路径
        String path=data.getPath();
        //参数
        Set<String> paramKeySet=data.getQueryParameterNames();
    }
}
  1. 在 h5 页面上,通过如下方式使用:
1
2
3
4
5
6
7
8
9
<!--1.通过a标签打开,点击标签是启动-->
<!-- 注意这里的href格式 -- >
<a href="hacket://app.me.hacket">open android app</a>

<!--2.通过iframe打开,设置iframe.src即会启动-->
<iframe src="hacket://me.hacket"></iframe>

<!--3.直接通过window.location 进行跳转-->
window.location.href= "hacket://me.hacket";
  1. 在原生 App 中唤起通过 Intent 方式
1
2
3
4
Intent intent = new Intent();
intent.setData(Uri.parse("hacket://me.hacket/"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
  1. 用户点击了链接后,会弹出一个列举了能处理该链接的 Dialog 供用户选择(所有能处理该链接的 APP)

833bn

测试 URL Scheme

adb 命令

adb shell am start -W -a android.intent.action.VIEW -d “yourdeeplink://example.com/path?id=123”

如:adb shell am start -W -a android.intent.action.VIEW -d “<hacket://hacket.me?name>=大圣 “

代码验证

data 为你的测试链接

1
2
3
4
Intent intent = new Intent();
intent.setData(Uri.parse("hacket://me.hacket/"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

html

放 APP 本地或放到 web 容器 (如 tomcat) 去

1
<a href='xxxlink://applink/ad_landing_recommend?data={"tsp_id":"60007289","goods_id":"2329783","page_type":"B","mall_code":1}'>B类型:xxxlink://applink/ad_landing_recommend?data={"tsp_id":"60007289","goods_id":"2329783","page_type":"B","mall_code":1}</a>

三方 APP

Via 浏览器,或者添加一个 function,添加 .zshrc/.bach_profile 文件中,模拟操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#### 启动via app mark.via.gp/mark.via.Shell,然后输入文本,最后按回车键
#### 可用来测试deeplink跳转
function adb:via() {
  echo "stop Via app."
  adb shell am force-stop mark.via.gp
  
  echo "start Via app."
  adb shell am start -n mark.via.gp/mark.via.Shell
  
  sleep 2
  echo "input tap 500 1033"
  # 模拟按2次tab键盘到tab,才能定位到EditText,好像经常找不到焦点
  # adb shell input keyevent KEYCODE_TAB
  # adb shell input keyevent KEYCODE_TAB
  adb shell input tap 500 1033 

  echo "input text $1"
  adb shell input text "$1"

  echo "send keyevent KEYCODE_ENTER"
  adb shell input keyevent KEYCODE_ENTER
}

可以根据不同的手机将坐标替换下

URL Scheme 兼容性

URL Scheme 兼容性高,但却存在许多限制:

  • 国内各个厂商浏览器差异很大,当要被唤醒的目标 App 未安装时,这个链接很容易出错。
  • 当注册有多个 Scheme 相同的时候,目前是没有办法区分的。
  • 不支持从其他 App 中的 WebView 中跳转到目标 App。
  • 被部分主流平台禁止,微信、微博、QQ 浏览器、手机百度中都已经被禁止使用。

三方 APP 唤端的限制

在部分 APP 内部去唤起第三方 APP,第一方 APP 出于防止流量流失、安全性等考虑,对上述 Deeplink 进行了限制,无法直接使用。因此往往是通过第一方 APP 提供的 API 进行唤端,比如微信的 launchApplication、wx-open-launch-app 等。其它 APP 的 API 形式唤端亦是如此

Web links are deep links that use the HTTP and HTTPS schemes.

1
2
3
4
5
6
7
8
<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" />
  <data android:host="myownpersonaldomain.com" />
</intent-filter>
  1. Android12 或以上,点击 web links 会跳转到浏览器
  2. Android12 之前,如果手机上的 APP 能处理该 web links,就会像 deep links 一样弹窗来让用户选择

Chrome Intent

URL Scheme 存在一个问题就是如果没有 APP 能处理该链接,点击无响应或跳转到一个错误界面;Chrome Intent 就可以在链接无法处理时跳转到一个指定的链接

Chrome Intent 介绍

  • Chrome Intent 是 Android 设备上 Chrome 浏览器中 URI 方案的深层链接替代品。
  • 如果 APP 已安装,则通过配置的 URI SCHEME 打开 APP。
  • 如果 APP 未安装,配置了 fallback url 的跳转 fallback url,没有配置的则跳转应用市场。

Chrome Intent语法

1
2
3
4
5
6
7
8
9
intent:  
   HOST/URI-path // Optional host  
   #Intent;  
      package=\[string\];  
      action=\[string\];  
      category=\[string\];  
      component=\[string\];  
      scheme=\[string\];  
   end;

示例:xxxlink://applink/xxxGals
不带 browser_fallback_url:

1
<a href="intent://applink/xxxGals/#Intent;scheme=xxxlink;package=com.zzz;end">open xxx App xxxGals</a>

在 Android Chrome 115 版本,不带 browser_fallback_url,会跳转到 Google Play

带 browser_fallback_url:

1
<a href="intent://applink/xxxGals/#Intent;scheme=xxxlink;package=com.zzz;S.browser_fallback_url=https://www.xxx.com;end">open xxx App xxxGals page fallback</a>

这样如果没有对应应用,该链接就会跳转到 S.browser_fallback_url 指定的 url 上。

Chrome Intent 兼容性

  • Google 通过 chrome 浏览器启动的优化方案
  • 很多第三方浏览器会拦截掉 Chrome Intent 启动应用的请求

deeplink: xxxlink://applink/{跳转类型}?data={参数字典的字符串并进行urlencode}

example: xxxlink://applink/selectcategory?data=%7b%27category_id%27%3a%27123%27%2c%27attr_ids%27%3a%27101_725-238_102%27%7d

slink: [<schema>://<host>]/<group>/<name>[?need_login=true&data=url_encode({json})]

example: <xxxlink://xxx.com/goods/flash_sale_list?data>={“id”:123, “key”:456} <yyylink://yyy.com/goods/flash_sale_list?data>={“id”:123, “key”:456}

简单一句话就是从一条短链通过接口转换成 deeplink

注意

slink 需要加白名单,否则只能跳转到首页

  • app 内置在: basic 库 assets/route_rule.json 中
  • 接口 setting/system,接口的会覆盖 app 内置的白名单
  1. onelink(会通过接口返回 deeplink)/deeplink 跳转的: 只支持 1 次 url encode 的,不支持 2 次 url encode 的
  2. Google play install referer/facebook google ddl 带 utm_xxx_onelink 的这种:Android 端会在调用 link/onelink/uniParser 接口后做 1 次 url decode
    a. 如果返回的 deeplink 没有&字符,支持后端 1 次或 2 次 encode 的,因为多次 url decode 也可以
    b. 如果返回的 deeplink 有&字符,后端只能 2 次 url encode,如果只进行 1 次 url encode,APP url decode 1 次后,再进去获取 data 后的参数获取不到

onelink 的域名是 applink

方案对比

 URL SchemeUniversal LinkApp Link
<ios9支持不支持不支持
>=ios9支持支持不支持
<android6支持不支持不支持
>=android6支持不支持支持
是否需要 HTTPS不需要需要需要
是否需要客户端需要需要需要
无对应 APP 时的现象报错/无反应跳到对应的页面跳到对应的页面

URI Scheme

  • URI Scheme 的兼容性是最高,但使用体验相对较差(需要二次弹窗确认,多个需要选择)
  • 当要被唤起的 APP 没有安装时,这个链接就会出错,页面无反应。
  • 当注册有多个 scheme 相同的时候,没有办法区分。
  • 国内三方 APP 会限制跳转
  • 已经安装 APP,直接唤起 APP;APP 没有安装,就会跳去对应的 web link。
  • universal Link 是从服务器上查询是哪个 APP 需要被打开,所以不会存在冲突问题
  • universal Link 支持从其他 app 中的 UIWebView 中跳转到目标 app
  • 缺点在于会记住用户的选择:在用户点击了 Universal link 之后,iOS 会去检测用户最近一次是选择了直接打开 app 还是打开网站。一旦用户点击了这个选项,他就会通过 Safiri 打开你的网站。并且在之后的操作中,默认一直延续这个选择,除非用户从你的 webpage 上通过点击 Smart App Banner 上的 OPEN 按钮来打开。
  • 优点与 Universal Link 类似
  • 缺点在于国内的支持相对较差,在有的浏览器或者手机 ROM 中并不能链接至 APP,而是在浏览器中打开了对应的链接。
  • 在询问是否用 APP 打开对应的链接时,如果选择了 “ 取消 “ 并且 “ 记住选择 “ 被勾上,那么下次你再次想链接至 APP 时就不会有任何反应

Ref

对 deeplink/Applink 的发展讲的很清晰

本文由作者按照 CC BY 4.0 进行授权