Android 通过短信跳转到特定 App -- Android App Links

为什么会有这篇文章:

在Android 6.0 之前,用户如果在短信中,点击一个链接「https://zd.badmask.com」,想要跳转到某 App 中,之前都是弹出符合这个意图过滤器的应用,大概会有浏览器、某App等,进而由用户选择,第一种是直接进入app,行为符合预期;第二种会选择打开浏览器「这也是大部分用户的行为」,呈现H5页面,通过H5页面,再进入App。
这个交互对于产品和用户来讲太复杂了,最期待的行为,点击之后,用户没有其他的选择权,直接定位到App。

先看效果:

不使用 Android App Links,会出现这样的行为:

不使用 Android App Links

使用 Android App Links,能直接跳转到对应的APP:
点击观看视频

首先需要了解的概念:Deep linking 与 Android App Links
Deep linking:

深度链接,指将用户直接带到应用中特定内容的网址,Android中可以直接通过添加意图过滤器,将用户吸引到正确的活动。
缺点:如果用户安装了其他应用程序可以处理此意图,例如上图中的短信,并且手机安装的app中有如下代码,则单击后出现选择app的对话框,询问用户使用哪个应用程序。

<activity
            android:name=".module.personal.ui.SplashActivity"
            android:configChanges="orientation|keyboardHidden"
            android:screenOrientation="portrait">
            <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:host="zd.badmask.com"  android:scheme="https" />
            </intent-filter>
</activity>
Android App Links:

Android 6.0 及更高版本上的 Android App Links允许应用程序将自己指定为给定链接类型的默认处理程序。
优势:
安全且具体,链接必须经过google网站的关联方法检测,没有其他应用可以使用您的链接;
无缝的用户体验,如果未安装对应的App,则会跳转到浏览器,并显示该网址的内容,没有404,没有错误;「重要」
Android Instant Apps 支持;
通过Google搜索吸引用户;

Android 官方截图:
developer.android.com截图
如何实现Android App Links

第一步:在 AndroidManifest.xml 文件中,加入 Intent Filter,

一个intent-filter标签中,暂时不要加入其他data标签,其中 scheme 必须为 https,但是 data 标签的 host 内容随意,稍后解释
<activity
            android:name=".module.personal.ui.SplashActivity"
            android:configChanges="orientation|keyboardHidden"
            android:screenOrientation="portrait">
            <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" />
                <data android:host="zd.badmask.com"  android:scheme="https" />
            </intent-filter>
</activity>

第二步:创建json文件

title require
sha256_cert_fingerprints 你app的所用的签名文件的 SHA256 值,可以自己生成app的签名文件,即 keystore,推荐命令行方式,这样显得比较帅,哈哈
package_name App 的 applicationId
文件命名 命名为 assetlinks.json ,不可更改!
其他的内容不要改动!!!
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "替换为 App 的 applicationId",
    "sha256_cert_fingerprints": ["ED:41:94:D6---:8A:1B:F4"]
  }
}]

第三步:将这个json文件,放到指定路径下

https://data标签中 host 的值/.well-known/assetlinks.json
很多博客把 assetlinks.json 文件的内容和名字搞错了,我也是很无语了,浪费了我很多时间啊~
关于https,需要注意SSL证书的问题,必须是可信任的证书

第四步:检验放到指定路径下的文件是否已生效

可通过这个链接检验:https://developers.google.com/digital-asset-links/tools/generator

检验链接是否可用.png

第五步:给你的App打包,用第二步的keystore文件,生成Apk文件「就是可以发布到应用市场的 apk 文件」,安装到手机上,发送短信至手机,内容大概是「hello,test Android App Links,https://zd.badmask.com
注:链接的内容是上文中 data 标签的 scheme 和 host 的值
这个时候就初步成功了,即使我上面还留有几个疑问。

FAQ
为什么intent-filter中,scheme一定要用https?

1.若想在短信等文本中,可以点击此链接,首先就要被识别为链接的形式,比如「https://zd.badmask.com/diary_book/13056043/」;用其他的 scheme 和 host 比如 badmask://zly 是不会被识别为链接的,自然就不可点击;

  1. Android App Links 对于链接的校验很严格,必须支持https才可以;
一个intent-filter标签中,如何加入其他data标签?

啥都不说,先上代码

      <activity
            android:name=".module.personal.ui.SplashActivity"
            android:configChanges="orientation|keyboardHidden"
            android:screenOrientation="portrait">
            <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:host="launch"
                    android:scheme="https" />
                <data
                    android:host="zd.badmask.com"
                    android:scheme="https" />
            </intent-filter>
        </activity>

官方解释如下


官方解释.png

数字资产链接把你在 intent-filter 中列出的子域名堪称唯一、独立的域名,所以如果列出多个子域名,那必须在每个子域名中发布一个有效的 assetlinks.json 文件,增加了无故的工作量.
如果一个 Activity 想被多个 intent-filter 识别,而且不更改之前的 assetlinks.json 文件,可以看下面的代码:

        <activity
            android:name=".module.personal.ui.SplashActivity"
            android:configChanges="orientation|keyboardHidden"
            android:screenOrientation="portrait"
            android:theme="@style/GMThemeWithBackground">
            <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:host="launch"
                    android:scheme="badmask" />
            </intent-filter>
            <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" />

                <data
                    android:host="zd.badmask.com"
                    android:scheme="https" />
            </intent-filter>
        </activity>
        //写两个 intent-filter 标签,之前定义的协议「badamsk://launch」依然可用.
        //不至于因为增加一个 App Links 的功能而影响整体~
目前只支持跳转到指定的app,那么如果跳转到指定app的指定页面?

对应我例子中这个 https://zd.badmask.com 域名的,一定是App的启动页:
1.从产品角度讲,在 App 未启动的情况下,这可能会关联一系列与业务相关的初始化操作,初始化操作没有完成,可能会导致一些列问题,所以只能先打开这个页面,然后再跳转到指定的其他页面;
2.从技术角度讲,如果直接用 https://zd.badmask.com 对应一个页面,那么每个页面都需要对应的一个域名,不合理

好,那么只能把 https://zd.badmask.com 域名定位到启动页,但是我怎样跳转到App 的指定页面呢?

理想情况下,想写成下面这个样子,跳转到A页面之后,再跳转到url对应的另一个页面,解析参数就可以了,好,这只是想象...

https://zd.example.com?url=badmask://example

在短信中,url=badmask://example 这部分并不能被识别为链接,只有被识别为链接才能被跳转,所以放弃吧,用这种 https://zd.example.com/detail/1212/
在「https://zd.example.com」这个协议对应的页面中去解析「detail/1212/」;
不过有一个问题需要注意,如果是 Android 6.0 以下的手机,或者手机上没有安装 app,那么会跳转到浏览器中,并且加载此网址对应的页面,所以为了避免用户访问404,在相应的路径下需要部署H5的代码。

       Intent intent = getIntent();
       if (Intent.ACTION_VIEW.equals(intent.getAction())) {
            Uri uri = intent.getData();
            if (uri != null) {
               uri.getPath();//调用这个方法,拿到「detail/1212」,然后去解析具体的业务
               //当然可以查看API调用其他方法
            } 
        } 
Android App Links的链接如果用短链接的形式,能不能跳转成功?

不能,短链接的原理都是重定向,而「https://data标签的内容/.well-known/assetlinks.json 」这个网址的要求不能被重定向.

Android App Links的链接如果出现在 Android 6.0以下的手机中 or 未提前安装 App,会有什么表现?

与 Deep linking 的表现类似,不过是直接跳转到浏览器,呈现此网页,所以此功能在 Android 6.0 以下 or 未安装 App 的手机上通用.

如果你只看到这里,就小看了Android App Links,还可以从 A app 跳转到 B app!!!

直接上代码,在另一个App中,写入如下代码:

textView.setMovementMethod(LinkMovementMethod.getInstance());
String a2 = "<a href='https://zd.badmask.com/diary_book/13056043/'>https://zd.badmask.com/diary_book/13056043/</a>";
CharSequence cs = Html.fromHtml(a2);
textView.setText(cs);

此时会显示为高亮显示的TextView,点击可直接跳转到https://zd.badmask.com/diary_book/13056043/ 该网址对应的页面。
不过这部分是我自己写在另一个 app 的代码,如果想直接应用在比如 微博/微信/QQ/简书 等平台,我测试了一下不可行,原因如下:

  1. 微博在我发送的内容里,发布成功后,内容更改为短链接的形式;
  2. 简书平台中输入的链接的内容,直接不可点击;
  3. 在 QQ/微博/更美 等 App中,即使发送的内容可以跳转,但基本都是跳转到App 中的某个固定页面 ,来呈现此 H5链接的内容...
    不过 这个功能在做商务合作的时候,让合作方在其 App 中加入相应代码,跳转到我们的 App 里是完全 ok 的,所以还是具体产品层面的意义.

参考链接:
Android 官方
Android M的App Links实现详解
Android AppLinks 接入

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容