Flutter中uni_link与go_router结合的Android深度链接异常问题
问题原因
Android平台下,通过深度链接唤起Flutter应用时,GoRouter会默认读取Android Intent中的data字段(即深度链接本身),并将其当作应用内路由路径尝试导航。由于你的深度链接并非GoRouter配置的有效路径,因此触发了errorBuilder;同时你又通过uni_links获取初始链接手动调用context.go(),导致两次导航逻辑冲突,出现异常行为。而iOS平台不存在这个默认行为,所以运行正常。
解决方案
提供三种可行的解决思路,按需选择:
方案1:强制指定GoRouter初始路径
初始化GoRouter时,通过initialLocation参数指定默认初始路径,覆盖Android传入的深度链接路径。让GoRouter不再自动处理外部深度链接,完全交由uni_links负责解析导航:
final router = GoRouter( initialLocation: '/', // 固定默认初始路径,忽略Android传入的深度链接 routes: [ // 你的应用路由配置 ], errorBuilder: (context, state) => ErrorPage(), );
之后保持initUniLinks的原有逻辑即可,不会再出现导航冲突。
方案2:在GoRouter的redirect中统一处理深度链接
如果不想完全忽略初始路径,可以在redirect回调中判断当前路径是否为外部深度链接,若是则直接解析并返回对应的内部路由路径,避免触发errorBuilder,同时省去uni_links的初始链接处理逻辑:
final router = GoRouter( redirect: (context, state) { final currentLocation = state.location; // 假设你的深度链接前缀是https://yourapp.com/,根据实际情况修改 if (currentLocation.startsWith('https://yourapp.com/')) { // 解析深度链接,转换为应用内有效路由 final internalPath = parseDeepLinkToInternalPath(currentLocation); return internalPath; } // 非深度链接路径,正常导航 return null; }, routes: [ // 你的应用路由配置 ], ); // 示例解析函数,根据实际业务逻辑实现 String parseDeepLinkToInternalPath(String deepLink) { // 比如将https://yourapp.com/detail/123转换为/detail/123 return deepLink.replaceFirst('https://yourapp.com', ''); }
方案3:调整AndroidManifest配置并完善链接监听
修改Android的AndroidManifest.xml,给FlutterActivity添加singleTop启动模式,同时确保uni_links能完整捕获初始链接和后续链接变化:
<activity android:name=".MainActivity" android:launchMode="singleTop" 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="https" android:host="yourapp.com" /> </intent-filter> </activity>
在Flutter端完善uni_links的监听逻辑,覆盖初始链接和后续链接唤起场景:
StreamSubscription? _linkSubscription; Future<void> initUniLinks() async { // 处理初始唤起链接 final initialLink = await getInitialLink(); if (initialLink != null) { _handleDeepLink(initialLink); } // 监听应用运行中收到的深度链接 _linkSubscription = uriLinkStream.listen((Uri? uri) { if (uri != null) { _handleDeepLink(uri.toString()); } }, onError: (error) { // 处理链接监听错误 }); } void _handleDeepLink(String link) { // 解析链接并导航到对应内部路径 final internalPath = parseDeepLinkToInternalPath(link); if (internalPath != null) { context.go(internalPath); } } // 页面销毁时取消订阅 @override void dispose() { _linkSubscription?.cancel(); super.dispose(); }
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

