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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:50:41