iOS带查询参数的Universal Link无法正常工作求助
iOS Universal Link 带查询参数配置指南(含Flutter集成)
一、AASA 文件的正确配置
你之前的AASA配置存在语法错误和匹配规则误区,正确的查询参数匹配不需要固定长度或多余的问号,以下是针对https://domain/forgot-password?token=xxx的有效配置:
{ "applinks": { "details": [ { "appIDs": [ "TEAM_ID.BUNDLE_ID" ], "components": [ { "/": "/forgot-password", "?": { "token": "*" } } ] } ] } }
- 注意事项:
- 将
TEAM_ID替换为你的苹果开发者团队ID,BUNDLE_ID替换为App的Bundle ID - 查询参数匹配用
*通配符即可,无需指定长度或额外加问号 - 确保JSON语法完全正确(比如引号闭合、逗号分隔),你之前迭代1的
"token" : "?*}存在引号未闭合的低级错误 - AASA文件必须部署在
https://domain/.well-known/apple-app-site-association路径,服务器需支持HTTPS、无重定向,且文件的Content-Type需设为application/json
- 将
二、iOS 原生项目配置
- 开启Associated Domains:在Xcode项目的Signing & Capabilities中,添加
Associated Domains能力,然后添加上applinks:domain(把domain替换为你的实际域名) - 验证ID一致性:确保AASA文件中的
appIDs与Xcode里的Team ID、Bundle ID完全匹配 - 确认AASA抓取状态:设备安装App后,系统会自动抓取AASA文件,也可通过Xcode调试工具查看文件是否被正确识别
三、Flutter 端的参数处理
需要在iOS的AppDelegate中实现Universal Link的回调逻辑,将查询参数传递给Flutter:
Swift 版本(AppDelegate.swift)
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void ) -> Bool { if userActivity.activityType == NSUserActivityTypeBrowsingWeb { guard let url = userActivity.webpageURL else { return false } // 解析token参数 let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let token = components?.queryItems?.first(where: { $0.name == "token" })?.value // 通过MethodChannel将参数传给Flutter let channel = FlutterMethodChannel(name: "com.example.universal_link", binaryMessenger: window?.rootViewController as! FlutterBinaryMessenger) channel.invokeMethod("handleForgotPassword", arguments: ["token": token ?? ""]) } return super.application(application, continue: userActivity, restorationHandler: restorationHandler) } }
Objective-C 版本(AppDelegate.m)
#import "AppDelegate.h" #import <Flutter/Flutter.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSString *token = nil; for (NSURLQueryItem *item in components.queryItems) { if ([item.name isEqualToString:@"token"]) { token = item.value; break; } } FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.example.universal_link" binaryMessenger:self.window.rootViewController]; [channel invokeMethod:@"handleForgotPassword" arguments:@{@"token": token ?: @""}]; } return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } @end
随后在Flutter代码中监听MethodChannel,处理参数:
import 'package:flutter/services.dart'; class _MyHomePageState extends State<MyHomePage> { static const platform = MethodChannel('com.example.universal_link'); @override void initState() { super.initState(); platform.setMethodCallHandler((call) async { if (call.method == 'handleForgotPassword') { String token = call.arguments['token']; // 执行重置密码逻辑,比如跳转至重置页面并传入token Navigator.push(context, MaterialPageRoute(builder: (context) => ForgotPasswordPage(token: token))); } }); } // ...其他业务代码 }
四、常见问题排查
- 链接无法在浏览器打开:检查域名DNS解析是否正常、HTTPS证书是否有效,确保
https://domain/forgot-password本身可正常访问 - 无法唤起App:
- 确认设备已安装对应App,且Bundle ID与AASA配置完全一致
- 测试时避免在第三方App(如微信)中点击链接,建议用Safari或短信打开(部分App会拦截Universal Link)
- 检查AASA是否被正确抓取:可在Xcode的Window > Devices and Simulators中选中设备,查看App容器内的
Library/Caches/com.apple.LaunchServices-054.csstore文件,搜索你的域名确认是否存在匹配记录
内容的提问来源于stack exchange,提问作者Banka Uday
相关产品推荐
相关产品推荐

