iOS旧版App触发未支持的Universal Links 如何做版本化适配?
iOS系统判断是否通过Universal Link拉起App的唯一依据是设备本地缓存的apple-app-site-association(AASA)文件的路径匹配规则,与App内部是否实际处理该路径无关。将/sign-up加入AASA后,所有安装了对应Bundle ID App的设备,只要路径匹配规则命中就会优先拉起App,之后才会走- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler回调。因此即使v1版本在回调中返回false,App被唤醒的行为已经发生,返回false仅会触发系统后续fallback到Safari打开,无法避免App被误拉起的问题。
路径强制加版本前缀,从根源隔离不同版本的支持范围
所有新增的Universal Link路径都带上对应支持的最低App版本号,比如v2版本才支持的注册路径统一使用/v2/sign-up,而非无版本的/sign-up。后续v3版本新增的路径全部放到/v3/*前缀下。
AASA文件中仅配置对应版本前缀的路径规则,也可以通过AASA的NOT语法排除不需要处理的路径,配置示例:{ "applinks": { "apps": [], "details": [ { "appID": "你的TeamID.你的BundleID", "paths": [ "/v1/*", "/v2/*", "NOT /v2/*/debug" ] } ] } }该方案下,v1版本的App代码默认仅处理
/v1/前缀的路径,后续新增的其他版本前缀路径即使匹配AASA规则,也不会触发v1版本的业务逻辑,配合回调返回false即可触发系统跳转到对应网页,不会影响老版本用户体验。新增全局统一的Universal Link校验层
不要在各业务场景单独处理回调返回值,统一在continueUserActivity入口做两层校验:- 优先判断路径前缀是否属于当前App版本支持的版本号范围,不属于直接返回false
- 再判断路径是否在当前版本支持的路径白名单内,不在也直接返回false
即使后续AASA误添加了新路径,老版本App也不会处理错误业务逻辑,同时触发系统fallback机制。
服务端增加版本兼容跳转兜底逻辑
对外暴露的无版本路径(比如对外宣传用的https://yourdomain.com/sign-up),服务端先判断用户设备安装的App版本,自动重定向到对应版本的带前缀路径:- 检测到用户安装v2及以上版本:跳转到
/v2/sign-up触发App拉起 - 检测到用户安装v1版本或未安装App:直接展示网页端注册页面,不会触发App拉起
- 检测到用户安装v2及以上版本:跳转到
AASA更新做灰度和版本适配
后续更新AASA文件时,不要直接全量添加全局无版本路径,优先添加带版本前缀的路径。如果必须使用无版本的全局路径,需等对应支持的版本用户覆盖率达到95%以上再加入AASA,避免大量老版本用户被误拉起。
针对现有v1用户被误拉起的问题,可以直接在AASA中移除无版本的/sign-up路径,仅保留/v2/sign-up路径,同时将对外的注册链接切换为带版本的路径,服务端配合做跳转兜底,即可避免v1用户被误拉起,同时不影响v2用户的正常使用。
内容的提问来源于stack exchange,提问作者Peter Foti

