Android APP Links 小结

893 阅读6分钟

Android APP Links 小结

Untitled design(2).png

介绍

最近接入Passkey和Fido2时使用了Digital Asset Links来实现网页和Android APP共享凭据,

Digital Asset Links还有个更通用的场景是在APP Links中用于网页和Android APP的关联凭证,本着来都来了,不能不到此一游的精神,写一篇关于APP Links总结。

我们经常有一种需求是从Web 页面中直接跳转到客户端应用内,在 Web 页面中唤起移动应用程序来增强功能和交互性,无论是在用户点击特定链接时打开应用程序,还是在特定条件下自动跳转到应用程序,这种无缝的切换可以帮助用户更流畅地进行操作和获取所需的信息。

Deep Links (自定义 URL Scheme)和App Links(应用链接)是实现在 Web 中唤起移动应用程序的常见技术。通过自定义 URL Scheme,开发人员可以为应用程序定义特定的 URL 格式,当用户点击相应的链接时,操作系统会尝试打开对应的应用程序。这种方法在跨平台开发中被广泛使用,可以方便地在不同移动平台上实现。这个方案在Android和iOS平台都支持。

应用链接则提供了更灵活和标准化的方式来实现在 Web 页面中唤起移动应用程序。通过在应用程序和网站之间建立关联,应用链接允许使用普通的 HTTP/HTTPS 链接来唤起应用程序,而不再需要特定的 URL Scheme。这种方法在 Android 得到了官方支持,并提供了更高的兼容性和更好的用户体验。在iOS平台相对应的方案叫做Universal Link,这部分的详情可以参考官方文档

文章后面还补充了一种更为小众的方案:Intents with Chrome,大家也可以简单了解下。

Deep Links

URL组成:[scheme:][//authority][path][?query][#fragment]

清单文件配置

AndroidManifest.xml中配置目标Activityintent-filter

data中可以指定需要匹配的URL的schemehostpathpathPrefix

注意:这里exported要设置成true,以便可以被其他应用打开,Android12开始如果Activity配置了intent-filter,强制要求显示设置exported值。

<activity android:name="com.will.LoginActivity"
            android:exported="true">
            <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="will"
                    android:pathPrefix="/login" />
            </intent-filter>
        </activity>

接收Intent中的数据

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Intent intent = getIntent();
        String action = intent.getAction();
        Uri data = intent.getData();
    
        String host = appLinkData.getHost();
        String lastPathSegment = appLinkData.getLastPathSegment();
        String source = appLinkData.getQueryParameter("source");
    }
    

Web页面跳转

schemepath匹配上文清单文件中的配置

window.location.href = 'will://login?source=web'

Deep Links方案的问题

  1. 如果定义的URL Scheme有多个APP满足的话,会弹出选择框让用户确认

  2. URL来源没有做验证,只要知道APP的自定义URL Scheme,例如a标签到mqq://, 就可以打开QQ

  3. 判断客户端是否成功唤起没有可靠的解决方案(通常是通过判断页面是否隐藏)

    总的来说就是网页和APP之间双向都没有做身份校验,但是优点是具有通用性,对于Android和iOS来说都通用,也支持自定义Scheme。

App Links

清单文件配置

第一步同样是需要在AndroidManifest.xml中配置目标Activityintent-filter

不同的是这次需要加上autoVerify="true"的属性,用户安装应用时,Android 会看到包含 autoVerify 属性的 intent 过滤器,并检查指定URL是否是关联验证链接。

scheme只支持http或者https

actionandroid.intent.action.VIEW

categoryandroid.intent.category.BROWSABLE 和android.intent.category.DEFAULT

<activity android:name="com.will.LoginActivity"
            android:exported="true">
            <intent-filter android:autoVerify="true"
                tools:targetApi="m">
                <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:scheme="https" />
                <data android:host="demo.will.com"/>
            </intent-filter>
        </activity>

接收Intent中的数据

数据接收的部分和Deep Links方法一样处理

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Intent intent = getIntent();
        String action = intent.getAction();
        Uri data = intent.getData();
    
        String host = appLinkData.getHost();
        String lastPathSegment = appLinkData.getLastPathSegment();
        String source = appLinkData.getQueryParameter("source");
    }
    

Digital Asset Links配置

创建文件assetlinks.json

[{  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.demo.will",
    "sha256_cert_fingerprints":
   ["B0:4E:29:05:4E:AB:44:C6:9A:CB:D5:89:A3:A8:1C:FF:09:6B:45:00:C5:FD:D1:3E:3E:12:C5:F3:FB:BD:BA:D3"]
  }
}]

json文件中包含了声明语句列表,这代表一个域名可以配置多个关联的APP,例如带有不同签名的测试版本和生产版本。

  • relation: 描述了网页和目标应用的关联关系(目标应用可以是APP,可以是其他的网页),delegate_permission/common.handle_all_urls 表示目标应用可以打开当前网页,其他的例如delegate_permission/common.get_login_creds表示目标应用可以获取当前的登录凭证。

  • target: 当前网页关联的目标应用,可以是web 和 android_app

    • namespace: android_app 或者 web

    • package_name: Android应用的Application Id

    • sha256_cert_fingerprints: 应用签名

sha256_cert_fingerprints 通常有俩种获取方式:

  1. 针对签名文件keystore,执行命令

    keytool -list -v -keystore [my-release-key.keystore]

  2. 针对已经签名的APK文件,执行命令

    keytool -printcert -jarfile [path-to-apk]

上传assetlinks.json到网页

上传assetlinks.json到你网页的指定路径下:

https://domain.name/.well-known/assetlinks.json

例如:Google的AssetLink地址

网页和APP的关联验证

用户安装应用时,Android 会看到包含 autoVerify 属性的 intent 过滤器,并查看intent data中指定URL下的.well-known路径下的关联应用列表中是否包含当前应用,如果包含当前应用,那么Android就会认为该网页为经过验证的允许此应用打开的网络连接(.well-known 路径段通常用于存放一些标准化的元数据或配置文件,这些文件被用来提供关于网站、应用或服务的信息)。

从Android12开始,除了Android系统会在应用安装时自动验证以外,我们也可以通过ADB命令手动执行和查看关联验证,

  1. 手动执行验证

    adb shell pm verify-app-links --re-verify PACKAGE_NAME

  2. 查看验证结果

    adb shell pm get-app-links PACKAGE_NAME

    可以看到结果显示类似

    com.xxx.xxx:
     ID: f9a077eb-0311-4d7d-8eb7-b5e02ae462d7
     Signatures: [***]
     Domain verification state:
     demo.will.com: verified
    

其他一些可能用到的相关ADB命令:

查看机器中的所有APP关联的APP Links

adb shell dumpsys package d

App Links方案的问题

  1. Android6.0及以上支持

  2. URL Scheme只支持http或者https

Intents with Chrome

另外再补充一种小众的方案,Chrome支持Android Intent的格式来唤起APP

基于Intent的URL格式

intent:  
   HOST/URI-path // Optional host  
   #Intent;  
      package=\[string\];  
      action=\[string\];  
      category=\[string\];  
      component=\[string\];  
      scheme=\[string\];  
   end;

Chrome Intents还支持设置fallback URL,如果APP无法被成功唤起时,跳转到fallback URL

S.browser_fallback_url=[encoded_full_url]

如果未设置fallback URL,目标APP未安装时会跳转到Google Play的APP下载页。

Web页面跳转

window.location.href = 
'intent:#Intent;scheme=will;package=com.will.app;S.browser_fallback_url=https%3A%2F%2Fbackup.com;end'

APP端清单文件的注册和Activity中Intent的处理和上面URL Scheme处理一样。

Chrome Intents在其他浏览器测试下有俩种情况:

  1. 跳转到fallback URL

  2. 无响应

更多详情参考Chrome官网

App Links Assistant

另外Android Studio提供了App Links Assistant 来帮助开发人员更方便的接入Deep Links以及App Links,可以通过[官网](添加 Android App Links  |  Android Studio  |  Android Developers)查看更多详情。