如何实现Flutter应用接收其他App的Intent(分享文件场景)
实现Flutter应用接收其他App发送的Intent(含图片分享场景)
我来帮你解决这个问题——让Flutter应用接收其他App分享的Intent(比如从相册分享图片)其实需要分Android端配置、iOS端配置和Flutter端逻辑处理三部分,下面一步步给你讲清楚:
一、快速方案:使用第三方插件(推荐)
最省心的方式是用成熟的第三方插件,比如receive_sharing_intent,它已经封装了跨平台的Intent/分享接收逻辑。
1. 安装插件
在pubspec.yaml中添加依赖:
dependencies: receive_sharing_intent: ^latest_version
然后运行flutter pub get拉取依赖。
2. Flutter端监听分享数据
在你的主页面中,初始化监听并处理接收的图片:
import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:http/http.dart' as http; import 'dart:io'; class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { Stream<List<SharedMediaFile>>? _sharedFilesStream; List<SharedMediaFile> _sharedFiles = []; @override void initState() { super.initState(); // 监听实时分享的内容(App前台时) _sharedFilesStream = ReceiveSharingIntent.getMediaStream(); _sharedFilesStream?.listen((List<SharedMediaFile> files) { setState(() { _sharedFiles = files; }); // 拿到图片后触发上传 if (_sharedFiles.isNotEmpty) { uploadImage(File(_sharedFiles.first.path)); } }); // 处理应用启动时已存在的分享数据(比如分享时App未打开) ReceiveSharingIntent.getInitialMedia().then((List<SharedMediaFile> files) { setState(() { _sharedFiles = files; }); if (_sharedFiles.isNotEmpty) { uploadImage(File(_sharedFiles.first.path)); } }); } // 图片上传的HTTP请求实现 Future<void> uploadImage(File imageFile) async { var request = http.MultipartRequest( 'POST', Uri.parse('https://your-upload-api-url.com/upload'), ); request.files.add(await http.MultipartFile.fromPath('image', imageFile.path)); var response = await request.send(); if (response.statusCode == 200) { print('图片上传成功'); } else { print('图片上传失败:${response.statusCode}'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('接收分享示例')), body: _sharedFiles.isEmpty ? const Text('等待其他App分享图片...') : Image.file(File(_sharedFiles.first.path)), ); } }
3. 平台端补充配置
- Android:插件会自动添加基础的
intent-filter,如果需要限定只接收图片,可以手动修改android/app/src/main/AndroidManifest.xml的Main Activity:
<activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <!-- 接收单张图片分享 --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="image/*"/> </intent-filter> <!-- 接收多张图片分享 --> <intent-filter> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="image/*"/> </intent-filter> </activity>
Android 13及以上需添加读取媒体权限:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
- iOS:在
ios/Runner/Info.plist中添加图片支持配置,让系统识别你的App可接收图片:
<key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>Image</string> <key>LSHandlerRank</key> <string>Alternate</string> <key>LSItemContentTypes</key> <array> <string>public.image</string> </array> </dict> </array>
二、自定义实现(不依赖第三方插件)
如果你不想用第三方插件,可以通过MethodChannel实现原生与Flutter的通信,手动处理Intent/分享数据。
Android端步骤
- 按上面的方式在
AndroidManifest.xml中添加intent-filter。 - 在
MainActivity.kt中获取Intent数据并传递给Flutter:
import android.content.Intent import android.net.Uri import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "com.your.app/intent" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "getSharedImage") { val imageUri = intent?.getParcelableExtra<Uri>(Intent.EXTRA_STREAM) result.success(imageUri?.path) } } } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) this.intent = intent // 通知Flutter后台收到新分享 MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CHANNEL) .invokeMethod("onNewSharedImage", intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)?.path) } }
iOS端步骤
- 按上面的方式在
Info.plist中添加图片支持配置。 - 在
AppDelegate.swift中处理分享URL并传递给Flutter:
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let CHANNEL = "com.your.app/intent" override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler { (call, result) in if call.method == "getSharedImage" { if let url = launchOptions?[.url] as? URL { result.success(url.path) } else { result.success(nil) } } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) channel.invokeMethod("onNewSharedImage", arguments: url.path) return true } }
Flutter端处理
通过MethodChannel监听原生传来的数据:
import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'dart:io'; class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const platform = MethodChannel('com.your.app/intent'); String? _imagePath; @override void initState() { super.initState(); // 获取启动时的分享数据 _getInitialImage(); // 监听新的分享数据 platform.setMethodCallHandler((call) async { if (call.method == "onNewSharedImage") { setState(() { _imagePath = call.arguments as String; }); if (_imagePath != null) { uploadImage(File(_imagePath!)); } } }); } Future<void> _getInitialImage() async { try { final String? path = await platform.invokeMethod('getSharedImage'); setState(() { _imagePath = path; }); if (_imagePath != null) { uploadImage(File(_imagePath!)); } } on PlatformException catch (e) { print("获取初始图片失败: ${e.message}"); } } Future<void> uploadImage(File imageFile) async { // 和快速方案的上传逻辑一致 var request = http.MultipartRequest( 'POST', Uri.parse('https://your-upload-api-url.com/upload'), ); request.files.add(await http.MultipartFile.fromPath('image', imageFile.path)); var response = await request.send(); if (response.statusCode == 200) { print('图片上传成功'); } else { print('图片上传失败:${response.statusCode}'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('自定义接收分享')), body: _imagePath == null ? const Text('等待其他App分享图片...') : Image.file(File(_imagePath!)), ); } }
注意事项
- Android端:如果分享的图片在外部存储,需要动态申请读取权限(Android 13+用
READ_MEDIA_IMAGES,低版本用READ_EXTERNAL_STORAGE)。 - iOS端:若需访问照片库,需在
Info.plist中添加隐私声明:
<key>NSPhotoLibraryUsageDescription</key> <string>需要访问照片库以接收分享的图片</string>
- 测试时,打开系统相册选一张图片点击分享,找到你的Flutter应用就能触发流程啦!
内容的提问来源于stack exchange,提问作者noam aghai




