Android Deep Link 与 App Link 深度解析

367 阅读11分钟

Android Deep Link 与 App Link 深度解析:原理、实践与演进

深入探讨移动端引流的核心技术,从通用 Scheme 到官方的 App Link,并提供详尽的实践指南。

1. 引言:为何需要“唤端”技术?

在移动互联网生态中,孤岛式的应用无法满足用户无缝连接的需求。我们经常遇到这样的场景:

  1. 点击朋友圈的广告,直接跳转到电商APP的商品页
  2. 浏览新闻时看到一个有趣的短视频,点击后唤起了抖音并定位到该视频
  3. 收到银行转账短信,点击链接直接打开手机银行APP查看详情
  4. 朋友分享的购物链接,点击后直接在淘宝APP打开对应商品

这种从短信、Web(H5)页面、社交媒体等场景无缝跳转到原生应用(Native APP)的技术,被称为  "唤端" ​ 或深度链接

2. Android Deep Link (URL Scheme):通用但存瑕的元老

2.1 核心原理

想象一下,每个APP都像一座独立的城堡,URL Scheme就是为每个城堡设计的"秘密密道"。这个密道有一个特殊的暗号格式,比如知乎的密道暗号是 zhihu://

工作机制

  • 应用向操作系统"登记"自己的密道暗号
  • 当系统遇到 zhihu://questions/123456这样的暗号时
  • 系统会找到所有能听懂这个暗号的APP
  • 弹出一个选择器:"你要用哪个城堡的密道?"

2.2 短信场景中的 URL Scheme

短信是深度链接最常见的应用场景之一:

<!-- 银行发送的转账通知短信 -->
尊敬的客户,您尾号8888的储蓄卡收入5000.00元。
<a href="icbc://transfer/result?order=20240119001">点击查看详情</a>
立即下载:<a href="https://appstore/icbc">应用商店</a>

短信中的实现方式

  1. 在短信中直接嵌入 scheme://path格式的链接
  2. 用户点击后,如果已安装APP → 直接打开
  3. 如果未安装APP → 显示无法打开的提示

2.3 实现方式

H5页面触发跳转

// 方法1:直接跳转
function openAppByScheme() {
    window.location.href = 'zhihu://question/123456';
}

// 方法2:通过iframe跳转(更稳定)
function openAppByIframe() {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = 'zhihu://question/123456';
    document.body.appendChild(iframe);
    
    // 2秒后移除iframe
    setTimeout(() => {
        document.body.removeChild(iframe);
    }, 2000);
}

// 方法3:处理短信链接
function handleSmsLink() {
    // 短信链接通常是直接可点击的
    // 用户点击 <a href="zhihu://question/123">短信链接</a> 即可
}

Android原生端配置AndroidManifest.xml):

<!-- 接收Scheme链接的Activity -->
<activity android:name=".DeepLinkActivity"
    android:exported="true">
    
    <!-- 声明Scheme处理能力 -->
    <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="deeplink"
            android:scheme="zhihu" />
            
        <!-- 可选:更精确的路径匹配 -->
        <data android:pathPrefix="/question/" />
    </intent-filter>
    
    <!-- 可以声明多个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" />
        <!-- 另一个Scheme -->
        <data android:scheme="zh" />
    </intent-filter>
</activity>

2.4 在Activity中处理传入的链接

class DeepLinkActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_deeplink)
        
        // 处理传入的Intent
        handleDeepLink(intent)
    }
    
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 防止重复创建Activity
        setIntent(intent)
        handleDeepLink(intent)
    }
    
    private fun handleDeepLink(intent: Intent?) {
        intent?.data?.let { uri ->
            when {
                // 处理知乎问答链接
                uri.toString().startsWith("zhihu://question/") -> {
                    val questionId = uri.lastPathSegment
                    openQuestionDetail(questionId)
                }
                // 处理用户主页链接
                uri.toString().startsWith("zhihu://user/") -> {
                    val userId = uri.lastPathSegment
                    openUserProfile(userId)
                }
                // 处理短信中的银行链接
                uri.toString().startsWith("icbc://") -> {
                    handleBankTransaction(uri)
                }
            }
        }
    }
    
    private fun openQuestionDetail(questionId: String?) {
        // 跳转到问题详情页
        val intent = Intent(this, QuestionDetailActivity::class.java)
        intent.putExtra("QUESTION_ID", questionId)
        startActivity(intent)
        finish()
    }
}

2.5 优缺点分析

优点

  • ✅ 兼容性极佳:从Android 1.0到最新版本都支持
  • ✅ 实现简单:只需在AndroidManifest中声明即可
  • ✅ 短信友好:短信中直接可点击,无需特殊处理

缺点

  • ❌ 弹出选择器:每次都要问用户"用哪个应用打开?"
  • ❌ 无法判断是否成功:只能靠猜(定时器方案不准确)
  • ❌ 容易被劫持:恶意应用可注册相同Scheme
  • ❌ 微信/QQ中被屏蔽:这些应用会拦截非白名单Scheme
  • ❌ 无降级方案:如果APP没安装,链接就打不开

3. Android App Link:官方出品的优雅方案

3.1 核心原理:基于域名的所有权验证

把App Link想象成官方的快递系统

  1. 使用标准地址:不再用密道暗号,而是用大家都能看懂的"街道地址"(HTTPS网址)

    • 原来是:zhihu://question/123
    • 现在是:https://www.zhihu.com/question/123
  2. 域名所有权验证:你要证明"知乎大街888号"确实是你家的

    • 在 www.zhihu.com这个"房产证"上,加上你的"指纹信息"
    • Android系统会派人去查看"房产证"
    • 如果指纹匹配,就直接把快递(用户)送到你家,不再问"送哪家?"

3.2 详细配置流程(保姆级教程)

第1步:在AndroidManifest中声明
<activity android:name=".AppLinkActivity"
    android:exported="true">
    
    <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" />
        
        <!-- 声明你的HTTPS链接格式 -->
        <data
            android:scheme="https"
            android:host="www.zhihu.com"
            android:pathPrefix="/question/" />
            
        <!-- 可以匹配更多路径 -->
        <data android:pathPrefix="/answer/" />
        <data android:pathPrefix="/user/" />
    </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:scheme="https"
            android:host="zhihu.com"
            android:pathPrefix="/m/" />
    </intent-filter>
</activity>
第2步:获取应用的"指纹"

每个Android应用都有唯一的"指纹"(SHA-256证书指纹),获取方法:

方法A:从签名文件中获取(推荐)

# 使用keytool查看签名信息
keytool -list -v -keystore your-release-key.keystore

# 会看到类似这样的输出:
# SHA256: 33:5A:45:9B:0C:... (很长一串)

方法B:从已安装的APP获取(调试用)

# 1. 先获取签名证书的MD5
adb shell pm dump com.zhihu.android | grep "Signatures"

# 2. 用keytool转换
keytool -printcert -file platform.x509.pem

方法C:在代码中获取

fun getAppSignature(context: Context): String {
    val packageInfo = context.packageManager.getPackageInfo(
        context.packageName,
        PackageManager.GET_SIGNATURES
    )
    val signatures = packageInfo.signatures
    val md = MessageDigest.getInstance("SHA-256")
    val digest = md.digest(signatures[0].toByteArray())
    return digest.joinToString(":") { "%02X".format(it) }
}
第3步:创建assetlinks.json文件

创建一个JSON文件,内容格式如下:

[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.zhihu.android",  // 你的应用包名
      "sha256_cert_fingerprints": [
        "33:5A:45:9B:0C:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
        // ↑ 这里填上一步获取的指纹
      ]
    }
  },
  // 如果你有多个签名(比如调试版和发布版不同签名)
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.zhihu.android",
      "sha256_cert_fingerprints": [
        "AA:BB:CC:...",  // 调试版签名指纹
        "DD:EE:FF:..."   // 发布版签名指纹
      ]
    }
  }
]
第4步:部署assetlinks.json到服务器

部署位置必须精确

https://你的域名/.well-known/assetlinks.json

示例

  • 如果你的域名是 www.zhihu.com
  • 文件必须放在:https://www.zhihu.com/.well-known/assetlinks.json

注意事项

  1. 必须通过HTTPS访问
  2. Content-Type必须是 application/json
  3. 必须返回200状态码
  4. 不能有重定向
  5. 文件大小不超过100KB

验证是否部署成功

# 在浏览器中直接访问
curl -I https://www.zhihu.com/.well-known/assetlinks.json

# 应该看到:
# HTTP/2 200
# content-type: application/json
第5步:测试验证

方法A:使用ADB命令测试

# 测试普通深度链接
adb shell am start -W -a android.intent.action.VIEW -d "https://www.zhihu.com/question/123456"

# 验证域名关联状态
adb shell pm get-app-links com.zhihu.android

# 强制验证(第一次安装时系统会自动验证)
adb shell pm verify-app-links --re-verify com.zhihu.android

方法B:在Android Studio中测试

  1. 运行APP到手机
  2. 点击Android Studio的"Logcat"
  3. 过滤"DigitalAssetLinks"
  4. 查看验证日志

方法C:通过网页测试

<!-- 创建一个测试HTML文件 -->
<!DOCTYPE html>
<html>
<body>
  <a href="https://www.zhihu.com/question/123456">
    点击这里应该直接打开知乎APP
  </a>
</body>
</html>

3.3 短信中的App Link使用

在短信中使用App Link时,用户会有无缝的体验:

<!-- 银行发送的转账成功短信(使用App Link) -->
【XX银行】您尾号8888的账户收入5,000.00元。
<a href="https://bank.example.com/transfer/20240119001">点击查看详情</a>

<!-- 电商订单短信 -->
【XX商城】您的订单已发货,快递单号:YT123456789
<a href="https://m.taobao.com/order/123456">查看物流</a>

<!-- 社交分享短信 -->
张三给您分享了一个视频:
<a href="https://www.douyin.com/video/123456">点击观看</a>

短信中App Link的优势

  1. 无缝体验:已安装APP → 直接打开;未安装 → 打开网页版
  2. 安全性高:HTTPS链接,防止劫持
  3. 可追踪:通过网页可统计点击率、转化率
  4. 兼容性好:所有手机短信都支持HTTPS链接

3.4 处理App Link的Activity代码

class AppLinkActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 处理深度链接
        handleAppLink(intent)
    }
    
    private fun handleAppLink(intent: Intent) {
        val uri = intent.data ?: return
        
        when {
            // 处理问题详情页
            uri.path?.startsWith("/question/") == true -> {
                val questionId = uri.lastPathSegment
                openQuestionPage(questionId)
            }
            
            // 处理回答详情页
            uri.path?.startsWith("/answer/") == true -> {
                val answerId = uri.lastPathSegment
                openAnswerPage(answerId)
            }
            
            // 处理用户主页
            uri.path?.startsWith("/user/") == true -> {
                val userId = uri.lastPathSegment
                openUserProfile(userId)
            }
            
            // 处理查询参数
            else -> {
                val id = uri.getQueryParameter("id")
                val type = uri.getQueryParameter("type")
                handleGenericLink(id, type)
            }
        }
    }
    
    // 处理用户从短信或其他地方打开的情况
    private fun handleSmsAppLink(uri: Uri) {
        // 记录来源
        val referrer = intent.getStringExtra(Intent.EXTRA_REFERRER)
        val fromSms = referrer?.contains("sms") == true
        
        if (fromSms) {
            // 特殊处理短信来源的流量
            trackEvent("sms_deeplink_open")
        }
    }
}

3.5 处理边缘情况

// 1. 处理多任务栈
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    // 如果是从历史记录中恢复,清除任务栈重新开始
    if (intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY != 0) {
        finish()
        return
    }
}

// 2. 处理重复打开
private var isProcessing = false

private fun handleDeepLinkSafely(intent: Intent) {
    if (isProcessing) {
        return
    }
    isProcessing = true
    
    try {
        // 处理链接
        processIntent(intent)
    } finally {
        isProcessing = false
    }
}

// 3. 延迟初始化处理
override fun onResume() {
    super.onResume()
    
    if (shouldHandleIntent) {
        // 等UI加载完成后再处理
        view.post {
            handleDeepLink(intent)
            shouldHandleIntent = false
        }
    }
}

4. 最佳实践:完整唤端方案

4.1 智能唤端策略

// 完整的H5唤端方案
class DeepLinkManager {
    constructor(options = {}) {
        this.options = {
            appLink: 'https://www.zhihu.com/question/123456',
            schemeLink: 'zhihu://question/123456',
            appStoreLink: 'https://apps.apple.com/app/id123456', // iOS
            playStoreLink: 'https://play.google.com/store/apps/details?id=com.zhihu.android',
            timeout: 1500,
            ...options
        };
        
        this.timer = null;
        this.hasApp = false;
    }
    
    // 主唤端方法
    open() {
        // 检查是否在特定浏览器中
        if (this.isInWechat()) {
            this.handleWechat();
            return;
        }
        
        if (this.isInQQ()) {
            this.handleQQ();
            return;
        }
        
        // 正常唤端流程
        this.startWatching();
        this.tryOpenAppLink();
    }
    
    // 尝试App Link
    tryOpenAppLink() {
        // 先尝试App Link
        this.openLink(this.options.appLink);
        
        // 设置超时检查
        this.timer = setTimeout(() => {
            if (!this.hasApp) {
                this.tryScheme();
            }
        }, this.options.timeout);
    }
    
    // 降级到Scheme
    tryScheme() {
        this.openLink(this.options.schemeLink);
        
        // Scheme也失败,跳转应用商店
        this.timer = setTimeout(() => {
            if (!this.hasApp) {
                this.goToAppStore();
            }
        }, 1000);
    }
    
    // 监听页面隐藏(表示唤端成功)
    startWatching() {
        this.hasApp = false;
        
        const onVisibilityChange = () => {
            if (document.hidden) {
                this.hasApp = true;
                if (this.timer) clearTimeout(this.timer);
            }
        };
        
        const onBlur = () => {
            this.hasApp = true;
            if (this.timer) clearTimeout(this.timer);
        };
        
        document.addEventListener('visibilitychange', onVisibilityChange);
        window.addEventListener('pagehide', onVisibilityChange);
        window.addEventListener('blur', onBlur);
        
        // 清理监听
        this.cleanup = () => {
            document.removeEventListener('visibilitychange', onVisibilityChange);
            window.removeEventListener('pagehide', onVisibilityChange);
            window.removeEventListener('blur', onBlur);
        };
    }
    
    // 处理微信环境
    handleWechat() {
        // 微信中无法直接打开App
        // 引导用户在其他浏览器中打开
        this.showWechatGuide();
    }
    
    // 工具方法
    isInWechat() {
        return /MicroMessenger/i.test(navigator.userAgent);
    }
    
    isInQQ() {
        return /QQ//i.test(navigator.userAgent);
    }
    
    openLink(url) {
        // 使用iframe方式,避免页面跳转
        const iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = url;
        document.body.appendChild(iframe);
        
        setTimeout(() => {
            document.body.removeChild(iframe);
        }, 1000);
    }
    
    goToAppStore() {
        if (this.isIOS()) {
            window.location.href = this.options.appStoreLink;
        } else {
            window.location.href = this.options.playStoreLink;
        }
    }
    
    isIOS() {
        return /iPad|iPhone|iPod/.test(navigator.userAgent);
    }
    
    destroy() {
        if (this.timer) clearTimeout(this.timer);
        if (this.cleanup) this.cleanup();
    }
}

// 使用示例
const deeplink = new DeepLinkManager({
    appLink: 'https://www.zhihu.com/question/123456',
    schemeLink: 'zhihu://question/123456',
    timeout: 2000
});

// 点击按钮时触发
document.getElementById('open-app-btn').addEventListener('click', () => {
    deeplink.open();
});

4.2 Android端完整配置

<!-- AndroidManifest.xml 完整示例 -->
<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTask">  <!-- 建议使用singleTask -->
    
    <!-- Deep Link (URL Scheme) -->
    <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="zhihu"
            android:host="deeplink" />
    </intent-filter>
    
    <!-- App Link 1: 主域名 -->
    <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:scheme="https"
            android:host="www.zhihu.com"
            android:pathPrefix="/question/" />
    </intent-filter>
    
    <!-- App Link 2: 短链接域名 -->
    <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:scheme="https"
            android:host="zhihu.cn"
            android:pathPattern="/q/.*" />
    </intent-filter>
    
    <!-- App Link 3: 分享链接域名 -->
    <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:scheme="https"
            android:host="share.zhihu.com" />
    </intent-filter>
</activity>

5. 常见问题与解决方案

问题1:App Link验证失败

可能原因

  1. assetlinks.json文件访问不到
  2. 证书指纹不匹配
  3. 包名写错了
  4. 服务器返回了错误的Content-Type

解决方案

# 1. 检查文件是否可访问
curl -I https://yourdomain.com/.well-known/assetlinks.json

# 2. 查看验证状态
adb shell pm get-app-links your.package.name

# 3. 强制重新验证
adb shell pm verify-app-links --re-verify your.package.name

# 4. 清除验证结果
adb shell pm set-app-links --package your.package.name 0 all

问题2:用户选择了"记住选择"

场景:用户第一次点击时,选择了"用浏览器打开"并勾选了"总是"。

解决方案

// 引导用户去设置中修改
fun showOpenByDefaultDialog(context: Context) {
    AlertDialog.Builder(context)
        .setTitle("打开方式设置")
        .setMessage("检测到您之前选择了用浏览器打开,是否要修改设置?")
        .setPositiveButton("去设置") { _, _ ->
            // 跳转到应用的默认打开方式设置
            val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
            intent.data = Uri.parse("package:${context.packageName}")
            context.startActivity(intent)
        }
        .setNegativeButton("取消", null)
        .show()
}

问题3:短信链接在国产手机上被拦截

现象:在小米、华为等手机上,点击短信中的链接会先打开浏览器。

解决方案

// 检查并引导用户
fun checkAndHandle(context: Context, uri: Uri) {
    val isFromSms = intent?.getStringExtra("from") == "sms"
    
    if (isFromSms && !isAppDefaultHandler(context)) {
        // 显示引导页
        showGuidePage(context)
    } else {
        // 正常处理
        handleDeepLink(uri)
    }
}

// 检查APP是否是默认处理器
fun isAppDefaultHandler(context: Context): Boolean {
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://yourdomain.com"))
    val resolveInfo = context.packageManager.resolveActivity(
        intent,
        PackageManager.MATCH_DEFAULT_ONLY
    )
    return resolveInfo?.activityInfo?.packageName == context.packageName
}

6. 实战:电商App完整示例

6.1 短信营销链接

<!-- 双11促销短信 -->
【XX商城】双11提前购!爆款5折起,限时抢购!
<a href="https://m.xxshop.com/promo/11?source=sms">立即抢购</a>
(点击直接打开APP,未安装可先查看详情)

6.2 Android配置

<!-- 商品详情页 -->
<activity
    android:name=".ProductDetailActivity"
    android:exported="true"
    android:launchMode="singleTask">
    
    <!-- 支持的商品链接格式 -->
    <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:scheme="https"
            android:host="m.xxshop.com"
            android:pathPrefix="/product/" />
    </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:scheme="https"
            android:host="m.xxshop.com"
            android:pathPrefix="/promo/" />
    </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:scheme="https"
            android:host="m.xxshop.com"
            android:pathPrefix="/order/" />
    </intent-filter>
</activity>

6.3 服务器assetlinks.json

[  {    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.xxshop.app",
      "sha256_cert_fingerprints": [
        "发布版指纹1",
        "发布版指纹2"
      ]
    }
  },
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.xxshop.app.debug",
      "sha256_cert_fingerprints": [
        "调试版指纹"
      ]
    }
  }
]

7. 总结与建议

核心要点回顾

  1. URL Scheme:兼容性好但体验差,适合作为兜底方案
  2. App Link:体验好但需要配置验证,是未来趋势
  3. 短信场景:优先使用App Link,提供更好的降级体验

推荐方案

// 根据场景选择策略
function getDeepLinkStrategy(scenario) {
    const strategies = {
        'sms': 'applink',      // 短信用App Link
        'email': 'applink',    // 邮件用App Link
        'social_media': 'hybrid',  // 社交媒体用混合
        'web_page': 'hybrid',  // 网页用混合
        'qr_code': 'hybrid'    // 二维码用混合
    };
    return strategies[scenario] || 'hybrid';
}

实施建议

  1. 新项目:直接上App Link为主,Scheme兜底
  2. 老项目:逐步迁移到App Link
  3. 短信营销:一定要用App Link
  4. 用户引导:做好未安装APP的引导页
  5. 数据监控:统计各渠道的唤端成功率

未来趋势

  1. Instant Apps:无需安装即可使用部分功能
  2. App Clips:轻量级应用体验
  3. 跨平台方案:Firebase Dynamic Links、Branch.io等

深度链接技术是移动端流量获取和用户体验的关键。正确实施可以显著提升转化率和用户留存。随着Android生态的成熟,App Link已成为必备技能,建议所有Android开发者都要掌握。