如何为Flutter应用注册以打开iOS端Zip文件(附Android需求)
Flutter 实现「用...打开」Zip 文件(iOS/Android 极简示例)
iOS 实现步骤
1. 核对 Info.plist 配置(你已完成,仅做校验)
确保 Info.plist 中已注册 Zip 文件类型,示例配置如下:
<key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>Zip Archive</string> <key>CFBundleTypeRole</key> <string>Viewer</string> <key>LSHandlerRank</key> <string>Alternate</string> <key>LSItemContentTypes</key> <array> <string>public.zip</string> </array> </dict> </array>
2. 原生端传递文件路径到 Flutter
修改 ios/Runner/AppDelegate.swift,通过 MethodChannel 将打开的 Zip 文件路径传给 Flutter:
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let channel = FlutterMethodChannel(name: "com.example.zip_handler", binaryMessenger: UIApplication.shared.delegate as! FlutterBinaryMessenger) override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 处理应用未启动时,通过「用...打开」启动的场景 override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { channel.invokeMethod("handleZipFile", arguments: url.path) return true } // 处理应用后台运行时,通过「用...打开」唤醒的场景 override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { if let url = userActivity.webpageURL { channel.invokeMethod("handleZipFile", arguments: url.path) } return true } }
3. Flutter 端接收并处理 Zip 文件
在 main.dart 中监听 MethodChannel 接收路径,执行自定义逻辑:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'dart:io'; import 'package:archive/archive.dart'; // 需在pubspec.yaml添加archive依赖 void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { static const platform = MethodChannel('com.example.zip_handler'); String? _zipFilePath; @override void initState() { super.initState(); platform.setMethodCallHandler((call) async { if (call.method == 'handleZipFile') { setState(() { _zipFilePath = call.arguments as String; }); // 执行自定义处理逻辑 await _processZipFile(_zipFilePath!); } }); } Future<void> _processZipFile(String path) async { print('接收到Zip文件:$path'); // 示例:解压Zip到临时目录 final bytes = File(path).readAsBytesSync(); final archive = ZipDecoder().decodeBytes(bytes); for (final file in archive.files) { if (!file.isFile) continue; final targetFile = File('${Directory.systemTemp.path}/${file.name}'); targetFile.createSync(recursive: true); targetFile.writeAsBytesSync(file.content as List<int>); print('已解压文件:${targetFile.path}'); } } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Zip 文件处理示例')), body: Center( child: _zipFilePath != null ? Text('正在处理:$_zipFilePath') : const Text('等待打开 Zip 文件'), ), ), ); } }
Android 实现步骤
1. 配置 AndroidManifest.xml
在 android/app/src/main/AndroidManifest.xml 的 <activity> 标签内添加 intent-filter,注册支持 Zip 文件:
<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:mimeType="application/zip" /> <data android:pathPattern=".*\\.zip" /> <data android:host="*" /> </intent-filter>
2. 原生端传递文件路径到 Flutter
修改 android/app/src/main/kotlin/com/example/your_app/MainActivity.kt,处理 Intent 并传递路径:
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.example.zip_handler" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> // 暂无需处理Flutter调用原生逻辑 } } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleIntent(intent) } override fun onCreate(savedInstanceState: android.os.Bundle?) { super.onCreate(savedInstanceState) handleIntent(intent) } private fun handleIntent(intent: Intent) { val action = intent.action val type = intent.type if (Intent.ACTION_VIEW == action && type != null && type.startsWith("application/zip")) { val uri: Uri? = intent.data uri?.let { val path = getRealPathFromURI(it) val channel = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CHANNEL) channel.invokeMethod("handleZipFile", path) } } } // 将Uri转换为真实文件路径(适配Android 10+) private fun getRealPathFromURI(uri: Uri): String? { val projection = arrayOf(android.provider.MediaStore.Files.FileColumns.DATA) contentResolver.query(uri, projection, null, null, null)?.use { cursor -> val columnIndex = cursor.getColumnIndexOrThrow(android.provider.MediaStore.Files.FileColumns.DATA) cursor.moveToFirst() return cursor.getString(columnIndex) } return uri.path } }
3. Flutter 端逻辑复用
Android 端无需修改 Flutter 代码,直接复用 iOS 端的 main.dart 即可,handleZipFile 方法会自动接收路径并执行自定义逻辑。
内容的提问来源于stack exchange,提问作者Xunkai
相关产品推荐
相关产品推荐

