一文搞懂 DeepLink:从原理到 iOS/Android 实战

发布时间:2026/5/21 15:17:51

一文搞懂 DeepLink:从原理到 iOS/Android 实战 你在微信里点过一个商品链接然后手机直接蹦到了淘宝的商品详情页——不是在浏览器里打开网页是真的把 App 拉起来了。这东西就叫 DeepLink。听起来不复杂但真要做的时候你会发现坑多得离谱iOS 和 Android 方案完全不一样微信还给你拦一道老方案的兼容性又是个问题。这篇文章把 DeepLink 的几种实现方式捋一遍附带 iOS 和 Android 的配置代码。先搞清楚它到底干了什么DeepLink 就是一套 URL 路由协议。App 提前告诉操作系统我认识这类链接系统收到链接之后就去找对应的 App把路径参数传过去App 再跳到对应的页面。看几个例子就明白了场景普通链接行为DeepLink 行为微信里点外卖链接打开外卖网页版直接打开外卖 App 并跳到商品详情页短信里点银行链接打开银行网页直接打开银行 App 并跳到账户页面浏览器里点直播链接打开网页端直接打开直播 App 并进入直播间三种实现方式只有两种值得用URL Scheme——能用但别用了这是最早的方案自定义一个协议头比如taobao://product?id123456// 格式taobao://product?id123456// iOS 配置 Info.plistkeyCFBundleURLTypes/keyarraydictkeyCFBundleURLSchemes/keyarraystringtaobao/string/array/dict/array为什么说这条路基本废了三个硬伤iOS 9 之后会弹确认框用户体验很差任何 App 都能注册同一个 Scheme你的链接可能被别人的 App 劫持你根本没法知道用户手机上有没有装能处理这个 Scheme 的 App所以现在新项目就别考虑 URL Scheme 了直接上后面两种。Universal Link——iOS 的正解iOS 9.2 之后推出的方案思路很聪明不用自定义协议了直接用 HTTPS 链接。系统能验证这个域名确实属于你的 App就自动拉起。流程是这样的用户点击 https://yourdomain.com/product/123 ↓ iOS 系统检查 apple-app-site-association 文件 ↓ 确认 yourdomain.com 属于你的 App ↓ 直接拉起 App传递路径参数配置起来稍微麻烦但也就三步。先在你的域名根目录放一个apple-app-site-association文件{applinks:{details:[{appID:ABC123.com.yourapp,paths:[/product/*,/user/*,/order/*]}]}}注意这个文件没有.json后缀路径是https://yourdomain.com/apple-app-site-association。然后去 Xcode 里配置Xcode → Signing Capabilities → Associated Domains 添加: applinks:yourdomain.com最后在代码里处理跳转// SceneDelegate.swiftfuncscene(_scene:UIScene,continueuserActivity:NSUserActivity){// 监听 Universal Link 跳转guarduserActivity.activityTypeNSUserActivityTypeBrowsingWeb,leturluserActivity.webpageURLelse{return}// 解析路径例如 yourdomain.com/product/123 → product/123letpathurl.pathComponentsifpath.count2{lettargetpath[1]// productletidpath[2]// 123handleDeepLink(target:target,id:id)}}// 根据不同路径跳转到对应页面funchandleDeepLink(target:String,id:String){switchtarget{caseproduct:letvcProductDetailViewController(id:id)navigationController?.pushViewController(vc,animated:true)caseuser:letvcUserProfileViewController(id:id)navigationController?.pushViewController(vc,animated:true)default:break}}这里有个容易忽略的点iOS 13 之后用了 SceneDelegate如果你还在 AppDelegate 里写 Universal Link 的处理逻辑根本不会回调。这个坑后面还会提到。App Link——Android 这边同理Android 的 App Link 和 iOS 的 Universal Link 原理几乎一样都是用 HTTPS 链接 域名验证。先在AndroidManifest.xml里配置 intent-filter注意android:autoVerifytrue这个属性不能少activityandroid:name.MainActivityintent-filterandroid:autoVerifytrueactionandroid:nameandroid.intent.action.VIEW/categoryandroid:nameandroid.intent.category.BROWSABLE/categoryandroid:nameandroid.intent.category.DEFAULT/!-- 支持 https 协议 --dataandroid:schemehttpsandroid:hostyourdomain.comandroid:pathPrefix/product//intent-filter/activity然后在域名根目录放验证文件路径是https://yourdomain.com/.well-known/assetlinks.json[{relation:[delegate_permission/common.view],target:{namespace:android_app,package_name:com.example.yourapp,sha256_cert_fingerprints:[AA:BB:CC:DD:EE:FF:...]}}]这里sha256_cert_fingerprints必须和你打包用的签名证书一致不然验证过不了。换个签名就失效这种事我亲眼见过。代码处理部分// MainActivity.ktoverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)// 处理 App LinkhandleIntent(intent)}overridefunonNewIntent(intent:Intent?){super.onNewIntent(intent)intent?.let{handleIntent(it)}}privatefunhandleIntent(intent:Intent){valuriintent.data?:returnvalpathSegmentsuri.pathSegmentsif(pathSegments.size2){valtargetpathSegments[0]// productvalidpathSegments[1]// 123when(target){product-navigateToProduct(id)user-navigateToUser(id)}}}H5 中间页怎么写实际业务里用户从浏览器点链接你得先判断他装没装 App装了就跳 App没装就去下载页。functionopenDeepLink(deepLink,webUrl,downloadUrl){constisMobile/iPhone|iPad|Android/i.test(navigator.userAgent);constisWechat/MicroMessenger/i.test(navigator.userAgent);// 微信内置浏览器特殊处理if(isWechat){// 微信不支持直接跳转 App Link引导用户复制链接在浏览器打开alert(请点击右上角「在浏览器打开」);return;}// 尝试跳转 Appwindow.location.hrefdeepLink;// 2秒后如果还在当前页说明没装 App跳下载setTimeout((){if(document.hidden||document.webkitHidden){// App 已经拉起return;}window.location.hrefdownloadUrl;},2000);}// 使用示例openDeepLink(myapp://product/123,// App 协议https://yourdomain.com/product/123,// 降级网页https://yourdomain.com/download// 下载页);这个先跳再等 2 秒的方案比较粗暴但确实是业界最常用的做法。更精细的方案可以结合 Universal Link 做无缝跳转不过那得有后端配合。微信这个拦路虎微信对 DeepLink 的封锁是最让人头疼的。好在有几种绕法应用宝中间页腾讯亲儿子方案在应用宝生成中间页微信里长按识别二维码跳转。接起来不算麻烦但体验上多了一步。微信开放标签需要公众号认证用微信的 JSSDK 调起 App!-- 需要引入微信 JSSDK --scriptsrchttps://res.wx.qq.com/open/js/jweixin-1.6.0.js/script!-- 使用开放标签 --wx-open-launch-appappidwxAPP_IDextinfoproduct/123templatebutton打开 App/button/template/wx-open-launch-appUniversal Link 穿透iOS 微信 7.0.7 之后对 Universal Link 放行了可以直接跳。这是目前 iOS 侧最干净的方案。说实话微信这一块没有银弹通常得几种方案组合着来。别忘了打点追踪DeepLink 不只是个跳转功能它最实际的价值在于渠道追踪——用户从哪来的、哪个活动的转化率高全靠链接上带的参数。// 带参数的 DeepLinkfunctiongenerateDeepLink(baseUrl,params){constquerynewURLSearchParams(params).toString();return${baseUrl}?${query};}// 生成带渠道参数的链接constlinkgenerateDeepLink(https://yourdomain.com/product/123,{channel:wechat,// 渠道campaign:spring,// 活动uid:user_123// 用户标识});// 解析时获取参数functionparseDeepLink(){constparamsnewURLSearchParams(window.location.search);console.log(params.get(channel));// wechatconsole.log(params.get(campaign));// spring}我踩过的坑坑怎么解Universal Link 一直不生效先确认apple-app-site-association文件能直接访问再检查 JSON 格式——少个逗号就不会报错但也不生效Android App Link 验证失败sha256_cert_fingerprints必须和打包签名一致debug 和 release 签名不同要注意微信无法跳转应用宝中间页是最稳的或者引导用户去浏览器打开iOS 13 回调收不到检查 SceneDelegate 配置AppDelegate 里写是没用的最后整理一下选型平台推荐方案兼容性iOSUniversal LinkiOS 9.2AndroidApp LinkAndroid 6.0微信内开放标签/应用宝需要认证相关技术iOS开发 · Android开发 · URL路由

相关新闻