Flutter使用receive_sharing_intent接收分享时无法跳转指定页面
问题原因
你当前的代码存在两个核心问题,对应两个跳转失败场景:
- 冷启动跳转失败:直接在
MyApp的build方法中执行导航逻辑,此时MaterialApp的路由栈还未完成初始化,传入的context不具备导航操作能力,Navigator.push执行无效。 - 前台运行跳转失败:
ReceiveSharingIntent.getInitialMedia()仅会在App进程完全未存活、被分享动作冷启动时返回分享内容,App处于前台/后台存活状态被分享唤起时,分享内容是通过流事件推送的,你当前代码没有监听对应流,自然拿不到回调触发跳转。
修复方案
需要同时覆盖冷启动、App存活唤起两个场景,同时保证跳转时机在路由初始化完成后执行,具体实现步骤:
- 定义全局
NavigatorKey,绑定到MaterialApp上,避免依赖未初始化的组件context做导航。 - 将根组件
MyApp改为StatefulWidget,在初始化逻辑中同时处理冷启动的初始分享内容、监听App存活时的分享流事件。 - 跳转逻辑放在首帧渲染完成的回调中执行,避免路由未挂载报错。
- 页面销毁时取消流订阅,防止内存泄漏。
完整可运行代码
import 'package:flutter/material.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'dart:async'; // 全局导航key,用于获取有效路由上下文 final GlobalKey<NavigatorState> globalNavigatorKey = GlobalKey<NavigatorState>(); class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { StreamSubscription? _shareEventListener; @override void initState() { super.initState(); _initShareListener(); } @override void dispose() { // 销毁时取消流订阅,避免内存泄漏 _shareEventListener?.cancel(); super.dispose(); } /// 统一处理分享跳转逻辑 void _navigateToAddPage(List<SharedMediaFile> shareFiles) { if (shareFiles.isEmpty) return; // 等首帧渲染完成、路由栈完全初始化后再跳转 WidgetsBinding.instance.addPostFrameCallback((_) { globalNavigatorKey.currentState?.push( MaterialPageRoute( builder: (_) => CategoryAddScreen(shareMediaList: shareFiles), ), ); }); } /// 初始化两个场景的分享监听 void _initShareListener() { // 处理冷启动场景:App进程未存活时被分享唤起 ReceiveSharingIntent.getInitialMedia().then(_navigateToAddPage); // 处理App存活场景:App在前台/后台运行时被分享唤起 _shareEventListener = ReceiveSharingIntent.getMediaStream().listen(_navigateToAddPage); } @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: globalNavigatorKey, // 绑定全局导航key // 保留你原有MaterialApp的其他配置,比如主题、首页、路由表等 // theme: ThemeData(...), // home: const HomePage(), // ... ); } } // 示例目标页面,可根据你的业务调整 class CategoryAddScreen extends StatelessWidget { final List<SharedMediaFile> shareMediaList; const CategoryAddScreen({Key? key, required this.shareMediaList}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('新增分类')), body: Center(child: Text('收到分享文件${shareMediaList.length}个')), ); } }
注意事项
- 若修改后仍无法收到回调,优先检查原生端配置:Android需确认
AndroidManifest.xml中对应Activity配置了匹配图片分享的intent-filter,iOS需确认Info.plist中配置了正确的分享权限与扩展。 - 如果需要在跳转前做登录态等前置判断,直接在
_navigateToAddPage方法中加判断逻辑即可,满足条件再执行push。 - 插件默认会缓存上一次的分享内容,如需重置可在处理完分享逻辑后调用
ReceiveSharingIntent.reset()清除缓存,避免重复触发跳转。
内容的提问来源于stack exchange,提问作者Too
相关产品推荐
相关产品推荐

