You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:25:05