├── ios
├── Assets
│ └── .gitkeep
├── Classes
│ ├── FlutterArchivePlugin.swift
│ └── SwiftFlutterArchivePlugin.swift
├── .gitignore
└── flutter_archive.podspec
├── test
└── flutter_archive_test.dart
├── android
├── settings.gradle
├── gradle.properties
├── .gitignore
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ └── com
│ │ └── kineapps
│ │ └── flutterarchive
│ │ └── FlutterArchivePlugin.kt
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── build.gradle
├── example
├── ios
│ ├── Runner
│ │ ├── Runner-Bridging-Header.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ ├── Flutter
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ ├── Flutter.podspec
│ │ └── AppFrameworkInfo.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ └── project.pbxproj
│ └── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── android
│ ├── gradle.properties
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── kineapps
│ │ │ │ │ │ └── flutter_archive_example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── settings.gradle
│ └── build.gradle
├── macos
│ ├── Runner
│ │ ├── Configs
│ │ │ ├── Debug.xcconfig
│ │ │ ├── Release.xcconfig
│ │ │ ├── Warnings.xcconfig
│ │ │ └── AppInfo.xcconfig
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── app_icon_16.png
│ │ │ │ ├── app_icon_32.png
│ │ │ │ ├── app_icon_64.png
│ │ │ │ ├── app_icon_1024.png
│ │ │ │ ├── app_icon_128.png
│ │ │ │ ├── app_icon_256.png
│ │ │ │ ├── app_icon_512.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Release.entitlements
│ │ ├── DebugProfile.entitlements
│ │ ├── MainFlutterWindow.swift
│ │ ├── Info.plist
│ │ └── Base.lproj
│ │ │ └── MainMenu.xib
│ ├── .gitignore
│ ├── Flutter
│ │ ├── Flutter-Debug.xcconfig
│ │ ├── Flutter-Release.xcconfig
│ │ └── GeneratedPluginRegistrant.swift
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ │ └── project.pbxproj
├── .metadata
├── test
│ └── widget_test.dart
├── README.md
├── .gitignore
├── pubspec.yaml
└── lib
│ └── main.dart
├── .gitattributes
├── macos
├── Classes
│ ├── SwiftFlutterArchivePlugin.swift
│ └── FlutterArchivePlugin.swift
└── flutter_archive.podspec
├── .metadata
├── LICENSE_THIRD_PARTY
├── .gitignore
├── LICENSE
├── pubspec.yaml
├── README.md
├── CHANGELOG.md
└── lib
└── flutter_archive.dart
/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/flutter_archive_test.dart:
--------------------------------------------------------------------------------
1 | void main() {}
2 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'flutter_archive'
2 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/macos/Classes/SwiftFlutterArchivePlugin.swift:
--------------------------------------------------------------------------------
1 | ../../ios/Classes/SwiftFlutterArchivePlugin.swift
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | android.enableJetifier=true
2 | android.useAndroidX=true
3 | org.gradle.jvmargs=-Xmx1536M
4 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/xcuserdata/
7 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kineapps/flutter_archive/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/kineapps/flutter_archive_example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.kineapps.flutter_archive_example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
6 |
--------------------------------------------------------------------------------
/ios/Classes/FlutterArchivePlugin.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 |
3 | public class FlutterArchivePlugin: NSObject, FlutterPlugin {
4 | public static func register(with registrar: FlutterPluginRegistrar) {
5 | SwiftFlutterArchivePlugin.register(with: registrar);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/example/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/macos/Classes/FlutterArchivePlugin.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | public class FlutterArchivePlugin: NSObject, FlutterPlugin {
5 | public static func register(with registrar: FlutterPluginRegistrar) {
6 | SwiftFlutterArchivePlugin.register(with: registrar);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
7 |
--------------------------------------------------------------------------------
/example/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 68587a0916366e9512a78df22c44163d041dd5f3
8 | channel: stable
9 |
10 | project_type: plugin
11 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 0b8abb4724aa590dd0f429683339b1e045a1594d
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/example/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import flutter_archive
9 |
10 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
11 | FlutterArchivePlugin.register(with: registry.registrar(forPlugin: "FlutterArchivePlugin"))
12 | }
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController.init()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter_test/flutter_test.dart';
9 |
10 | void main() {
11 | testWidgets('Verify Platform version', (WidgetTester tester) async {});
12 | }
13 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 | /Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # flutter_archive_example
2 |
3 | Demonstrates how to use the flutter_archive plugin.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = flutter_archive_example
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.kineapps.flutterArchiveExample
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2020 com.kineapps. All rights reserved.
15 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '2.1.0'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:8.7.3'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | tasks.register("clean", Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # This podspec is NOT to be published. It is only used as a local source!
3 | # This is a generated file; do not edit or check into version control.
4 | #
5 |
6 | Pod::Spec.new do |s|
7 | s.name = 'Flutter'
8 | s.version = '1.0.0'
9 | s.summary = 'A UI toolkit for beautiful and fast apps.'
10 | s.homepage = 'https://flutter.dev'
11 | s.license = { :type => 'BSD' }
12 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
13 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
14 | s.ios.deployment_target = '12.0'
15 | # Framework linking is handled by Flutter tooling, not CocoaPods.
16 | # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs.
17 | s.vendored_frameworks = 'path/to/nothing'
18 | end
19 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/macos/flutter_archive.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint flutter_archive.podspec' to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'flutter_archive'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'FlutterMacOS'
18 | s.dependency 'ZIPFoundation', '0.9.19'
19 |
20 | s.platform = :osx, '10.11'
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
22 | s.swift_version = '5.0'
23 | end
24 |
--------------------------------------------------------------------------------
/ios/flutter_archive.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint flutter_archive.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'flutter_archive'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.public_header_files = 'Classes/**/*.h'
18 | s.dependency 'Flutter'
19 | s.dependency 'ZIPFoundation', '0.9.19'
20 |
21 | s.platform = :ios, '12.0'
22 | s.ios.deployment_target = '12.0'
23 |
24 | # Flutter.framework does not contain a i386 slice.
25 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
26 | s.swift_version = '5.0'
27 | end
28 |
--------------------------------------------------------------------------------
/LICENSE_THIRD_PARTY:
--------------------------------------------------------------------------------
1 | https://github.com/weichsel/ZIPFoundation
2 |
3 | MIT License
4 |
5 | Copyright (c) 2017 Thomas Zoechling
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
--------------------------------------------------------------------------------
/example/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # https://www.dartlang.org/guides/libraries/private-files
2 |
3 | # Files and directories created by pub
4 | .dart_tool/
5 | .packages
6 | .pub/
7 | build/
8 | pubspec.lock
9 |
10 | # Directory created by dartdoc
11 | /doc/api/
12 |
13 | # IDE
14 | *.iml // IntelliJ
15 | *.ipr // IntelliJ
16 | *.iws // IntelliJ
17 | .idea/ // IntelliJ
18 | .DS_Store // Mac
19 |
20 | # copied from https://github.com/flutter/plugins/blob/master/.gitignore
21 | .DS_Store
22 | .atom/
23 | .idea/
24 | .vscode/
25 |
26 | .packages
27 | .pub/
28 | .dart_tool/
29 | pubspec.lock
30 | flutter_export_environment.sh
31 |
32 | examples/all_plugins/pubspec.yaml
33 |
34 | Podfile
35 | Podfile.lock
36 | Pods/
37 | .symlinks/
38 | **/Flutter/App.framework/
39 | **/Flutter/Flutter.framework/
40 | **/Flutter/Generated.xcconfig
41 | **/Flutter/flutter_assets/
42 | ServiceDefinitions.json
43 | xcuserdata/
44 | **/DerivedData/
45 |
46 | local.properties
47 | keystore.properties
48 | .gradle/
49 | gradlew
50 | gradlew.bat
51 | gradle-wrapper.jar
52 | .flutter-plugins-dependencies
53 | *.iml
54 | **/ios/Flutter/ephemeral/
55 |
56 | GeneratedPluginRegistrant.h
57 | GeneratedPluginRegistrant.m
58 | GeneratedPluginRegistrant.java
59 | build/
60 | .flutter-plugins
61 |
62 | .project
63 | .classpath
64 | .settings
65 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2020 KineApps. All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are
7 | met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 | * Redistributions in binary form must reproduce the above
12 | copyright notice, this list of conditions and the following
13 | disclaimer in the documentation and/or other materials provided
14 | with the distribution.
15 | * Neither the name of copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived
17 | from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'com.kineapps.flutterarchive'
2 | version '1.0-SNAPSHOT'
3 |
4 | buildscript {
5 | ext.kotlin_version = '2.1.0'
6 | ext.coroutinesVersion = "1.7.3"
7 | repositories {
8 | google()
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:8.7.3'
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15 | }
16 | }
17 |
18 | rootProject.allprojects {
19 | repositories {
20 | google()
21 | mavenCentral()
22 | }
23 | }
24 |
25 | apply plugin: 'com.android.library'
26 | apply plugin: 'kotlin-android'
27 |
28 | android {
29 | // Conditional for compatibility with AGP <4.2.
30 | if (project.android.hasProperty("namespace")) {
31 | namespace 'com.kineapps.flutterarchive'
32 | }
33 |
34 | compileSdkVersion 36
35 |
36 | compileOptions {
37 | sourceCompatibility JavaVersion.VERSION_17
38 | targetCompatibility JavaVersion.VERSION_17
39 | }
40 |
41 | kotlinOptions {
42 | jvmTarget = JavaVersion.VERSION_17.toString()
43 | }
44 |
45 | sourceSets {
46 | main.java.srcDirs += 'src/main/kotlin'
47 | }
48 | defaultConfig {
49 | minSdkVersion 19
50 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
51 | }
52 | lintOptions {
53 | disable 'InvalidPackage'
54 | }
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
59 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
60 | }
61 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | .vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | /build/
31 |
32 | # Android related
33 | **/android/**/gradle-wrapper.jar
34 | **/android/.gradle
35 | **/android/captures/
36 | **/android/gradlew
37 | **/android/gradlew.bat
38 | **/android/local.properties
39 | **/android/**/GeneratedPluginRegistrant.java
40 |
41 | # iOS/XCode related
42 | **/ios/**/*.mode1v3
43 | **/ios/**/*.mode2v3
44 | **/ios/**/*.moved-aside
45 | **/ios/**/*.pbxuser
46 | **/ios/**/*.perspectivev3
47 | **/ios/**/*sync/
48 | **/ios/**/.sconsign.dblite
49 | **/ios/**/.tags*
50 | **/ios/**/.vagrant/
51 | **/ios/**/DerivedData/
52 | **/ios/**/Icon?
53 | **/ios/**/Pods/
54 | **/ios/**/.symlinks/
55 | **/ios/**/profile
56 | **/ios/**/xcuserdata
57 | **/ios/.generated/
58 | **/ios/Flutter/App.framework
59 | **/ios/Flutter/Flutter.framework
60 | **/ios/Flutter/Generated.xcconfig
61 | **/ios/Flutter/app.flx
62 | **/ios/Flutter/app.zip
63 | **/ios/Flutter/flutter_assets/
64 | **/ios/Flutter/flutter_export_environment.sh
65 | **/ios/ServiceDefinitions.json
66 | **/ios/Runner/GeneratedPluginRegistrant.*
67 |
68 | # Exceptions to above rules.
69 | !**/ios/**/default.mode1v3
70 | !**/ios/**/default.mode2v3
71 | !**/ios/**/default.pbxuser
72 | !**/ios/**/default.perspectivev3
73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
74 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | flutter_archive_example
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_archive_example
2 | description: Demonstrates how to use the flutter_archive plugin.
3 | version: 0.0.1+1
4 | publish_to: "none"
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | # The following adds the Cupertino Icons font to your application.
14 | # Use with the CupertinoIcons class for iOS style icons.
15 | cupertino_icons: ^1.0.2
16 |
17 | dev_dependencies:
18 | flutter_test:
19 | sdk: flutter
20 |
21 | flutter_archive:
22 | path: ../
23 |
24 | # For information on the generic Dart part of this file, see the
25 | # following page: https://dart.dev/tools/pub/pubspec
26 |
27 | # The following section is specific to Flutter.
28 | flutter:
29 | # The following line ensures that the Material Icons font is
30 | # included with your application, so that you can use the icons in
31 | # the material Icons class.
32 | uses-material-design: true
33 | # To add assets to your application, add an assets section, like this:
34 | # assets:
35 | # - images/a_dot_burr.jpeg
36 | # - images/a_dot_ham.jpeg
37 | # An image asset can refer to one or more resolution-specific "variants", see
38 | # https://flutter.dev/assets-and-images/#resolution-aware.
39 | # For details regarding adding assets from package dependencies, see
40 | # https://flutter.dev/assets-and-images/#from-packages
41 | # To add custom fonts to your application, add a fonts section here,
42 | # in this "flutter" section. Each entry in this list should have a
43 | # "family" key with the font family name, and a "fonts" key with a
44 | # list giving the asset and other descriptors for the font. For
45 | # example:
46 | # fonts:
47 | # - family: Schyler
48 | # fonts:
49 | # - asset: fonts/Schyler-Regular.ttf
50 | # - asset: fonts/Schyler-Italic.ttf
51 | # style: italic
52 | # - family: Trajan Pro
53 | # fonts:
54 | # - asset: fonts/TrajanPro.ttf
55 | # - asset: fonts/TrajanPro_Bold.ttf
56 | # weight: 700
57 | #
58 | # For details regarding fonts from package dependencies,
59 | # see https://flutter.dev/custom-fonts/#from-packages
60 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_archive
2 | description: Create and extract ZIP archive files in Android, iOS and macOS. Zip all files in a directory recursively or a given list of files.
3 | version: 6.0.4
4 | homepage: https://github.com/kineapps/flutter_archive
5 | repository: https://github.com/kineapps/flutter_archive
6 |
7 | environment:
8 | sdk: '>=2.15.0 <4.0.0'
9 | flutter: ">=2.8.0"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 |
19 | # For information on the generic Dart part of this file, see the
20 | # following page: https://dart.dev/tools/pub/pubspec
21 |
22 | # The following section is specific to Flutter.
23 | flutter:
24 | # This section identifies this Flutter project as a plugin project.
25 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily
26 | # be modified. They are used by the tooling to maintain consistency when
27 | # adding or updating assets for this project.
28 | plugin:
29 | platforms:
30 | android:
31 | package: com.kineapps.flutterarchive
32 | pluginClass: FlutterArchivePlugin
33 | ios:
34 | pluginClass: FlutterArchivePlugin
35 | macos:
36 | pluginClass: FlutterArchivePlugin
37 | # To add assets to your plugin package, add an assets section, like this:
38 | # assets:
39 | # - images/a_dot_burr.jpeg
40 | # - images/a_dot_ham.jpeg
41 | #
42 | # For details regarding assets in packages, see
43 | # https://flutter.dev/assets-and-images/#from-packages
44 | #
45 | # An image asset can refer to one or more resolution-specific "variants", see
46 | # https://flutter.dev/assets-and-images/#resolution-aware.
47 | # To add custom fonts to your plugin package, add a fonts section here,
48 | # in this "flutter" section. Each entry in this list should have a
49 | # "family" key with the font family name, and a "fonts" key with a
50 | # list giving the asset and other descriptors for the font. For
51 | # example:
52 | # fonts:
53 | # - family: Schyler
54 | # fonts:
55 | # - asset: fonts/Schyler-Regular.ttf
56 | # - asset: fonts/Schyler-Italic.ttf
57 | # style: italic
58 | # - family: Trajan Pro
59 | # fonts:
60 | # - asset: fonts/TrajanPro.ttf
61 | # - asset: fonts/TrajanPro_Bold.ttf
62 | # weight: 700
63 | #
64 | # For details regarding fonts in packages, see
65 | # https://flutter.dev/custom-fonts/#from-packages
66 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | namespace 'com.kineapps.flutter_archive_example'
30 |
31 | compileSdkVersion 36
32 |
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_17
35 | targetCompatibility JavaVersion.VERSION_17
36 | }
37 |
38 | kotlinOptions {
39 | jvmTarget = JavaVersion.VERSION_17.toString()
40 | }
41 |
42 | sourceSets {
43 | main.java.srcDirs += 'src/main/kotlin'
44 | }
45 |
46 | lintOptions {
47 | disable 'InvalidPackage'
48 | }
49 |
50 | defaultConfig {
51 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
52 | applicationId "com.kineapps.flutter_archive_example"
53 | minSdkVersion 19
54 | targetSdkVersion 31
55 | versionCode flutterVersionCode.toInteger()
56 | versionName flutterVersionName
57 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
58 | }
59 |
60 | buildTypes {
61 | release {
62 | // TODO: Add your own signing config for the release build.
63 | // Signing with the debug keys for now, so `flutter run --release` works.
64 | signingConfig signingConfigs.debug
65 | }
66 | }
67 | }
68 |
69 | flutter {
70 | source '../..'
71 | }
72 |
73 | dependencies {
74 | testImplementation 'junit:junit:4.12'
75 | androidTestImplementation 'androidx.test:runner:1.1.1'
76 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
77 | }
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flutter_archive
2 |
3 | Create and extract ZIP archive files. Uses Android/iOS/macOS platform APIs for high performance and optimal memory usage.
4 |
5 | ## Features
6 |
7 | - Supports Android (API level 16+), iOS 12+ and macOS 10.11+.
8 | - Modern plugin implementation based on Kotlin (Android) and Swift (iOS/macOS).
9 | - Uses background processing to keep UI responsive.
10 | - Zip all files in a directory (optionally recursively).
11 | - Zip a given list of files.
12 | - Unzip an archive file to a given directory.
13 | - Progress reporting.
14 | - Extract and zip files selectively (allows excluding files).
15 |
16 | ## Examples
17 |
18 | ### Create a zip file from a directory
19 |
20 | ```dart
21 | final dataDir = Directory("data_dir_path");
22 | try {
23 | final zipFile = File("zip_file_path");
24 | ZipFile.createFromDirectory(
25 | sourceDir: dataDir, zipFile: zipFile, recurseSubDirs: true);
26 | } catch (e) {
27 | print(e);
28 | }
29 | ```
30 |
31 | ### Create a zip file from a given list of files.
32 |
33 | ```dart
34 | final sourceDir = Directory("source_dir");
35 | final files = [
36 | File(sourceDir.path + "file1"),
37 | File(sourceDir.path + "file2")
38 | ];
39 | final zipFile = File("zip_file_path");
40 | try {
41 | ZipFile.createFromFiles(
42 | sourceDir: sourceDir, files: files, zipFile: zipFile);
43 | } catch (e) {
44 | print(e);
45 | }
46 | ```
47 |
48 | ### Extract a ZIP archive
49 |
50 | ```dart
51 | final zipFile = File("zip_file_path");
52 | final destinationDir = Directory("destination_dir_path");
53 | try {
54 | ZipFile.extractToDirectory(zipFile: zipFile, destinationDir: destinationDir);
55 | } catch (e) {
56 | print(e);
57 | }
58 | ```
59 |
60 | ### Get progress info while extracting a zip archive.
61 |
62 | ```dart
63 | final zipFile = File("zip_file_path");
64 | final destinationDir = Directory("destination_dir_path");
65 | try {
66 | await ZipFile.extractToDirectory(
67 | zipFile: zipFile,
68 | destinationDir: destinationDir,
69 | onExtracting: (zipEntry, progress) {
70 | print('progress: ${progress.toStringAsFixed(1)}%');
71 | print('name: ${zipEntry.name}');
72 | print('isDirectory: ${zipEntry.isDirectory}');
73 | print(
74 | 'modificationDate: ${zipEntry.modificationDate.toLocal().toIso8601String()}');
75 | print('uncompressedSize: ${zipEntry.uncompressedSize}');
76 | print('compressedSize: ${zipEntry.compressedSize}');
77 | print('compressionMethod: ${zipEntry.compressionMethod}');
78 | print('crc: ${zipEntry.crc}');
79 | return ZipFileOperation.includeItem;
80 | });
81 | } catch (e) {
82 | print(e);
83 | }
84 | ```
85 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 6.0.4
2 | - [Android] Updated compileSdkVersion to 36, Gradle to 8.14 and Java/Kotlin compatibility to version 17
3 |
4 | ## 6.0.3
5 | - [iOS] Fixed build issue #78
6 |
7 | ## 6.0.2
8 | - [iOS] Upgraded to ZIPFoundation 0.9.19
9 |
10 | ## 6.0.1
11 | - [iOS] Upgraded to ZIPFoundation 0.9.18 (thanks to AliakseiT)
12 |
13 | ## 6.0.0
14 | - [Andfroid] Fix AGP 8.0 compile error
15 | - [Andfroid] Updated gradle version 7.3.1 and Kotlin version 1.7.10
16 | - [Andfroid] Set compileSdkVersion to 33
17 |
18 | ## 5.0.0
19 |
20 | - [iOS] BRAKING CHANGE: minimum iOS version is now iOS 12.0
21 | - [iOS] Upgraded to ZIPFoundation 0.9.13 (thanks to daniel-possienke)
22 |
23 | ## 4.2.2
24 |
25 | - [iOS] fixed: progress never 100% (thanks to Lan-tb)
26 | - [iOS] added charset support (thanks to Lan-tb)
27 |
28 | ## 4.2.1
29 |
30 | - [Android] Fixed build issue related to Result.error
31 | - fixed sdk constraints
32 |
33 | ## 4.2.0
34 |
35 | - [Android] Fixed #25: added parameter zipFileCharset to ZipFile.extractToDirectory for defining the charset to use
36 |
37 | ## 4.1.1
38 |
39 | - Fixed #43
40 |
41 | ## 4.1.0
42 |
43 | - fixed: skipping file in ZipFile.extractToDirectory did not work
44 | - [Android] updated to Kotlin 1.5.30
45 | - [Android] upgraded gradle
46 | - [Android] jcenter => mavenCentral
47 | - [Android] set compileSdkVersion to 31
48 | - [Android] Removed V1 embedding
49 | - [Android] Fixed warning "inappropriate blocking method call"
50 | - [iOS] updated podspec (added s.swift_version etc.)
51 |
52 | ## 4.0.1
53 |
54 | [iOS] ZipFile.createFromDirectory: fixed issues with file paths
55 |
56 | ## 4.0.0
57 |
58 | - ZipFile.createFromDirectory: added a new parameter onZipping for progress reporting and to allow filtering files to be included in the zip (#30)
59 | - BREAKING CHANGE: replaced enum ExtractOperation with ZipFileOperation
60 | - [iOS] fixed: recurseSubDirs parameter in ZipFile.createFromDirectory was ignored
61 | - [Android] Updated compileSdkVersion and targetSdkVersion to 30
62 |
63 | ## 3.0.0
64 |
65 | - null safety
66 |
67 | ## 2.0.2
68 |
69 | - Fixed minor lint issues
70 | - Experimental fix to #26 (publish plugin from Mac)
71 |
72 | ## 2.0.1
73 |
74 | - Added support for iOS 9
75 |
76 | ## 2.0.0
77 |
78 | - Added support for macOS (thanks for the PR to [tonycn](https://github.com/tonycn))
79 |
80 | ## 1.0.3
81 |
82 | - Fixed #13: Extracting multiple zip files in parallel does not work when using onExtracting callback
83 |
84 | ## 1.0.2
85 |
86 | - [Android] Fixed: java.lang.ClassCastException: java.util.zip.ZipFile
87 | cannot be cast to java.io.Closeable occurring if API level < 19
88 |
89 | ## 1.0.1
90 |
91 | - Fixed "MissingPluginException"
92 |
93 | ## 1.0.0
94 |
95 | - Renamed FlutterArchive as ZipFile, renamed also methods
96 | - Support for progress reporting in unzip (ZipFile.extractToDirectory)
97 | - Added support for including base directory name to file paths
98 | - [iOS] Upgraded to ZIPFoundation 0.9.11
99 |
100 | ## 0.1.4
101 |
102 | - [Android] Fixed: unzipping some files could fail to "java.util.zip.ZipException: invalid stored block lengths"
103 | - [Android] Fixed: any thrown exception during zip/unzip caused crash
104 |
105 | ## 0.1.3
106 |
107 | - [Android] Improved error handling.
108 |
109 | ## 0.1.2
110 |
111 | - [iOS] Zip/unzip files in a background thread to keep UI more responsive.
112 |
113 | ## 0.1.1+1
114 |
115 | - Minor cleanup.
116 |
117 | ## 0.1.1
118 |
119 | - Added support for Android V2 embedding.
120 |
121 | ## 0.1.0
122 |
123 | - Updated public API.
124 | - Improved documentation.
125 | - Added code samples.
126 |
127 | ## 0.0.2
128 |
129 | - Documented public APIs and updated README.md.
130 |
131 | ## 0.0.1
132 |
133 | - Initial release.
134 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/lib/flutter_archive.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020 KineApps. All rights reserved.
2 | //
3 | // This source code is licensed under the BSD-style license found in the
4 | // LICENSE file in the root directory of this source tree.
5 |
6 | import 'dart:async';
7 | import 'dart:io';
8 |
9 | import 'package:flutter/services.dart';
10 |
11 | enum ZipFileOperation { includeItem, skipItem, cancel }
12 |
13 | typedef OnExtracting = ZipFileOperation Function(
14 | ZipEntry zipEntry, double progress);
15 |
16 | typedef OnZipping = ZipFileOperation Function(
17 | String filePath, bool isDirectory, double progress);
18 |
19 | /// Charsets for [ZipFile.extractToDirectory].
20 | /// https://developer.android.com/reference/java/nio/charset/StandardCharsets
21 | enum Charsets {
22 | // ISO Latin Alphabet No.
23 | ISO_8859_1,
24 |
25 | // Seven-bit ASCII, a.k.a.
26 | US_ASCII,
27 |
28 | // Sixteen-bit UCS Transformation Format, byte order identified by an
29 | // optional byte-order mark
30 | UTF_16,
31 |
32 | // Sixteen-bit UCS Transformation Format, big-endian byte order
33 | UTF_16BE,
34 |
35 | // Sixteen-bit UCS Transformation Format, little-endian byte order
36 | UTF_16LE,
37 |
38 | // Eight-bit UCS Transformation Format
39 | UTF_8,
40 |
41 | // https://en.wikipedia.org/wiki/Code_page_437
42 | CP437,
43 | }
44 |
45 | /// Utility class for creating and extracting zip archive files.
46 | class ZipFile {
47 | static const MethodChannel _channel = MethodChannel('flutter_archive');
48 |
49 | /// Compress and save all files in [sourceDir] to [zipFile].
50 | ///
51 | /// Set [includeBaseDirectory] to true to include the directory name from
52 | /// [sourceDir] at the root of the archive. Set [includeBaseDirectory] to
53 | /// false to include only the contents of the [sourceDir].
54 | ///
55 | /// By default zip all subdirectories recursively. Set [recurseSubDirs]
56 | /// to false to disable recursive zipping.
57 | ///
58 | /// Optional callback function [onZipping] is called before zipping a file
59 | /// or a directory. [onZipping] must return one of the following values:
60 | /// [ZipFileOperation.includeItem] - include this file/directory in zip
61 | /// [ZipFileOperation.skipItem] - exclude this file or directory from the zip
62 | /// [ZipFileOperation.cancel] - cancel the operation
63 | static Future createFromDirectory(
64 | {required Directory sourceDir,
65 | required File zipFile,
66 | bool includeBaseDirectory = false,
67 | bool recurseSubDirs = true,
68 | OnZipping? onZipping}) async {
69 | final reportProgress = onZipping != null;
70 | if (reportProgress) {
71 | if (!_isMethodCallHandlerSet) {
72 | _channel.setMethodCallHandler(_channelMethodCallHandler);
73 | _isMethodCallHandlerSet = true;
74 | }
75 | }
76 | final jobId = ++_jobId;
77 | try {
78 | if (onZipping != null) {
79 | _onZippingHandlerByJobId[jobId] = onZipping;
80 | }
81 |
82 | await _channel.invokeMethod('zipDirectory', {
83 | 'sourceDir': sourceDir.path,
84 | 'zipFile': zipFile.path,
85 | 'recurseSubDirs': recurseSubDirs,
86 | 'includeBaseDirectory': includeBaseDirectory,
87 | 'reportProgress': reportProgress,
88 | 'jobId': jobId,
89 | });
90 | } finally {
91 | _onZippingHandlerByJobId.remove(jobId);
92 | }
93 | }
94 |
95 | /// Compress given list of [files] and save the resulted archive to [zipFile].
96 | /// [sourceDir] is the root directory of [files] (all [files] must reside
97 | /// under the [sourceDir]).
98 | ///
99 | /// Set [includeBaseDirectory] to true to include the directory name from
100 | /// [sourceDir] at the root of the archive. Set [includeBaseDirectory] to
101 | /// false to include only the contents of the [sourceDir].
102 | static Future createFromFiles({
103 | required Directory sourceDir,
104 | required List files,
105 | required File zipFile,
106 | bool includeBaseDirectory = false,
107 | }) async {
108 | var sourceDirPath =
109 | includeBaseDirectory ? sourceDir.parent.path : sourceDir.path;
110 | if (!sourceDirPath.endsWith(Platform.pathSeparator)) {
111 | sourceDirPath += Platform.pathSeparator;
112 | }
113 |
114 | final sourceDirPathLen = sourceDirPath.length;
115 |
116 | final relativeFilePaths = [];
117 | for (final f in files) {
118 | if (!f.path.startsWith(sourceDirPath)) {
119 | throw Exception('Files must reside under the rootDir');
120 | }
121 | final relativeFilePath = f.path.substring(sourceDirPathLen);
122 | assert(!relativeFilePath.startsWith(Platform.pathSeparator));
123 | relativeFilePaths.add(relativeFilePath);
124 | }
125 | await _channel.invokeMethod('zipFiles', {
126 | 'sourceDir': sourceDir.path,
127 | 'files': relativeFilePaths,
128 | 'zipFile': zipFile.path,
129 | 'includeBaseDirectory': includeBaseDirectory
130 | });
131 | }
132 |
133 | /// Extract [zipFile] to a given [destinationDir]. Optional callback function
134 | /// [onExtracting] is called before extracting a zip entry.
135 | ///
136 | /// [onExtracting] must return one of the following values:
137 | /// [ZipFileOperation.includeItem] - extract this file/directory
138 | /// [ZipFileOperation.skipItem] - do not extract this file/directory
139 | /// [ZipFileOperation.cancel] - cancel the operation
140 | ///
141 | /// In iOS and Android (API level >= 24) you can also specify the charset
142 | /// [zipFileCharset] to be used to decode the ZIP entry names and comments.
143 | /// The enum [Charsets] defines the most common values
144 | /// (use e.g. [Charsets.UTF_8.name]).
145 | /// More information: https://developer.android.com/reference/java/util/zip/ZipFile#ZipFile(java.lang.String,%20java.nio.charset.Charset)
146 | static Future extractToDirectory({
147 | required File zipFile,
148 | required Directory destinationDir,
149 | OnExtracting? onExtracting,
150 | String? zipFileCharset,
151 | }) async {
152 | final reportProgress = onExtracting != null;
153 | if (reportProgress) {
154 | if (!_isMethodCallHandlerSet) {
155 | _channel.setMethodCallHandler(_channelMethodCallHandler);
156 | _isMethodCallHandlerSet = true;
157 | }
158 | }
159 | final jobId = ++_jobId;
160 | try {
161 | if (onExtracting != null) {
162 | _onExtractingHandlerByJobId[jobId] = onExtracting;
163 | }
164 |
165 | await _channel.invokeMethod('unzip', {
166 | 'zipFile': zipFile.path,
167 | 'zipFileCharset': zipFileCharset,
168 | 'destinationDir': destinationDir.path,
169 | 'reportProgress': reportProgress,
170 | 'jobId': jobId,
171 | });
172 | } finally {
173 | _onExtractingHandlerByJobId.remove(jobId);
174 | }
175 | }
176 |
177 | static bool _isMethodCallHandlerSet = false;
178 | static int _jobId = 0;
179 | static final _onExtractingHandlerByJobId = {};
180 | static final _onZippingHandlerByJobId = {};
181 |
182 | static Future _channelMethodCallHandler(MethodCall call) {
183 | if (call.method == 'progress') {
184 | final args = Map.from(call.arguments as Map);
185 | final jobId = args["jobId"] as int? ?? 0;
186 | final zipEntry = ZipEntry.fromMap(args);
187 | final progress = args["progress"] as double? ?? 0;
188 | final onExtractHandler = _onExtractingHandlerByJobId[jobId];
189 | if (onExtractHandler != null) {
190 | final result = onExtractHandler(zipEntry, progress);
191 | return Future.value(result.name);
192 | } else {
193 | final onZippingHandler = _onZippingHandlerByJobId[jobId];
194 | if (onZippingHandler != null) {
195 | final result =
196 | onZippingHandler(zipEntry.name, zipEntry.isDirectory, progress);
197 | return Future.value(result.name);
198 | } else {
199 | return Future.value();
200 | }
201 | }
202 | }
203 | return Future.value();
204 | }
205 | }
206 |
207 | enum CompressionMethod { none, deflated }
208 |
209 | class ZipEntry {
210 | const ZipEntry({
211 | required this.name,
212 | required this.isDirectory,
213 | this.modificationDate,
214 | this.uncompressedSize,
215 | this.compressedSize,
216 | this.crc,
217 | this.compressionMethod,
218 | });
219 |
220 | factory ZipEntry.fromMap(Map map) {
221 | return ZipEntry(
222 | name: map['name'] as String? ?? '',
223 | isDirectory: (map['isDirectory'] as bool?) == true,
224 | modificationDate: DateTime.fromMillisecondsSinceEpoch(
225 | map['modificationDate'] as int? ?? 0),
226 | uncompressedSize: map['uncompressedSize'] as int?,
227 | compressedSize: map['compressedSize'] as int?,
228 | crc: map['crc'] as int?,
229 | compressionMethod: map['compressionMethod'] == 'none'
230 | ? CompressionMethod.none
231 | : CompressionMethod.deflated,
232 | );
233 | }
234 |
235 | final String name;
236 | final bool isDirectory;
237 | final DateTime? modificationDate;
238 | final int? uncompressedSize;
239 | final int? compressedSize;
240 | final int? crc;
241 | final CompressionMethod? compressionMethod;
242 | }
243 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'dart:async';
5 |
6 | import 'package:flutter/services.dart';
7 | import 'package:flutter_archive/flutter_archive.dart';
8 |
9 | void main() => runApp(MyApp());
10 |
11 | class MyApp extends StatefulWidget {
12 | @override
13 | _MyAppState createState() => _MyAppState();
14 | }
15 |
16 | class _MyAppState extends State {
17 | @override
18 | void initState() {
19 | super.initState();
20 | }
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return MaterialApp(
25 | home: Scaffold(
26 | appBar: AppBar(
27 | title: const Text('Plugin test app'),
28 | ),
29 | body: Center(
30 | child: ElevatedButton(
31 | onPressed: _test,
32 | child: const Text("Test"),
33 | ),
34 | ),
35 | ),
36 | );
37 | }
38 |
39 | final _appDataDir = Directory.systemTemp;
40 |
41 | static const _dataFilesBaseDirectoryName = "store";
42 | final _dataFiles = {
43 | "file1.txt": "abc",
44 | "file2.txt": "åäö",
45 | "subdir1/file3.txt": r"@_£$",
46 | "subdir1/subdir11/file4.txt": "123",
47 | };
48 |
49 | Future _test() async {
50 | print("Start test");
51 | // test createFromDirectory
52 | // case 1
53 | var zipFile = await _testZip(includeBaseDirectory: false, progress: true);
54 | await _testUnzip(zipFile, zipIncludesBaseDirectory: false);
55 | await _testUnzip(zipFile, progress: true);
56 | // case 2
57 | zipFile = await _testZip(includeBaseDirectory: true, progress: false);
58 | await _testUnzip(zipFile, zipIncludesBaseDirectory: true);
59 |
60 | // test createFromFiles
61 | // case 1
62 | zipFile = await _testZipFiles(includeBaseDirectory: false);
63 | await _testUnzip(zipFile, zipIncludesBaseDirectory: false);
64 | // case 2
65 | zipFile = await _testZipFiles(includeBaseDirectory: true);
66 | await _testUnzip(zipFile, zipIncludesBaseDirectory: true);
67 |
68 | print("DONE!");
69 | }
70 |
71 | Future _testZip(
72 | {required bool includeBaseDirectory, bool progress = false}) async {
73 | print("_appDataDir=${_appDataDir.path}");
74 | final storeDir =
75 | Directory("${_appDataDir.path}${"/$_dataFilesBaseDirectoryName"}");
76 |
77 | _createTestFiles(storeDir);
78 |
79 | final zipFile = _createZipFile("testZip.zip");
80 | print("Writing to zip file: ${zipFile.path}");
81 |
82 | int onProgressCallCount1 = 0;
83 |
84 | try {
85 | await ZipFile.createFromDirectory(
86 | sourceDir: storeDir,
87 | zipFile: zipFile,
88 | recurseSubDirs: true,
89 | includeBaseDirectory: includeBaseDirectory,
90 | onZipping: progress
91 | ? (fileName, isDirectory, progress) {
92 | ++onProgressCallCount1;
93 | print('Zip #1:');
94 | print('progress: ${progress.toStringAsFixed(1)}%');
95 | print('name: $fileName');
96 | print('isDirectory: $isDirectory');
97 | return ZipFileOperation.includeItem;
98 | }
99 | : null,
100 | );
101 | assert(!progress || onProgressCallCount1 > 0);
102 | } on PlatformException catch (e) {
103 | print(e);
104 | }
105 | return zipFile;
106 | }
107 |
108 | Future _testZipFiles({required bool includeBaseDirectory}) async {
109 | print("_appDataDir=${_appDataDir.path}");
110 | final storeDir =
111 | Directory("${_appDataDir.path}${"/$_dataFilesBaseDirectoryName"}");
112 |
113 | final testFiles = _createTestFiles(storeDir);
114 |
115 | final zipFile = _createZipFile("testZipFiles.zip");
116 | print("Writing files to zip file: ${zipFile.path}");
117 |
118 | try {
119 | await ZipFile.createFromFiles(
120 | sourceDir: storeDir,
121 | files: testFiles,
122 | zipFile: zipFile,
123 | includeBaseDirectory: includeBaseDirectory);
124 | } on PlatformException catch (e) {
125 | print(e);
126 | }
127 | return zipFile;
128 | }
129 |
130 | Future _testUnzip(File zipFile,
131 | {bool progress = false, bool zipIncludesBaseDirectory = false}) async {
132 | print("_appDataDir=${_appDataDir.path}");
133 |
134 | final destinationDir = Directory("${_appDataDir.path}/unzip");
135 | final destinationDir2 = Directory("${_appDataDir.path}/unzip2");
136 |
137 | if (destinationDir.existsSync()) {
138 | print("Deleting existing unzip directory: ${destinationDir.path}");
139 | destinationDir.deleteSync(recursive: true);
140 | }
141 | if (destinationDir2.existsSync()) {
142 | print("Deleting existing unzip directory: ${destinationDir2.path}");
143 | destinationDir2.deleteSync(recursive: true);
144 | }
145 |
146 | print("Extracting zip to directory: ${destinationDir.path}");
147 | destinationDir.createSync();
148 | // test concurrent extraction
149 | final extractFutures = [];
150 | int onExtractingCallCount1 = 0;
151 | int onExtractingCallCount2 = 0;
152 | try {
153 | extractFutures.add(ZipFile.extractToDirectory(
154 | zipFile: zipFile,
155 | destinationDir: destinationDir,
156 | onExtracting: progress
157 | ? (zipEntry, progress) {
158 | ++onExtractingCallCount1;
159 | print('Extract #1:');
160 | print('progress: ${progress.toStringAsFixed(1)}%');
161 | print('name: ${zipEntry.name}');
162 | print('isDirectory: ${zipEntry.isDirectory}');
163 | print(
164 | 'modificationDate: ${zipEntry.modificationDate!.toLocal().toIso8601String()}');
165 | print('uncompressedSize: ${zipEntry.uncompressedSize}');
166 | print('compressedSize: ${zipEntry.compressedSize}');
167 | print('compressionMethod: ${zipEntry.compressionMethod}');
168 | print('crc: ${zipEntry.crc}');
169 | return ZipFileOperation.includeItem;
170 | }
171 | : null));
172 |
173 | extractFutures.add(ZipFile.extractToDirectory(
174 | zipFile: zipFile,
175 | destinationDir: destinationDir2,
176 | onExtracting: progress
177 | ? (zipEntry, progress) {
178 | ++onExtractingCallCount2;
179 | print('Extract #2:');
180 | print('progress: ${progress.toStringAsFixed(1)}%');
181 | print('name: ${zipEntry.name}');
182 | print('isDirectory: ${zipEntry.isDirectory}');
183 | print(
184 | 'modificationDate: ${zipEntry.modificationDate!.toLocal().toIso8601String()}');
185 | print('uncompressedSize: ${zipEntry.uncompressedSize}');
186 | print('compressedSize: ${zipEntry.compressedSize}');
187 | print('compressionMethod: ${zipEntry.compressionMethod}');
188 | print('crc: ${zipEntry.crc}');
189 | return ZipFileOperation.includeItem;
190 | }
191 | : null));
192 |
193 | await Future.wait(extractFutures);
194 | assert(onExtractingCallCount1 == onExtractingCallCount2);
195 | assert(!progress || onExtractingCallCount1 > 0);
196 | } on PlatformException catch (e) {
197 | print(e);
198 | }
199 |
200 | // verify unzipped files
201 | if (zipIncludesBaseDirectory) {
202 | _verifyFiles(
203 | Directory("${destinationDir.path}/$_dataFilesBaseDirectoryName"));
204 | _verifyFiles(
205 | Directory("${destinationDir2.path}/$_dataFilesBaseDirectoryName"));
206 | } else {
207 | _verifyFiles(destinationDir);
208 | _verifyFiles(destinationDir2);
209 | }
210 | }
211 |
212 | File _createZipFile(String fileName) {
213 | final zipFilePath = "${_appDataDir.path}/$fileName";
214 | final zipFile = File(zipFilePath);
215 |
216 | if (zipFile.existsSync()) {
217 | print("Deleting existing zip file: ${zipFile.path}");
218 | zipFile.deleteSync();
219 | }
220 | return zipFile;
221 | }
222 |
223 | List _createTestFiles(Directory storeDir) {
224 | if (storeDir.existsSync()) {
225 | storeDir.deleteSync(recursive: true);
226 | }
227 | storeDir.createSync();
228 | final files = [];
229 | for (final fileName in _dataFiles.keys) {
230 | final file = File("${storeDir.path}/$fileName");
231 | file.createSync(recursive: true);
232 | print("Writing file: ${file.path}");
233 | file.writeAsStringSync(_dataFiles[fileName]!);
234 | files.add(file);
235 | }
236 |
237 | // verify created files
238 | _verifyFiles(storeDir);
239 |
240 | return files;
241 | }
242 |
243 | void _verifyFiles(Directory filesDir) {
244 | print("Verifying files at: ${filesDir.path}");
245 | final extractedItems = filesDir.listSync(recursive: true);
246 | for (final item in extractedItems) {
247 | print("extractedItem: ${item.path}");
248 | }
249 | print("File count: ${extractedItems.length}");
250 | assert(extractedItems.whereType().length == _dataFiles.length,
251 | "Invalid number of files");
252 | for (final fileName in _dataFiles.keys) {
253 | final file = File('${filesDir.path}/$fileName');
254 | print("Verifying file: ${file.path}");
255 | assert(file.existsSync(), "File not found: ${file.path}");
256 | final content = file.readAsStringSync();
257 | assert(content == _dataFiles[fileName],
258 | "Invalid file content: ${file.path}");
259 | }
260 | print("All files ok");
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/ios/Classes/SwiftFlutterArchivePlugin.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020 KineApps. All rights reserved.
2 | //
3 | // This source code is licensed under the BSD-style license found in the
4 | // LICENSE file in the root directory of this source tree.
5 |
6 | #if os(OSX)
7 | import FlutterMacOS
8 | #elseif os(iOS)
9 | import Flutter
10 | #endif
11 |
12 | /// https://github.com/weichsel/ZIPFoundation
13 | import ZIPFoundation
14 |
15 | enum ZipFileOperation: String {
16 | case includeItem
17 | case skipItem
18 | case cancel
19 | }
20 |
21 | public class SwiftFlutterArchivePlugin: NSObject, FlutterPlugin {
22 | init(_ channel: FlutterMethodChannel) {
23 | self.channel = channel
24 | }
25 |
26 | let channel: FlutterMethodChannel
27 |
28 | public static func register(with registrar: FlutterPluginRegistrar) {
29 | #if os(OSX)
30 | let channel = FlutterMethodChannel(name: "flutter_archive", binaryMessenger: registrar.messenger)
31 | #elseif os(iOS)
32 | let channel = FlutterMethodChannel(name: "flutter_archive", binaryMessenger: registrar.messenger())
33 | #endif
34 |
35 | let instance = SwiftFlutterArchivePlugin(channel)
36 | registrar.addMethodCallDelegate(instance, channel: channel)
37 | }
38 |
39 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
40 | log("call:" + call.method)
41 |
42 | switch call.method {
43 | case "zipDirectory":
44 | guard let args = call.arguments as? [String: Any] else {
45 | result(FlutterError(code: "INVALID_ARGUMENTS",
46 | message: "Invalid arguments",
47 | details: nil))
48 | return
49 | }
50 | guard let sourceDir = args["sourceDir"] as? String else {
51 | result(FlutterError(code: "INVALID_ARGUMENTS",
52 | message: "Argument 'sourceDir' is missing",
53 | details: nil))
54 | return
55 | }
56 | guard let zipFile = args["zipFile"] as? String else {
57 | result(FlutterError(code: "INVALID_ARGUMENTS",
58 | message: "Argument 'zipFile' is missing",
59 | details: nil))
60 | return
61 | }
62 | let includeBaseDirectory = args["includeBaseDirectory"] as? Bool == true
63 | let recurseSubDirs = args["recurseSubDirs"] as? Bool == true
64 | let reportProgress = args["reportProgress"] as? Bool == true
65 | let jobId = args["jobId"] as? Int
66 |
67 | log("sourceDir: " + sourceDir)
68 | log("zipFile: " + zipFile)
69 | log("includeBaseDirectory: " + includeBaseDirectory.description)
70 | log("recurseSubDirs: " + recurseSubDirs.description)
71 | log("reportProgress: " + reportProgress.description)
72 | log("jobId: " + (jobId?.description ?? ""))
73 |
74 | DispatchQueue.global(qos: .userInitiated).async {
75 | let fileManager = FileManager()
76 | let sourceURL = URL(fileURLWithPath: sourceDir)
77 | let destinationURL = URL(fileURLWithPath: zipFile)
78 | do {
79 | if reportProgress || !recurseSubDirs {
80 | try self.zipDirectory(at: sourceURL,
81 | to: destinationURL,
82 | recurseSubDirs: recurseSubDirs,
83 | includeBaseDirectory: includeBaseDirectory,
84 | reportProgress: reportProgress,
85 | jobId: jobId)
86 | } else {
87 | try fileManager.zipItem(at: sourceURL,
88 | to: destinationURL,
89 | shouldKeepParent: includeBaseDirectory,
90 | compressionMethod: .deflate)
91 | }
92 | DispatchQueue.main.async {
93 | self.log("Created zip at: " + destinationURL.path)
94 | result(true)
95 | }
96 | } catch {
97 | DispatchQueue.main.async {
98 | self.log("Creation of ZIP archive failed with error:\(error)")
99 | result(FlutterError(code: "ZIP_ERROR",
100 | message: error.localizedDescription,
101 | details: nil))
102 | }
103 | }
104 | }
105 |
106 | case "zipFiles":
107 | guard let args = call.arguments as? [String: Any] else {
108 | result(FlutterError(code: "INVALID_ARGUMENTS",
109 | message: "Invalid arguments",
110 | details: nil))
111 | return
112 | }
113 | guard let sourceDir = args["sourceDir"] as? String else {
114 | result(FlutterError(code: "INVALID_ARGUMENTS",
115 | message: "Argument 'sourceDir' is missing",
116 | details: nil))
117 | return
118 | }
119 | guard let files = args["files"] as? [String] else {
120 | result(FlutterError(code: "INVALID_ARGUMENTS",
121 | message: "Argument 'files' is missing",
122 | details: nil))
123 | return
124 | }
125 | guard let zipFile = args["zipFile"] as? String else {
126 | result(FlutterError(code: "INVALID_ARGUMENTS",
127 | message: "Argument 'zipFile' is missing",
128 | details: nil))
129 | return
130 | }
131 | let includeBaseDirectory = args["includeBaseDirectory"] as? Bool == true
132 |
133 | log("files: " + files.joined(separator: ","))
134 | log("zipFile: " + zipFile)
135 | log("includeBaseDirectory: " + includeBaseDirectory.description)
136 |
137 | DispatchQueue.global(qos: .userInitiated).async {
138 | var sourceURL = URL(fileURLWithPath: sourceDir)
139 | if includeBaseDirectory {
140 | sourceURL = sourceURL.deletingLastPathComponent()
141 | }
142 | let destinationURL = URL(fileURLWithPath: zipFile)
143 | do {
144 | // create zip archive
145 | let archive = try Archive(url: destinationURL, accessMode: .create)
146 |
147 | for item in files {
148 | self.log("Adding: " + item)
149 | try archive.addEntry(with: item, relativeTo: sourceURL, compressionMethod: .deflate)
150 | }
151 |
152 | DispatchQueue.main.async {
153 | self.log("Created zip at: " + zipFile)
154 | result(true)
155 | }
156 | } catch {
157 | DispatchQueue.main.async {
158 | self.log("Creation of ZIP archive failed with error:\(error)")
159 | result(FlutterError(code: "ZIP_ERROR",
160 | message: error.localizedDescription,
161 | details: nil))
162 | }
163 | }
164 | }
165 |
166 | case "unzip":
167 | guard let args = call.arguments as? [String: Any] else {
168 | result(FlutterError(code: "INVALID_ARGUMENTS",
169 | message: "Invalid arguments",
170 | details: nil))
171 | return
172 | }
173 | guard let zipFile = args["zipFile"] as? String else {
174 | result(FlutterError(code: "INVALID_ARGUMENTS",
175 | message: "Argument 'zipFile' is missing",
176 | details: nil))
177 | return
178 | }
179 | guard let destinationDir = args["destinationDir"] as? String else {
180 | result(FlutterError(code: "INVALID_ARGUMENTS",
181 | message: "Argument 'destinationDir' is missing",
182 | details: nil))
183 | return
184 | }
185 | let reportProgress = args["reportProgress"] as? Bool
186 | let jobId = args["jobId"] as? Int
187 | let zipFileCharset = args["zipFileCharset"] as? String
188 | log("zipFile: " + zipFile)
189 | log("destinationDir: " + destinationDir)
190 | log("zipFileCharset: " + (zipFileCharset ?? ""))
191 |
192 | DispatchQueue.global(qos: .userInitiated).async {
193 | let fileManager = FileManager()
194 | let sourceURL = URL(fileURLWithPath: zipFile)
195 | let destinationURL = URL(fileURLWithPath: destinationDir)
196 | let preferredEncoding = self.charSet2Encoding(zipFileCharset: zipFileCharset)
197 | do {
198 | if reportProgress == true {
199 | try self.unzipItemAndReportProgress(at: sourceURL, to: destinationURL, jobId: jobId!, preferredEncoding: preferredEncoding)
200 | } else {
201 | try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
202 | try fileManager.unzipItem(at: sourceURL, to: destinationURL)
203 | }
204 |
205 | DispatchQueue.main.async {
206 | self.log("Extracted zip to: " + destinationURL.path)
207 | result(true)
208 | }
209 | } catch {
210 | DispatchQueue.main.async {
211 | self.log("Extraction of ZIP archive failed with error:\(error)")
212 | result(FlutterError(code: "UNZIP_ERROR",
213 | message: error.localizedDescription,
214 | details: nil))
215 | }
216 | }
217 | }
218 |
219 | default:
220 | log("not implemented")
221 | result(FlutterMethodNotImplemented)
222 | }
223 | }
224 |
225 | private func charSet2Encoding(zipFileCharset: String?) ->String.Encoding? {
226 | switch (zipFileCharset) {
227 | case ("ISO_8859_1"): return String.Encoding.isoLatin1
228 | case ("US_ASCII"): return String.Encoding.ascii
229 | case ("UTF_16"): return String.Encoding.utf16
230 | case ("UTF_16BE"): return String.Encoding.utf16BigEndian
231 | case ("UTF_16LE"): return String.Encoding.utf16LittleEndian
232 | case ("UTF_8"): return String.Encoding.utf8
233 | case ("CP437"): return nil
234 | default: return nil
235 | }
236 | }
237 |
238 | private func zipDirectory(at sourceURL: URL,
239 | to zipFileURL: URL,
240 | recurseSubDirs: Bool,
241 | includeBaseDirectory: Bool,
242 | reportProgress: Bool,
243 | jobId: Int?) throws
244 | {
245 | var files = [URL]()
246 | if let enumerator = FileManager.default.enumerator(
247 | at: sourceURL,
248 | includingPropertiesForKeys: [.isRegularFileKey],
249 | options: recurseSubDirs ?
250 | [.skipsHiddenFiles, .skipsPackageDescendants] :
251 | [.skipsHiddenFiles, .skipsPackageDescendants, .skipsSubdirectoryDescendants])
252 | {
253 | for case let fileURL as URL in enumerator {
254 | let fileAttributes = try fileURL.resourceValues(forKeys: [.isRegularFileKey])
255 | if fileAttributes.isRegularFile! {
256 | let url = fileURL.standardizedFileURL
257 | log("Found file: " + url.path)
258 | files.append(url)
259 | }
260 | }
261 | }
262 |
263 | // create zip archive
264 | let archive = try Archive(url: zipFileURL, accessMode: .create)
265 |
266 | let totalEntriesCount = Double(files.count)
267 | var currentEntryIndex: Double = 0
268 |
269 | let dispatchGroup = DispatchGroup()
270 |
271 | let baseDirUrl = URL(fileURLWithPath: includeBaseDirectory ?
272 | sourceURL.deletingLastPathComponent().path : sourceURL.path).standardizedFileURL
273 | log("baseDirUrl: " + baseDirUrl.path)
274 | for item in files {
275 | if reportProgress {
276 | log("File: " + item.path)
277 | currentEntryIndex += 1
278 | let progress: Double = currentEntryIndex / totalEntriesCount * 100.0
279 |
280 | let entryDic: [String: Any] = [
281 | "name": item.path,
282 | "isDirectory": item.isDirectory,
283 | "jobId": jobId!,
284 | "progress": progress,
285 | ]
286 |
287 | var extractOperation: ZipFileOperation?
288 | dispatchGroup.enter()
289 | DispatchQueue.main.async {
290 | self.channel.invokeMethod("progress", arguments: entryDic) {
291 | (result: Any?) -> Void in
292 | if let error = result as? FlutterError {
293 | self.log("failed: \(error)")
294 | extractOperation = ZipFileOperation.includeItem
295 | } else if FlutterMethodNotImplemented.isEqual(result) {
296 | self.log("not implemented")
297 | extractOperation = ZipFileOperation.includeItem
298 | } else {
299 | extractOperation = ZipFileOperation(rawValue: result as! String)
300 | self.log("result: \(String(describing: extractOperation))")
301 | }
302 | dispatchGroup.leave()
303 | }
304 | }
305 |
306 |
307 | log("Waiting...")
308 | dispatchGroup.wait()
309 | log("..waiting")
310 | if extractOperation == ZipFileOperation.skipItem {
311 | log("skip")
312 | continue
313 | } else if extractOperation == ZipFileOperation.cancel {
314 | log("cancel")
315 | break
316 | }
317 | }
318 |
319 | let relativePath = item.path.replacingFirstOccurrence(of: baseDirUrl.path + "/", with: "")
320 | log("Adding: " + relativePath)
321 | try archive.addEntry(with: relativePath, relativeTo: baseDirUrl, compressionMethod: .deflate)
322 | }
323 | }
324 |
325 | /// Unzips the contents at the specified source URL to the destination URL.
326 | ///
327 | /// - Parameters:
328 | /// - sourceURL: The file URL pointing to an existing ZIP file.
329 | /// - destinationURL: The file URL that identifies the destination directory of the unzip operation.
330 | /// - jobId: Job id
331 | /// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance.
332 | /// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive.
333 | /// - Throws: Throws an error if the source item does not exist or the destination URL is not writable.
334 | private func unzipItemAndReportProgress(at sourceURL: URL, to destinationURL: URL, jobId: Int, skipCRC32: Bool = false,
335 | preferredEncoding: String.Encoding? = nil) throws
336 | {
337 | // based on https://github.com/weichsel/ZIPFoundation/blob/development/Sources/ZIPFoundation/FileManager%2BZIP.swift
338 | guard itemExists(at: sourceURL) else {
339 | throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: sourceURL.path])
340 | }
341 | let archive = try Archive(url: sourceURL, accessMode: .read, pathEncoding: preferredEncoding)
342 |
343 | // Defer extraction of symlinks until all files & directories have been created.
344 | // This is necessary because we can't create links to files that haven't been created yet.
345 | let sortedEntries = archive.sorted { (left, right) -> Bool in
346 | switch (left.type, right.type) {
347 | case (.directory, .file): return true
348 | case (.directory, .symlink): return true
349 | case (.file, .symlink): return true
350 | default: return false
351 | }
352 | }
353 |
354 | let totalEntriesCount = Double(sortedEntries.count)
355 | var currentEntryIndex: Double = 0
356 |
357 | let dispatchGroup = DispatchGroup()
358 | for entry in sortedEntries {
359 | let path = preferredEncoding == nil ? entry.path : entry.path(using: preferredEncoding!)
360 | let destinationEntryURL = destinationURL.appendingPathComponent(path)
361 |
362 | var entryDic = entryToDictionary(entry: entry, preferredEncoding: preferredEncoding)
363 | currentEntryIndex += 1
364 | let progress: Double = currentEntryIndex / totalEntriesCount * 100.0
365 | entryDic["jobId"] = jobId
366 | entryDic["progress"] = progress
367 | var extractOperation: ZipFileOperation?
368 | dispatchGroup.enter()
369 | DispatchQueue.main.async {
370 | self.channel.invokeMethod("progress", arguments: entryDic) {
371 | (result: Any?) -> Void in
372 | if let error = result as? FlutterError {
373 | self.log("failed: \(error)")
374 | extractOperation = ZipFileOperation.includeItem
375 | } else if FlutterMethodNotImplemented.isEqual(result) {
376 | self.log("not implemented")
377 | extractOperation = ZipFileOperation.includeItem
378 | } else {
379 | extractOperation = ZipFileOperation(rawValue: result as! String)
380 | self.log("result: \(String(describing: extractOperation))")
381 | }
382 | dispatchGroup.leave()
383 | }
384 | }
385 |
386 | log("Waiting...")
387 | dispatchGroup.wait()
388 | log("..waiting")
389 | if extractOperation == ZipFileOperation.skipItem {
390 | log("skip")
391 | continue
392 | } else if extractOperation == ZipFileOperation.cancel {
393 | log("cancel")
394 | break
395 | }
396 |
397 | guard destinationEntryURL.isContained(in: destinationURL) else {
398 | throw CocoaError(.fileReadInvalidFileName,
399 | userInfo: [NSFilePathErrorKey: destinationEntryURL.path])
400 | }
401 | _ = try archive.extract(entry, to: destinationEntryURL, skipCRC32: skipCRC32)
402 | }
403 | }
404 |
405 | // MARK: - Helpers
406 |
407 | // https://github.com/weichsel/ZIPFoundation/blob/development/Sources/ZIPFoundation/FileManager%2BZIP.swift
408 | private func itemExists(at url: URL) -> Bool {
409 | // Use `URL.checkResourceIsReachable()` instead of `FileManager.fileExists()` here
410 | // because we don't want implicit symlink resolution.
411 | // As per documentation, `FileManager.fileExists()` traverses symlinks and therefore a broken symlink
412 | // would throw a `.fileReadNoSuchFile` false positive error.
413 | // For ZIP files it may be intended to archive "broken" symlinks because they might be
414 | // resolvable again when extracting the archive to a different destination.
415 | return (try? url.checkResourceIsReachable()) == true
416 | }
417 |
418 | /// https://github.com/flutter/flutter/issues/13204
419 | private func log(_ message: String) {
420 | NSLog("\n" + message)
421 | }
422 |
423 | private func entryToDictionary(entry: Entry, preferredEncoding: String.Encoding? = nil) -> [String: Any] {
424 | let date = entry.fileAttributes[FileAttributeKey.modificationDate] as? Date
425 | let millis = Int(date?.timeIntervalSince1970 ?? 0) * 1000
426 | let dic: [String: Any] = [
427 | "name": preferredEncoding == nil ? entry.path : entry.path(using: preferredEncoding!),
428 | "isDirectory": entry.type == Entry.EntryType.directory,
429 | "modificationDate": millis,
430 | "uncompressedSize": entry.uncompressedSize,
431 | "compressedSize": entry.compressedSize,
432 | "crc": entry.checksum,
433 | "compressionMethod": entry.compressedSize != entry.uncompressedSize ? "deflated" : "none",
434 | ]
435 | return dic
436 | }
437 | }
438 |
439 | extension URL {
440 | var isDirectory: Bool {
441 | return (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true
442 | }
443 | }
444 |
445 | extension String {
446 | func replacingFirstOccurrence(of target: String, with replacement: String) -> String {
447 | guard let range = self.range(of: target) else { return self }
448 | return replacingCharacters(in: range, with: replacement)
449 | }
450 | }
451 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/kineapps/flutterarchive/FlutterArchivePlugin.kt:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2022 KineApps. All rights reserved.
2 | //
3 | // This source code is licensed under the BSD-style license found in the
4 | // LICENSE file in the root directory of this source tree.
5 |
6 | package com.kineapps.flutterarchive
7 |
8 | import android.os.Build
9 | import android.util.Log
10 | import io.flutter.embedding.engine.plugins.FlutterPlugin
11 | import io.flutter.plugin.common.BinaryMessenger
12 | import io.flutter.plugin.common.MethodCall
13 | import io.flutter.plugin.common.MethodChannel
14 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler
15 | import io.flutter.plugin.common.MethodChannel.Result
16 | import kotlinx.coroutines.CancellationException
17 | import kotlinx.coroutines.CompletableDeferred
18 | import kotlinx.coroutines.CoroutineScope
19 | import kotlinx.coroutines.Dispatchers
20 | import kotlinx.coroutines.launch
21 | import kotlinx.coroutines.withContext
22 | import java.io.BufferedOutputStream
23 | import java.io.Closeable
24 | import java.io.File
25 | import java.io.FileInputStream
26 | import java.io.FileOutputStream
27 | import java.io.IOException
28 | import java.nio.charset.Charset
29 | import java.util.zip.ZipEntry
30 | import java.util.zip.ZipEntry.DEFLATED
31 | import java.util.zip.ZipFile
32 | import java.util.zip.ZipOutputStream
33 |
34 | enum class ZipFileOperation { INCLUDE_ITEM, SKIP_ITEM, CANCEL }
35 |
36 | /**
37 | * FlutterArchivePlugin
38 | */
39 | class FlutterArchivePlugin : FlutterPlugin, MethodCallHandler {
40 | private var pluginBinding: FlutterPlugin.FlutterPluginBinding? = null
41 | private var methodChannel: MethodChannel? = null
42 |
43 | companion object {
44 | private const val LOG_TAG = "FlutterArchivePlugin"
45 | }
46 |
47 | override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
48 | Log.d(LOG_TAG, "onAttachedToEngine - IN")
49 |
50 | if (pluginBinding != null) {
51 | Log.w(LOG_TAG, "onAttachedToEngine - already attached")
52 | }
53 |
54 | pluginBinding = binding
55 |
56 | val messenger = pluginBinding?.binaryMessenger
57 | doOnAttachedToEngine(messenger!!)
58 |
59 | Log.d(LOG_TAG, "onAttachedToEngine - OUT")
60 | }
61 |
62 | override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
63 | Log.d(LOG_TAG, "onDetachedFromEngine")
64 | doOnDetachedFromEngine()
65 | }
66 |
67 | private fun doOnAttachedToEngine(messenger: BinaryMessenger) {
68 | Log.d(LOG_TAG, "doOnAttachedToEngine - IN")
69 |
70 | methodChannel = MethodChannel(messenger, "flutter_archive")
71 | methodChannel?.setMethodCallHandler(this)
72 |
73 | Log.d(LOG_TAG, "doOnAttachedToEngine - OUT")
74 | }
75 |
76 | private fun doOnDetachedFromEngine() {
77 | Log.d(LOG_TAG, "doOnDetachedFromEngine - IN")
78 |
79 | if (pluginBinding == null) {
80 | Log.w(LOG_TAG, "doOnDetachedFromEngine - already detached")
81 | }
82 | pluginBinding = null
83 |
84 | methodChannel?.setMethodCallHandler(null)
85 | methodChannel = null
86 |
87 | Log.d(LOG_TAG, "doOnDetachedFromEngine - OUT")
88 | }
89 |
90 | override fun onMethodCall(call: MethodCall, result: Result) {
91 | val uiScope = CoroutineScope(Dispatchers.Main)
92 |
93 | when (call.method) {
94 | "zipDirectory" -> {
95 | uiScope.launch {
96 | try {
97 | val sourceDir = call.argument("sourceDir")
98 | val zipFile = call.argument("zipFile")
99 | val recurseSubDirs = call.argument("recurseSubDirs") == true
100 | val includeBaseDirectory =
101 | call.argument("includeBaseDirectory") == true
102 | val reportProgress = call.argument("reportProgress")
103 | val jobId = call.argument("jobId")
104 |
105 | withContext(Dispatchers.IO) {
106 | zip(
107 | sourceDirPath = sourceDir!!,
108 | zipFilePath = zipFile!!,
109 | recurseSubDirs = recurseSubDirs,
110 | includeBaseDirectory = includeBaseDirectory,
111 | reportProgress = reportProgress == true,
112 | jobId = jobId!!
113 | )
114 | }
115 | result.success(true)
116 | } catch (e: Exception) {
117 | e.printStackTrace()
118 | result.error("zip_error", e.localizedMessage, e.toString())
119 | }
120 | }
121 | }
122 | "zipFiles" -> {
123 | uiScope.launch {
124 | try {
125 | val sourceDir = call.argument("sourceDir")
126 | val files = call.argument>("files")
127 | val zipFile = call.argument("zipFile")
128 | val includeBaseDirectory =
129 | call.argument("includeBaseDirectory") == true
130 |
131 | withContext(Dispatchers.IO) {
132 | zipFiles(sourceDir!!, files!!, zipFile!!, includeBaseDirectory)
133 | }
134 | result.success(true)
135 | } catch (e: Exception) {
136 | e.printStackTrace()
137 | result.error("zip_error", e.localizedMessage, e.toString())
138 | }
139 | }
140 | }
141 | "unzip" -> {
142 | uiScope.launch {
143 | try {
144 | val zipFile = call.argument("zipFile")
145 | val zipFileCharset = call.argument("zipFileCharset")
146 | val destinationDir = call.argument("destinationDir")
147 | val reportProgress = call.argument("reportProgress")
148 | val jobId = call.argument("jobId")
149 |
150 | val charset = zipFileCharset?.let { Charset.forName(zipFileCharset) }
151 |
152 | Log.d(LOG_TAG, "onMethodCall / unzip...")
153 | withContext(Dispatchers.IO) {
154 | unzip(
155 | zipFilePath = zipFile!!,
156 | zipFileCharSet = charset,
157 | destinationDirPath = destinationDir!!,
158 | reportProgress = reportProgress == true,
159 | jobId = jobId!!
160 | )
161 | }
162 | Log.d(LOG_TAG, "...onMethodCall / unzip")
163 | result.success(true)
164 | } catch (e: Exception) {
165 | e.printStackTrace()
166 | result.error("unzip_error", e.localizedMessage, e.toString())
167 | }
168 | }
169 | }
170 | else -> result.notImplemented()
171 | }
172 | }
173 |
174 | @Throws(IOException::class)
175 | private suspend fun zip(
176 | sourceDirPath: String,
177 | zipFilePath: String,
178 | recurseSubDirs: Boolean,
179 | includeBaseDirectory: Boolean,
180 | reportProgress: Boolean,
181 | jobId: Int
182 | ) {
183 | Log.i(
184 | "zip",
185 | "sourceDirPath: $sourceDirPath, zipFilePath: $zipFilePath, recurseSubDirs: $recurseSubDirs, includeBaseDirectory: $includeBaseDirectory"
186 | )
187 |
188 | val rootDirectory =
189 | if (includeBaseDirectory) File(sourceDirPath).parentFile else File(sourceDirPath)
190 |
191 | val totalFileCount = if (reportProgress) getFilesCount(rootDirectory, recurseSubDirs) else 0
192 |
193 | withContext(Dispatchers.IO) {
194 | ZipOutputStream(
195 | BufferedOutputStream(
196 | FileOutputStream(zipFilePath)
197 | )
198 | ).use { zipOutputStream ->
199 | addFilesInDirectoryToZip(
200 | zipOutputStream = zipOutputStream,
201 | rootDirectory = rootDirectory,
202 | directoryPath = sourceDirPath,
203 | recurseSubDirs = recurseSubDirs,
204 | reportProgress = reportProgress,
205 | jobId = jobId,
206 | totalFilesCount = totalFileCount,
207 | totalHandledFilesCount = 0
208 | )
209 | }
210 | }
211 | }
212 |
213 | /**
214 | * Add all files in [rootDirectory] to [zipOutputStream].
215 | *
216 | * @return Updated total number of handled files
217 | */
218 | private suspend fun addFilesInDirectoryToZip(
219 | zipOutputStream: ZipOutputStream,
220 | rootDirectory: File,
221 | directoryPath: String,
222 | recurseSubDirs: Boolean,
223 | reportProgress: Boolean,
224 | jobId: Int,
225 | totalFilesCount: Int,
226 | totalHandledFilesCount: Int
227 | ): Int {
228 | val directory = File(directoryPath)
229 |
230 | val files = directory.listFiles() ?: arrayOf()
231 | var handledFilesCount = totalHandledFilesCount
232 | for (f in files) {
233 | val path = directoryPath + File.separator + f.name
234 | val relativePath = File(path).relativeTo(rootDirectory).path
235 |
236 | if (f.isDirectory) {
237 | // include subdirectories only if requested
238 | if (!recurseSubDirs) {
239 | continue
240 | }
241 | Log.i("zip", "Adding directory: $relativePath")
242 |
243 | // add directory entry
244 | val entry = ZipEntry(relativePath + File.separator)
245 | entry.time = f.lastModified()
246 | entry.size = f.length()
247 |
248 | if (reportProgress) {
249 | // report progress
250 | val progress: Double =
251 | handledFilesCount.toDouble() / totalFilesCount.toDouble() * 100.0
252 |
253 | Log.d(LOG_TAG, "Waiting reportProgress...")
254 | val zipFileOperation = reportProgress(jobId, entry, progress)
255 | Log.d(LOG_TAG, "...reportProgress: $zipFileOperation")
256 |
257 | if (zipFileOperation == ZipFileOperation.SKIP_ITEM) {
258 | continue
259 | } else if (zipFileOperation == ZipFileOperation.CANCEL) {
260 | throw CancellationException("Operation cancelled")
261 | }
262 | }
263 |
264 | withContext(Dispatchers.IO) {
265 | zipOutputStream.putNextEntry(entry)
266 | }
267 |
268 | // zip files and subdirectories in this directory
269 | handledFilesCount = addFilesInDirectoryToZip(
270 | zipOutputStream = zipOutputStream,
271 | rootDirectory = rootDirectory,
272 | directoryPath = path,
273 | recurseSubDirs = true,
274 | reportProgress = reportProgress,
275 | jobId = jobId,
276 | totalFilesCount = totalFilesCount,
277 | totalHandledFilesCount = handledFilesCount
278 | )
279 | } else {
280 | Log.i("zip", "Adding file: $relativePath")
281 | ++handledFilesCount
282 | withContext(Dispatchers.IO) {
283 | FileInputStream(f).use { fileInputStream ->
284 | val entry = ZipEntry(relativePath)
285 | entry.time = f.lastModified()
286 | entry.size = f.length()
287 |
288 | if (reportProgress) {
289 | // report progress
290 | val progress: Double =
291 | handledFilesCount.toDouble() / totalFilesCount.toDouble() * 100.0
292 |
293 | Log.d(LOG_TAG, "Waiting reportProgress...")
294 | val zipFileOperation = reportProgress(jobId, entry, progress)
295 | Log.d(LOG_TAG, "...reportProgress: $zipFileOperation")
296 |
297 | when (zipFileOperation) {
298 | ZipFileOperation.INCLUDE_ITEM -> {
299 | zipOutputStream.putNextEntry(entry)
300 | fileInputStream.copyTo(zipOutputStream)
301 | }
302 | ZipFileOperation.CANCEL -> {
303 | throw CancellationException("Operation cancelled")
304 | }
305 | else -> {
306 | // skip this entry
307 | }
308 | }
309 | } else {
310 | zipOutputStream.putNextEntry(entry)
311 | fileInputStream.copyTo(zipOutputStream)
312 | }
313 | }
314 | }
315 | }
316 | }
317 | return handledFilesCount
318 | }
319 |
320 | @Throws(IOException::class)
321 | private fun zipFiles(
322 | sourceDirPath: String,
323 | relativeFilePaths: List,
324 | zipFilePath: String,
325 | includeBaseDirectory: Boolean
326 | ) {
327 | Log.i(
328 | "zip",
329 | "sourceDirPath: $sourceDirPath, " +
330 | "zipFilePath: $zipFilePath, " +
331 | "includeBaseDirectory: $includeBaseDirectory"
332 | )
333 | Log.i("zip", "Files: ${relativeFilePaths.joinToString(",")}")
334 |
335 | val rootDirectory =
336 | if (includeBaseDirectory) File(sourceDirPath).parentFile else File(sourceDirPath)
337 |
338 | ZipOutputStream(
339 | BufferedOutputStream(
340 | FileOutputStream(zipFilePath)
341 | )
342 | ).use { zipOutputStream ->
343 | for (relativeFilePath in relativeFilePaths) {
344 | val file = rootDirectory.resolve(relativeFilePath)
345 | val cleanedRelativeFilePath = file.relativeTo(rootDirectory).path
346 | Log.i("zip", "Adding file: $cleanedRelativeFilePath")
347 | FileInputStream(file).use { fileInputStream ->
348 | val entry = ZipEntry(cleanedRelativeFilePath)
349 | entry.time = file.lastModified()
350 | entry.size = file.length()
351 | zipOutputStream.putNextEntry(entry)
352 | fileInputStream.copyTo(zipOutputStream)
353 | }
354 | }
355 | }
356 | }
357 |
358 | @Throws(IOException::class)
359 | private suspend fun unzip(
360 | zipFilePath: String,
361 | zipFileCharSet: Charset?,
362 | destinationDirPath: String,
363 | reportProgress: Boolean,
364 | jobId: Int
365 | ) {
366 | val destinationDir = File(destinationDirPath)
367 |
368 | Log.d(LOG_TAG, "destinationDir.path: ${destinationDir.path}")
369 | Log.d(LOG_TAG, "destinationDir.canonicalPath: ${destinationDir.canonicalPath}")
370 | Log.d(LOG_TAG, "destinationDir.absolutePath: ${destinationDir.absolutePath}")
371 |
372 | // specify charset if unzip fails to MALFORMED exception, see for example
373 | // https://stackoverflow.com/questions/41908761/unzipping-a-file-with-special-characters-in-filenames-from-api24-upward
374 | val zipFile: ZipFile =
375 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
376 | zipFileCharSet != null
377 | ) {
378 | ZipFile(zipFilePath, zipFileCharSet)
379 | } else {
380 | ZipFileEx(zipFilePath)
381 | }
382 |
383 | zipFile.use {
384 | val entriesCount = zipFile.size().toDouble()
385 | var currentEntryIndex = 0.0
386 | for (ze in zipFile.entries()) {
387 | val filename = ze.name
388 | Log.d(
389 | LOG_TAG,
390 | "zipEntry fileName=$filename, compressedSize=${ze.compressedSize}, size=${ze.size}, crc=${ze.crc}"
391 | )
392 |
393 | val outputFile = File(destinationDirPath, filename)
394 |
395 | // prevent Zip Path Traversal attack
396 | // https://support.google.com/faqs/answer/9294009
397 | val outputFileCanonicalPath = outputFile.canonicalPath
398 | if (!outputFileCanonicalPath.startsWith(destinationDir.canonicalPath)) {
399 | Log.d(LOG_TAG, "outputFile path: ${outputFile.path}")
400 | Log.d(LOG_TAG, "canonicalPath: $outputFileCanonicalPath")
401 | throw SecurityException("Invalid zip file")
402 | }
403 |
404 | if (reportProgress) {
405 | // report progress
406 | val progress: Double = currentEntryIndex++ / (entriesCount - 1) * 100
407 |
408 | Log.d(LOG_TAG, "Waiting reportProgress...")
409 | val zipFileOperation = reportProgress(jobId, ze, progress)
410 | Log.d(LOG_TAG, "...reportProgress: $zipFileOperation")
411 |
412 | if (zipFileOperation == ZipFileOperation.SKIP_ITEM) {
413 | continue
414 | } else if (zipFileOperation == ZipFileOperation.CANCEL) {
415 | break
416 | }
417 | }
418 |
419 | // need to create any missing directories
420 | if (ze.isDirectory) {
421 | Log.d(LOG_TAG, "Creating directory: " + outputFile.path)
422 | outputFile.mkdirs()
423 | } else {
424 | val parentDir = outputFile.parentFile
425 | if (parentDir != null && !parentDir.exists()) {
426 | Log.d(LOG_TAG, "Creating directory: " + parentDir.path)
427 | parentDir.mkdirs()
428 | }
429 |
430 | Log.d(LOG_TAG, "Writing entry to file: " + outputFile.path)
431 | withContext(Dispatchers.IO) {
432 | zipFile.getInputStream(ze).use { zis ->
433 | outputFile.outputStream()
434 | .use { outputStream -> zis.copyTo(outputStream) }
435 | }
436 | }
437 | }
438 | }
439 | }
440 | }
441 |
442 | private suspend fun reportProgress(
443 | jobId: Int,
444 | zipEntry: ZipEntry,
445 | progress: Double
446 | ): ZipFileOperation {
447 | val map = zipEntryToMap(zipEntry).toMutableMap()
448 | map["jobId"] = jobId
449 | map["progress"] = progress
450 |
451 | val deferred = CompletableDeferred()
452 |
453 | val uiScope = CoroutineScope(Dispatchers.Main)
454 | uiScope.launch {
455 | methodChannel?.invokeMethod("progress", map, object : Result {
456 |
457 | override fun success(result: Any?) {
458 | Log.i(LOG_TAG, "invokeMethod - success: $result")
459 | when (result) {
460 | "cancel" -> {
461 | deferred.complete(ZipFileOperation.CANCEL)
462 | }
463 | "skipItem" -> {
464 | deferred.complete(ZipFileOperation.SKIP_ITEM)
465 | }
466 | else -> {
467 | deferred.complete(ZipFileOperation.INCLUDE_ITEM)
468 | }
469 | }
470 | }
471 |
472 | override fun error(code: String, msg: String?, details: Any?) {
473 | Log.e(LOG_TAG, "invokeMethod - error: $msg")
474 | // ignore error and extract normally
475 | deferred.complete(ZipFileOperation.INCLUDE_ITEM)
476 | }
477 |
478 | override fun notImplemented() {
479 | Log.e(LOG_TAG, "invokeMethod - notImplemented")
480 | // ignore error and extract normally
481 | deferred.complete(ZipFileOperation.INCLUDE_ITEM)
482 | }
483 | })
484 | }
485 | return deferred.await()
486 | }
487 |
488 | /**
489 | * Return number of files under [dir]. Count also files in subdirectories
490 | * if [recurseSubDirs] is true.
491 | */
492 | private fun getFilesCount(dir: File, recurseSubDirs: Boolean): Int {
493 | val fileAndDirs = dir.listFiles()
494 | var count = 0
495 | if (fileAndDirs != null) {
496 | for (f in fileAndDirs) {
497 | if (recurseSubDirs && f.isDirectory) {
498 | count += getFilesCount(f, recurseSubDirs)
499 | } else {
500 | count++
501 | }
502 | }
503 | }
504 | return count
505 | }
506 |
507 | private fun zipEntryToMap(ze: ZipEntry): Map {
508 | return mapOf(
509 | "name" to ze.name,
510 | "isDirectory" to ze.isDirectory,
511 | "comment" to ze.comment,
512 | "modificationDate" to ze.time,
513 | "uncompressedSize" to ze.size,
514 | "compressedSize" to ze.compressedSize,
515 | "crc" to ze.crc,
516 | "compressionMethod" to (if (ze.method == DEFLATED) "deflated" else "none")
517 | )
518 | }
519 |
520 | // This is needed because ZipFile implements Closeable only starting from API 19 and
521 | // we support >=16
522 | class ZipFileEx(name: String?) : ZipFile(name), Closeable
523 | }
524 |
--------------------------------------------------------------------------------
/example/macos/Runner/Base.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 2825EDA2B7E425A67EF2581F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E66F8FB77AD5CD9F792F17E /* Pods_Runner.framework */; };
12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
14 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXCopyFilesBuildPhase section */
21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
22 | isa = PBXCopyFilesBuildPhase;
23 | buildActionMask = 2147483647;
24 | dstPath = "";
25 | dstSubfolderSpec = 10;
26 | files = (
27 | );
28 | name = "Embed Frameworks";
29 | runOnlyForDeploymentPostprocessing = 0;
30 | };
31 | /* End PBXCopyFilesBuildPhase section */
32 |
33 | /* Begin PBXFileReference section */
34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
37 | 3E66F8FB77AD5CD9F792F17E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
38 | 6C8F778387C8B87CADE0DDD9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
39 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
40 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
41 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
42 | 7BF65B94ADA84A925396EB4A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
43 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
44 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
45 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
47 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
48 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
49 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | CE6E4F333B1E1EEE26EB0103 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
51 | /* End PBXFileReference section */
52 |
53 | /* Begin PBXFrameworksBuildPhase section */
54 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
55 | isa = PBXFrameworksBuildPhase;
56 | buildActionMask = 2147483647;
57 | files = (
58 | 2825EDA2B7E425A67EF2581F /* Pods_Runner.framework in Frameworks */,
59 | );
60 | runOnlyForDeploymentPostprocessing = 0;
61 | };
62 | /* End PBXFrameworksBuildPhase section */
63 |
64 | /* Begin PBXGroup section */
65 | 566540B082174A6CFE95918A /* Frameworks */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 3E66F8FB77AD5CD9F792F17E /* Pods_Runner.framework */,
69 | );
70 | name = Frameworks;
71 | sourceTree = "";
72 | };
73 | 9740EEB11CF90186004384FC /* Flutter */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
77 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
78 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
79 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
80 | );
81 | name = Flutter;
82 | sourceTree = "";
83 | };
84 | 97C146E51CF9000F007C117D = {
85 | isa = PBXGroup;
86 | children = (
87 | 9740EEB11CF90186004384FC /* Flutter */,
88 | 97C146F01CF9000F007C117D /* Runner */,
89 | 97C146EF1CF9000F007C117D /* Products */,
90 | E69B4D5D2A0DB72BC2E72F88 /* Pods */,
91 | 566540B082174A6CFE95918A /* Frameworks */,
92 | );
93 | sourceTree = "";
94 | };
95 | 97C146EF1CF9000F007C117D /* Products */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 97C146EE1CF9000F007C117D /* Runner.app */,
99 | );
100 | name = Products;
101 | sourceTree = "";
102 | };
103 | 97C146F01CF9000F007C117D /* Runner */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
107 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
108 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
109 | 97C147021CF9000F007C117D /* Info.plist */,
110 | 97C146F11CF9000F007C117D /* Supporting Files */,
111 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
112 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
113 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
114 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
115 | );
116 | path = Runner;
117 | sourceTree = "";
118 | };
119 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
120 | isa = PBXGroup;
121 | children = (
122 | );
123 | name = "Supporting Files";
124 | sourceTree = "";
125 | };
126 | E69B4D5D2A0DB72BC2E72F88 /* Pods */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 6C8F778387C8B87CADE0DDD9 /* Pods-Runner.debug.xcconfig */,
130 | CE6E4F333B1E1EEE26EB0103 /* Pods-Runner.release.xcconfig */,
131 | 7BF65B94ADA84A925396EB4A /* Pods-Runner.profile.xcconfig */,
132 | );
133 | path = Pods;
134 | sourceTree = "";
135 | };
136 | /* End PBXGroup section */
137 |
138 | /* Begin PBXNativeTarget section */
139 | 97C146ED1CF9000F007C117D /* Runner */ = {
140 | isa = PBXNativeTarget;
141 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
142 | buildPhases = (
143 | 47F5A62ADCF321E3D18E1DED /* [CP] Check Pods Manifest.lock */,
144 | 9740EEB61CF901F6004384FC /* Run Script */,
145 | 97C146EA1CF9000F007C117D /* Sources */,
146 | 97C146EB1CF9000F007C117D /* Frameworks */,
147 | 97C146EC1CF9000F007C117D /* Resources */,
148 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
149 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
150 | DE45073DF0D19C85955D3576 /* [CP] Embed Pods Frameworks */,
151 | );
152 | buildRules = (
153 | );
154 | dependencies = (
155 | );
156 | name = Runner;
157 | productName = Runner;
158 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
159 | productType = "com.apple.product-type.application";
160 | };
161 | /* End PBXNativeTarget section */
162 |
163 | /* Begin PBXProject section */
164 | 97C146E61CF9000F007C117D /* Project object */ = {
165 | isa = PBXProject;
166 | attributes = {
167 | LastUpgradeCheck = 1510;
168 | ORGANIZATIONNAME = "The Chromium Authors";
169 | TargetAttributes = {
170 | 97C146ED1CF9000F007C117D = {
171 | CreatedOnToolsVersion = 7.3.1;
172 | DevelopmentTeam = YOUR_TEAM_ID;
173 | LastSwiftMigration = 0910;
174 | };
175 | };
176 | };
177 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
178 | compatibilityVersion = "Xcode 3.2";
179 | developmentRegion = en;
180 | hasScannedForEncodings = 0;
181 | knownRegions = (
182 | en,
183 | Base,
184 | );
185 | mainGroup = 97C146E51CF9000F007C117D;
186 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
187 | projectDirPath = "";
188 | projectRoot = "";
189 | targets = (
190 | 97C146ED1CF9000F007C117D /* Runner */,
191 | );
192 | };
193 | /* End PBXProject section */
194 |
195 | /* Begin PBXResourcesBuildPhase section */
196 | 97C146EC1CF9000F007C117D /* Resources */ = {
197 | isa = PBXResourcesBuildPhase;
198 | buildActionMask = 2147483647;
199 | files = (
200 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
201 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
202 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
203 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
204 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | /* End PBXResourcesBuildPhase section */
209 |
210 | /* Begin PBXShellScriptBuildPhase section */
211 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
212 | isa = PBXShellScriptBuildPhase;
213 | alwaysOutOfDate = 1;
214 | buildActionMask = 2147483647;
215 | files = (
216 | );
217 | inputPaths = (
218 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
219 | );
220 | name = "Thin Binary";
221 | outputPaths = (
222 | );
223 | runOnlyForDeploymentPostprocessing = 0;
224 | shellPath = /bin/sh;
225 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
226 | };
227 | 47F5A62ADCF321E3D18E1DED /* [CP] Check Pods Manifest.lock */ = {
228 | isa = PBXShellScriptBuildPhase;
229 | buildActionMask = 2147483647;
230 | files = (
231 | );
232 | inputFileListPaths = (
233 | );
234 | inputPaths = (
235 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
236 | "${PODS_ROOT}/Manifest.lock",
237 | );
238 | name = "[CP] Check Pods Manifest.lock";
239 | outputFileListPaths = (
240 | );
241 | outputPaths = (
242 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
243 | );
244 | runOnlyForDeploymentPostprocessing = 0;
245 | shellPath = /bin/sh;
246 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
247 | showEnvVarsInLog = 0;
248 | };
249 | 9740EEB61CF901F6004384FC /* Run Script */ = {
250 | isa = PBXShellScriptBuildPhase;
251 | alwaysOutOfDate = 1;
252 | buildActionMask = 2147483647;
253 | files = (
254 | );
255 | inputPaths = (
256 | );
257 | name = "Run Script";
258 | outputPaths = (
259 | );
260 | runOnlyForDeploymentPostprocessing = 0;
261 | shellPath = /bin/sh;
262 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
263 | };
264 | DE45073DF0D19C85955D3576 /* [CP] Embed Pods Frameworks */ = {
265 | isa = PBXShellScriptBuildPhase;
266 | buildActionMask = 2147483647;
267 | files = (
268 | );
269 | inputPaths = (
270 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
271 | "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework",
272 | "${BUILT_PRODUCTS_DIR}/flutter_archive/flutter_archive.framework",
273 | );
274 | name = "[CP] Embed Pods Frameworks";
275 | outputPaths = (
276 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework",
277 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_archive.framework",
278 | );
279 | runOnlyForDeploymentPostprocessing = 0;
280 | shellPath = /bin/sh;
281 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
282 | showEnvVarsInLog = 0;
283 | };
284 | /* End PBXShellScriptBuildPhase section */
285 |
286 | /* Begin PBXSourcesBuildPhase section */
287 | 97C146EA1CF9000F007C117D /* Sources */ = {
288 | isa = PBXSourcesBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
292 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
293 | );
294 | runOnlyForDeploymentPostprocessing = 0;
295 | };
296 | /* End PBXSourcesBuildPhase section */
297 |
298 | /* Begin PBXVariantGroup section */
299 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
300 | isa = PBXVariantGroup;
301 | children = (
302 | 97C146FB1CF9000F007C117D /* Base */,
303 | );
304 | name = Main.storyboard;
305 | sourceTree = "";
306 | };
307 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
308 | isa = PBXVariantGroup;
309 | children = (
310 | 97C147001CF9000F007C117D /* Base */,
311 | );
312 | name = LaunchScreen.storyboard;
313 | sourceTree = "";
314 | };
315 | /* End PBXVariantGroup section */
316 |
317 | /* Begin XCBuildConfiguration section */
318 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
319 | isa = XCBuildConfiguration;
320 | baseConfigurationReference = 7BF65B94ADA84A925396EB4A /* Pods-Runner.profile.xcconfig */;
321 | buildSettings = {
322 | ALWAYS_SEARCH_USER_PATHS = NO;
323 | CLANG_ANALYZER_NONNULL = YES;
324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
325 | CLANG_CXX_LIBRARY = "libc++";
326 | CLANG_ENABLE_MODULES = YES;
327 | CLANG_ENABLE_OBJC_ARC = YES;
328 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
329 | CLANG_WARN_BOOL_CONVERSION = YES;
330 | CLANG_WARN_COMMA = YES;
331 | CLANG_WARN_CONSTANT_CONVERSION = YES;
332 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
334 | CLANG_WARN_EMPTY_BODY = YES;
335 | CLANG_WARN_ENUM_CONVERSION = YES;
336 | CLANG_WARN_INFINITE_RECURSION = YES;
337 | CLANG_WARN_INT_CONVERSION = YES;
338 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
339 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
340 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
342 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
343 | CLANG_WARN_STRICT_PROTOTYPES = YES;
344 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
345 | CLANG_WARN_UNREACHABLE_CODE = YES;
346 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
347 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
348 | COPY_PHASE_STRIP = NO;
349 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
350 | ENABLE_NS_ASSERTIONS = NO;
351 | ENABLE_STRICT_OBJC_MSGSEND = YES;
352 | GCC_C_LANGUAGE_STANDARD = gnu99;
353 | GCC_NO_COMMON_BLOCKS = YES;
354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
356 | GCC_WARN_UNDECLARED_SELECTOR = YES;
357 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
358 | GCC_WARN_UNUSED_FUNCTION = YES;
359 | GCC_WARN_UNUSED_VARIABLE = YES;
360 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
361 | MTL_ENABLE_DEBUG_INFO = NO;
362 | SDKROOT = iphoneos;
363 | TARGETED_DEVICE_FAMILY = "1,2";
364 | VALIDATE_PRODUCT = YES;
365 | };
366 | name = Profile;
367 | };
368 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
369 | isa = XCBuildConfiguration;
370 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
371 | buildSettings = {
372 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
373 | CLANG_ENABLE_MODULES = YES;
374 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
375 | DEVELOPMENT_TEAM = YOUR_TEAM_ID;
376 | ENABLE_BITCODE = NO;
377 | FRAMEWORK_SEARCH_PATHS = (
378 | "$(inherited)",
379 | "$(PROJECT_DIR)/Flutter",
380 | );
381 | INFOPLIST_FILE = Runner/Info.plist;
382 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
383 | LIBRARY_SEARCH_PATHS = (
384 | "$(inherited)",
385 | "$(PROJECT_DIR)/Flutter",
386 | );
387 | PRODUCT_BUNDLE_IDENTIFIER = com.kineapps.flutterArchiveExample;
388 | PRODUCT_NAME = "$(TARGET_NAME)";
389 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
390 | SWIFT_VERSION = 5.0;
391 | VERSIONING_SYSTEM = "apple-generic";
392 | };
393 | name = Profile;
394 | };
395 | 97C147031CF9000F007C117D /* Debug */ = {
396 | isa = XCBuildConfiguration;
397 | baseConfigurationReference = 6C8F778387C8B87CADE0DDD9 /* Pods-Runner.debug.xcconfig */;
398 | buildSettings = {
399 | ALWAYS_SEARCH_USER_PATHS = NO;
400 | CLANG_ANALYZER_NONNULL = YES;
401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
402 | CLANG_CXX_LIBRARY = "libc++";
403 | CLANG_ENABLE_MODULES = YES;
404 | CLANG_ENABLE_OBJC_ARC = YES;
405 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
406 | CLANG_WARN_BOOL_CONVERSION = YES;
407 | CLANG_WARN_COMMA = YES;
408 | CLANG_WARN_CONSTANT_CONVERSION = YES;
409 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
410 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
411 | CLANG_WARN_EMPTY_BODY = YES;
412 | CLANG_WARN_ENUM_CONVERSION = YES;
413 | CLANG_WARN_INFINITE_RECURSION = YES;
414 | CLANG_WARN_INT_CONVERSION = YES;
415 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
416 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
417 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
419 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
420 | CLANG_WARN_STRICT_PROTOTYPES = YES;
421 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
422 | CLANG_WARN_UNREACHABLE_CODE = YES;
423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
424 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
425 | COPY_PHASE_STRIP = NO;
426 | DEBUG_INFORMATION_FORMAT = dwarf;
427 | ENABLE_STRICT_OBJC_MSGSEND = YES;
428 | ENABLE_TESTABILITY = YES;
429 | GCC_C_LANGUAGE_STANDARD = gnu99;
430 | GCC_DYNAMIC_NO_PIC = NO;
431 | GCC_NO_COMMON_BLOCKS = YES;
432 | GCC_OPTIMIZATION_LEVEL = 0;
433 | GCC_PREPROCESSOR_DEFINITIONS = (
434 | "DEBUG=1",
435 | "$(inherited)",
436 | );
437 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
438 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
439 | GCC_WARN_UNDECLARED_SELECTOR = YES;
440 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
441 | GCC_WARN_UNUSED_FUNCTION = YES;
442 | GCC_WARN_UNUSED_VARIABLE = YES;
443 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
444 | MTL_ENABLE_DEBUG_INFO = YES;
445 | ONLY_ACTIVE_ARCH = YES;
446 | SDKROOT = iphoneos;
447 | TARGETED_DEVICE_FAMILY = "1,2";
448 | };
449 | name = Debug;
450 | };
451 | 97C147041CF9000F007C117D /* Release */ = {
452 | isa = XCBuildConfiguration;
453 | baseConfigurationReference = CE6E4F333B1E1EEE26EB0103 /* Pods-Runner.release.xcconfig */;
454 | buildSettings = {
455 | ALWAYS_SEARCH_USER_PATHS = NO;
456 | CLANG_ANALYZER_NONNULL = YES;
457 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
458 | CLANG_CXX_LIBRARY = "libc++";
459 | CLANG_ENABLE_MODULES = YES;
460 | CLANG_ENABLE_OBJC_ARC = YES;
461 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
462 | CLANG_WARN_BOOL_CONVERSION = YES;
463 | CLANG_WARN_COMMA = YES;
464 | CLANG_WARN_CONSTANT_CONVERSION = YES;
465 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
466 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
467 | CLANG_WARN_EMPTY_BODY = YES;
468 | CLANG_WARN_ENUM_CONVERSION = YES;
469 | CLANG_WARN_INFINITE_RECURSION = YES;
470 | CLANG_WARN_INT_CONVERSION = YES;
471 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
472 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
473 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
474 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
475 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
476 | CLANG_WARN_STRICT_PROTOTYPES = YES;
477 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
478 | CLANG_WARN_UNREACHABLE_CODE = YES;
479 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
480 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
481 | COPY_PHASE_STRIP = NO;
482 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
483 | ENABLE_NS_ASSERTIONS = NO;
484 | ENABLE_STRICT_OBJC_MSGSEND = YES;
485 | GCC_C_LANGUAGE_STANDARD = gnu99;
486 | GCC_NO_COMMON_BLOCKS = YES;
487 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
488 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
489 | GCC_WARN_UNDECLARED_SELECTOR = YES;
490 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
491 | GCC_WARN_UNUSED_FUNCTION = YES;
492 | GCC_WARN_UNUSED_VARIABLE = YES;
493 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
494 | MTL_ENABLE_DEBUG_INFO = NO;
495 | SDKROOT = iphoneos;
496 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
497 | TARGETED_DEVICE_FAMILY = "1,2";
498 | VALIDATE_PRODUCT = YES;
499 | };
500 | name = Release;
501 | };
502 | 97C147061CF9000F007C117D /* Debug */ = {
503 | isa = XCBuildConfiguration;
504 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
505 | buildSettings = {
506 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
507 | CLANG_ENABLE_MODULES = YES;
508 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
509 | DEVELOPMENT_TEAM = YOUR_TEAM_ID;
510 | ENABLE_BITCODE = NO;
511 | FRAMEWORK_SEARCH_PATHS = (
512 | "$(inherited)",
513 | "$(PROJECT_DIR)/Flutter",
514 | );
515 | INFOPLIST_FILE = Runner/Info.plist;
516 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
517 | LIBRARY_SEARCH_PATHS = (
518 | "$(inherited)",
519 | "$(PROJECT_DIR)/Flutter",
520 | );
521 | PRODUCT_BUNDLE_IDENTIFIER = com.kineapps.flutterArchiveExample;
522 | PRODUCT_NAME = "$(TARGET_NAME)";
523 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
524 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
525 | SWIFT_VERSION = 5.0;
526 | VERSIONING_SYSTEM = "apple-generic";
527 | };
528 | name = Debug;
529 | };
530 | 97C147071CF9000F007C117D /* Release */ = {
531 | isa = XCBuildConfiguration;
532 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
533 | buildSettings = {
534 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
535 | CLANG_ENABLE_MODULES = YES;
536 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
537 | DEVELOPMENT_TEAM = YOUR_TEAM_ID;
538 | ENABLE_BITCODE = NO;
539 | FRAMEWORK_SEARCH_PATHS = (
540 | "$(inherited)",
541 | "$(PROJECT_DIR)/Flutter",
542 | );
543 | INFOPLIST_FILE = Runner/Info.plist;
544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
545 | LIBRARY_SEARCH_PATHS = (
546 | "$(inherited)",
547 | "$(PROJECT_DIR)/Flutter",
548 | );
549 | PRODUCT_BUNDLE_IDENTIFIER = com.kineapps.flutterArchiveExample;
550 | PRODUCT_NAME = "$(TARGET_NAME)";
551 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
552 | SWIFT_VERSION = 5.0;
553 | VERSIONING_SYSTEM = "apple-generic";
554 | };
555 | name = Release;
556 | };
557 | /* End XCBuildConfiguration section */
558 |
559 | /* Begin XCConfigurationList section */
560 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
561 | isa = XCConfigurationList;
562 | buildConfigurations = (
563 | 97C147031CF9000F007C117D /* Debug */,
564 | 97C147041CF9000F007C117D /* Release */,
565 | 249021D3217E4FDB00AE95B9 /* Profile */,
566 | );
567 | defaultConfigurationIsVisible = 0;
568 | defaultConfigurationName = Release;
569 | };
570 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
571 | isa = XCConfigurationList;
572 | buildConfigurations = (
573 | 97C147061CF9000F007C117D /* Debug */,
574 | 97C147071CF9000F007C117D /* Release */,
575 | 249021D4217E4FDB00AE95B9 /* Profile */,
576 | );
577 | defaultConfigurationIsVisible = 0;
578 | defaultConfigurationName = Release;
579 | };
580 | /* End XCConfigurationList section */
581 | };
582 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
583 | }
584 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXAggregateTarget section */
10 | 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
11 | isa = PBXAggregateTarget;
12 | buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
13 | buildPhases = (
14 | 33CC111E2044C6BF0003C045 /* ShellScript */,
15 | );
16 | dependencies = (
17 | );
18 | name = "Flutter Assemble";
19 | productName = FLX;
20 | };
21 | /* End PBXAggregateTarget section */
22 |
23 | /* Begin PBXBuildFile section */
24 | 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
25 | 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
26 | 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
27 | 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
28 | 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
29 | 63BDF32641D5531E2AC85C98 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 934DCDBF1E617308CA051283 /* Pods_Runner.framework */; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXContainerItemProxy section */
33 | 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = 33CC111A2044C6BA0003C045;
38 | remoteInfo = FLX;
39 | };
40 | /* End PBXContainerItemProxy section */
41 |
42 | /* Begin PBXCopyFilesBuildPhase section */
43 | 33CC110E2044A8840003C045 /* Bundle Framework */ = {
44 | isa = PBXCopyFilesBuildPhase;
45 | buildActionMask = 2147483647;
46 | dstPath = "";
47 | dstSubfolderSpec = 10;
48 | files = (
49 | );
50 | name = "Bundle Framework";
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | /* End PBXCopyFilesBuildPhase section */
54 |
55 | /* Begin PBXFileReference section */
56 | 1ECEF6E2F16647E08B5C49B0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
57 | 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
58 | 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
59 | 33CC10ED2044A3C60003C045 /* flutter_archive_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flutter_archive_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
60 | 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
61 | 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
62 | 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
63 | 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
64 | 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
65 | 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
66 | 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
67 | 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
68 | 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
69 | 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
70 | 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
71 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
72 | 934DCDBF1E617308CA051283 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
73 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
74 | AA118D27FC678A676366C46F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
75 | FD8F94FFCF840A8D20F8C02B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
76 | /* End PBXFileReference section */
77 |
78 | /* Begin PBXFrameworksBuildPhase section */
79 | 33CC10EA2044A3C60003C045 /* Frameworks */ = {
80 | isa = PBXFrameworksBuildPhase;
81 | buildActionMask = 2147483647;
82 | files = (
83 | 63BDF32641D5531E2AC85C98 /* Pods_Runner.framework in Frameworks */,
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 119A99D3FFEE91AEDAE6CDFE /* Pods */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 1ECEF6E2F16647E08B5C49B0 /* Pods-Runner.debug.xcconfig */,
94 | AA118D27FC678A676366C46F /* Pods-Runner.release.xcconfig */,
95 | FD8F94FFCF840A8D20F8C02B /* Pods-Runner.profile.xcconfig */,
96 | );
97 | name = Pods;
98 | path = Pods;
99 | sourceTree = "";
100 | };
101 | 33BA886A226E78AF003329D5 /* Configs */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
105 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
106 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
107 | 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
108 | );
109 | path = Configs;
110 | sourceTree = "";
111 | };
112 | 33CC10E42044A3C60003C045 = {
113 | isa = PBXGroup;
114 | children = (
115 | 33FAB671232836740065AC1E /* Runner */,
116 | 33CEB47122A05771004F2AC0 /* Flutter */,
117 | 33CC10EE2044A3C60003C045 /* Products */,
118 | D73912EC22F37F3D000D13A0 /* Frameworks */,
119 | 119A99D3FFEE91AEDAE6CDFE /* Pods */,
120 | );
121 | sourceTree = "";
122 | };
123 | 33CC10EE2044A3C60003C045 /* Products */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 33CC10ED2044A3C60003C045 /* flutter_archive_example.app */,
127 | );
128 | name = Products;
129 | sourceTree = "";
130 | };
131 | 33CC11242044D66E0003C045 /* Resources */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 33CC10F22044A3C60003C045 /* Assets.xcassets */,
135 | 33CC10F42044A3C60003C045 /* MainMenu.xib */,
136 | 33CC10F72044A3C60003C045 /* Info.plist */,
137 | );
138 | name = Resources;
139 | path = ..;
140 | sourceTree = "";
141 | };
142 | 33CEB47122A05771004F2AC0 /* Flutter */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
146 | 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
147 | 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
148 | 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
149 | );
150 | path = Flutter;
151 | sourceTree = "";
152 | };
153 | 33FAB671232836740065AC1E /* Runner */ = {
154 | isa = PBXGroup;
155 | children = (
156 | 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
157 | 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
158 | 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
159 | 33E51914231749380026EE4D /* Release.entitlements */,
160 | 33CC11242044D66E0003C045 /* Resources */,
161 | 33BA886A226E78AF003329D5 /* Configs */,
162 | );
163 | path = Runner;
164 | sourceTree = "";
165 | };
166 | D73912EC22F37F3D000D13A0 /* Frameworks */ = {
167 | isa = PBXGroup;
168 | children = (
169 | 934DCDBF1E617308CA051283 /* Pods_Runner.framework */,
170 | );
171 | name = Frameworks;
172 | sourceTree = "";
173 | };
174 | /* End PBXGroup section */
175 |
176 | /* Begin PBXNativeTarget section */
177 | 33CC10EC2044A3C60003C045 /* Runner */ = {
178 | isa = PBXNativeTarget;
179 | buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
180 | buildPhases = (
181 | FC41AE4F95FDD64C1B1364BB /* [CP] Check Pods Manifest.lock */,
182 | 33CC10E92044A3C60003C045 /* Sources */,
183 | 33CC10EA2044A3C60003C045 /* Frameworks */,
184 | 33CC10EB2044A3C60003C045 /* Resources */,
185 | 33CC110E2044A8840003C045 /* Bundle Framework */,
186 | 3399D490228B24CF009A79C7 /* ShellScript */,
187 | 062BABA8F06F9299CDFDF8C5 /* [CP] Embed Pods Frameworks */,
188 | );
189 | buildRules = (
190 | );
191 | dependencies = (
192 | 33CC11202044C79F0003C045 /* PBXTargetDependency */,
193 | );
194 | name = Runner;
195 | productName = Runner;
196 | productReference = 33CC10ED2044A3C60003C045 /* flutter_archive_example.app */;
197 | productType = "com.apple.product-type.application";
198 | };
199 | /* End PBXNativeTarget section */
200 |
201 | /* Begin PBXProject section */
202 | 33CC10E52044A3C60003C045 /* Project object */ = {
203 | isa = PBXProject;
204 | attributes = {
205 | LastSwiftUpdateCheck = 0920;
206 | LastUpgradeCheck = 1430;
207 | ORGANIZATIONNAME = "The Flutter Authors";
208 | TargetAttributes = {
209 | 33CC10EC2044A3C60003C045 = {
210 | CreatedOnToolsVersion = 9.2;
211 | LastSwiftMigration = 1100;
212 | ProvisioningStyle = Automatic;
213 | SystemCapabilities = {
214 | com.apple.Sandbox = {
215 | enabled = 1;
216 | };
217 | };
218 | };
219 | 33CC111A2044C6BA0003C045 = {
220 | CreatedOnToolsVersion = 9.2;
221 | ProvisioningStyle = Manual;
222 | };
223 | };
224 | };
225 | buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
226 | compatibilityVersion = "Xcode 8.0";
227 | developmentRegion = en;
228 | hasScannedForEncodings = 0;
229 | knownRegions = (
230 | en,
231 | Base,
232 | );
233 | mainGroup = 33CC10E42044A3C60003C045;
234 | productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
235 | projectDirPath = "";
236 | projectRoot = "";
237 | targets = (
238 | 33CC10EC2044A3C60003C045 /* Runner */,
239 | 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
240 | );
241 | };
242 | /* End PBXProject section */
243 |
244 | /* Begin PBXResourcesBuildPhase section */
245 | 33CC10EB2044A3C60003C045 /* Resources */ = {
246 | isa = PBXResourcesBuildPhase;
247 | buildActionMask = 2147483647;
248 | files = (
249 | 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
250 | 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
251 | );
252 | runOnlyForDeploymentPostprocessing = 0;
253 | };
254 | /* End PBXResourcesBuildPhase section */
255 |
256 | /* Begin PBXShellScriptBuildPhase section */
257 | 062BABA8F06F9299CDFDF8C5 /* [CP] Embed Pods Frameworks */ = {
258 | isa = PBXShellScriptBuildPhase;
259 | buildActionMask = 2147483647;
260 | files = (
261 | );
262 | inputFileListPaths = (
263 | );
264 | name = "[CP] Embed Pods Frameworks";
265 | outputFileListPaths = (
266 | );
267 | runOnlyForDeploymentPostprocessing = 0;
268 | shellPath = /bin/sh;
269 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
270 | showEnvVarsInLog = 0;
271 | };
272 | 3399D490228B24CF009A79C7 /* ShellScript */ = {
273 | isa = PBXShellScriptBuildPhase;
274 | alwaysOutOfDate = 1;
275 | buildActionMask = 2147483647;
276 | files = (
277 | );
278 | inputFileListPaths = (
279 | );
280 | inputPaths = (
281 | );
282 | outputFileListPaths = (
283 | );
284 | outputPaths = (
285 | );
286 | runOnlyForDeploymentPostprocessing = 0;
287 | shellPath = /bin/sh;
288 | shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
289 | };
290 | 33CC111E2044C6BF0003C045 /* ShellScript */ = {
291 | isa = PBXShellScriptBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | );
295 | inputFileListPaths = (
296 | Flutter/ephemeral/FlutterInputs.xcfilelist,
297 | );
298 | inputPaths = (
299 | Flutter/ephemeral/tripwire,
300 | );
301 | outputFileListPaths = (
302 | Flutter/ephemeral/FlutterOutputs.xcfilelist,
303 | );
304 | outputPaths = (
305 | );
306 | runOnlyForDeploymentPostprocessing = 0;
307 | shellPath = /bin/sh;
308 | shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
309 | };
310 | FC41AE4F95FDD64C1B1364BB /* [CP] Check Pods Manifest.lock */ = {
311 | isa = PBXShellScriptBuildPhase;
312 | buildActionMask = 2147483647;
313 | files = (
314 | );
315 | inputFileListPaths = (
316 | );
317 | inputPaths = (
318 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
319 | "${PODS_ROOT}/Manifest.lock",
320 | );
321 | name = "[CP] Check Pods Manifest.lock";
322 | outputFileListPaths = (
323 | );
324 | outputPaths = (
325 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
326 | );
327 | runOnlyForDeploymentPostprocessing = 0;
328 | shellPath = /bin/sh;
329 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
330 | showEnvVarsInLog = 0;
331 | };
332 | /* End PBXShellScriptBuildPhase section */
333 |
334 | /* Begin PBXSourcesBuildPhase section */
335 | 33CC10E92044A3C60003C045 /* Sources */ = {
336 | isa = PBXSourcesBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
340 | 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
341 | 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
342 | );
343 | runOnlyForDeploymentPostprocessing = 0;
344 | };
345 | /* End PBXSourcesBuildPhase section */
346 |
347 | /* Begin PBXTargetDependency section */
348 | 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
349 | isa = PBXTargetDependency;
350 | target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
351 | targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
352 | };
353 | /* End PBXTargetDependency section */
354 |
355 | /* Begin PBXVariantGroup section */
356 | 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
357 | isa = PBXVariantGroup;
358 | children = (
359 | 33CC10F52044A3C60003C045 /* Base */,
360 | );
361 | name = MainMenu.xib;
362 | path = Runner;
363 | sourceTree = "";
364 | };
365 | /* End PBXVariantGroup section */
366 |
367 | /* Begin XCBuildConfiguration section */
368 | 338D0CE9231458BD00FA5F75 /* Profile */ = {
369 | isa = XCBuildConfiguration;
370 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
371 | buildSettings = {
372 | ALWAYS_SEARCH_USER_PATHS = NO;
373 | CLANG_ANALYZER_NONNULL = YES;
374 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
375 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
376 | CLANG_CXX_LIBRARY = "libc++";
377 | CLANG_ENABLE_MODULES = YES;
378 | CLANG_ENABLE_OBJC_ARC = YES;
379 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
380 | CLANG_WARN_BOOL_CONVERSION = YES;
381 | CLANG_WARN_CONSTANT_CONVERSION = YES;
382 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
383 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
384 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
385 | CLANG_WARN_EMPTY_BODY = YES;
386 | CLANG_WARN_ENUM_CONVERSION = YES;
387 | CLANG_WARN_INFINITE_RECURSION = YES;
388 | CLANG_WARN_INT_CONVERSION = YES;
389 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
390 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
391 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
392 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
393 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
394 | CODE_SIGN_IDENTITY = "-";
395 | COPY_PHASE_STRIP = NO;
396 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
397 | ENABLE_NS_ASSERTIONS = NO;
398 | ENABLE_STRICT_OBJC_MSGSEND = YES;
399 | GCC_C_LANGUAGE_STANDARD = gnu11;
400 | GCC_NO_COMMON_BLOCKS = YES;
401 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
402 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
404 | GCC_WARN_UNUSED_FUNCTION = YES;
405 | GCC_WARN_UNUSED_VARIABLE = YES;
406 | MACOSX_DEPLOYMENT_TARGET = 10.14;
407 | MTL_ENABLE_DEBUG_INFO = NO;
408 | SDKROOT = macosx;
409 | SWIFT_COMPILATION_MODE = wholemodule;
410 | SWIFT_OPTIMIZATION_LEVEL = "-O";
411 | };
412 | name = Profile;
413 | };
414 | 338D0CEA231458BD00FA5F75 /* Profile */ = {
415 | isa = XCBuildConfiguration;
416 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
417 | buildSettings = {
418 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
419 | CLANG_ENABLE_MODULES = YES;
420 | CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
421 | CODE_SIGN_STYLE = Automatic;
422 | COMBINE_HIDPI_IMAGES = YES;
423 | FRAMEWORK_SEARCH_PATHS = (
424 | "$(inherited)",
425 | "$(PROJECT_DIR)/Flutter/ephemeral",
426 | );
427 | INFOPLIST_FILE = Runner/Info.plist;
428 | LD_RUNPATH_SEARCH_PATHS = (
429 | "$(inherited)",
430 | "@executable_path/../Frameworks",
431 | );
432 | PROVISIONING_PROFILE_SPECIFIER = "";
433 | SWIFT_VERSION = 5.0;
434 | };
435 | name = Profile;
436 | };
437 | 338D0CEB231458BD00FA5F75 /* Profile */ = {
438 | isa = XCBuildConfiguration;
439 | buildSettings = {
440 | CODE_SIGN_STYLE = Manual;
441 | PRODUCT_NAME = "$(TARGET_NAME)";
442 | };
443 | name = Profile;
444 | };
445 | 33CC10F92044A3C60003C045 /* Debug */ = {
446 | isa = XCBuildConfiguration;
447 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
448 | buildSettings = {
449 | ALWAYS_SEARCH_USER_PATHS = NO;
450 | CLANG_ANALYZER_NONNULL = YES;
451 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
452 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
453 | CLANG_CXX_LIBRARY = "libc++";
454 | CLANG_ENABLE_MODULES = YES;
455 | CLANG_ENABLE_OBJC_ARC = YES;
456 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
457 | CLANG_WARN_BOOL_CONVERSION = YES;
458 | CLANG_WARN_CONSTANT_CONVERSION = YES;
459 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
460 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
461 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
462 | CLANG_WARN_EMPTY_BODY = YES;
463 | CLANG_WARN_ENUM_CONVERSION = YES;
464 | CLANG_WARN_INFINITE_RECURSION = YES;
465 | CLANG_WARN_INT_CONVERSION = YES;
466 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
467 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
468 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
469 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
470 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
471 | CODE_SIGN_IDENTITY = "-";
472 | COPY_PHASE_STRIP = NO;
473 | DEBUG_INFORMATION_FORMAT = dwarf;
474 | ENABLE_STRICT_OBJC_MSGSEND = YES;
475 | ENABLE_TESTABILITY = YES;
476 | GCC_C_LANGUAGE_STANDARD = gnu11;
477 | GCC_DYNAMIC_NO_PIC = NO;
478 | GCC_NO_COMMON_BLOCKS = YES;
479 | GCC_OPTIMIZATION_LEVEL = 0;
480 | GCC_PREPROCESSOR_DEFINITIONS = (
481 | "DEBUG=1",
482 | "$(inherited)",
483 | );
484 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
485 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
486 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
487 | GCC_WARN_UNUSED_FUNCTION = YES;
488 | GCC_WARN_UNUSED_VARIABLE = YES;
489 | MACOSX_DEPLOYMENT_TARGET = 10.14;
490 | MTL_ENABLE_DEBUG_INFO = YES;
491 | ONLY_ACTIVE_ARCH = YES;
492 | SDKROOT = macosx;
493 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
494 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
495 | };
496 | name = Debug;
497 | };
498 | 33CC10FA2044A3C60003C045 /* Release */ = {
499 | isa = XCBuildConfiguration;
500 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
501 | buildSettings = {
502 | ALWAYS_SEARCH_USER_PATHS = NO;
503 | CLANG_ANALYZER_NONNULL = YES;
504 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
505 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
506 | CLANG_CXX_LIBRARY = "libc++";
507 | CLANG_ENABLE_MODULES = YES;
508 | CLANG_ENABLE_OBJC_ARC = YES;
509 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
510 | CLANG_WARN_BOOL_CONVERSION = YES;
511 | CLANG_WARN_CONSTANT_CONVERSION = YES;
512 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
513 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
514 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
515 | CLANG_WARN_EMPTY_BODY = YES;
516 | CLANG_WARN_ENUM_CONVERSION = YES;
517 | CLANG_WARN_INFINITE_RECURSION = YES;
518 | CLANG_WARN_INT_CONVERSION = YES;
519 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
520 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
521 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
522 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
523 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
524 | CODE_SIGN_IDENTITY = "-";
525 | COPY_PHASE_STRIP = NO;
526 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
527 | ENABLE_NS_ASSERTIONS = NO;
528 | ENABLE_STRICT_OBJC_MSGSEND = YES;
529 | GCC_C_LANGUAGE_STANDARD = gnu11;
530 | GCC_NO_COMMON_BLOCKS = YES;
531 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
532 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
533 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
534 | GCC_WARN_UNUSED_FUNCTION = YES;
535 | GCC_WARN_UNUSED_VARIABLE = YES;
536 | MACOSX_DEPLOYMENT_TARGET = 10.14;
537 | MTL_ENABLE_DEBUG_INFO = NO;
538 | SDKROOT = macosx;
539 | SWIFT_COMPILATION_MODE = wholemodule;
540 | SWIFT_OPTIMIZATION_LEVEL = "-O";
541 | };
542 | name = Release;
543 | };
544 | 33CC10FC2044A3C60003C045 /* Debug */ = {
545 | isa = XCBuildConfiguration;
546 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
547 | buildSettings = {
548 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
549 | CLANG_ENABLE_MODULES = YES;
550 | CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
551 | CODE_SIGN_STYLE = Automatic;
552 | COMBINE_HIDPI_IMAGES = YES;
553 | FRAMEWORK_SEARCH_PATHS = (
554 | "$(inherited)",
555 | "$(PROJECT_DIR)/Flutter/ephemeral",
556 | );
557 | INFOPLIST_FILE = Runner/Info.plist;
558 | LD_RUNPATH_SEARCH_PATHS = (
559 | "$(inherited)",
560 | "@executable_path/../Frameworks",
561 | );
562 | PROVISIONING_PROFILE_SPECIFIER = "";
563 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
564 | SWIFT_VERSION = 5.0;
565 | };
566 | name = Debug;
567 | };
568 | 33CC10FD2044A3C60003C045 /* Release */ = {
569 | isa = XCBuildConfiguration;
570 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
571 | buildSettings = {
572 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
573 | CLANG_ENABLE_MODULES = YES;
574 | CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
575 | CODE_SIGN_STYLE = Automatic;
576 | COMBINE_HIDPI_IMAGES = YES;
577 | FRAMEWORK_SEARCH_PATHS = (
578 | "$(inherited)",
579 | "$(PROJECT_DIR)/Flutter/ephemeral",
580 | );
581 | INFOPLIST_FILE = Runner/Info.plist;
582 | LD_RUNPATH_SEARCH_PATHS = (
583 | "$(inherited)",
584 | "@executable_path/../Frameworks",
585 | );
586 | PROVISIONING_PROFILE_SPECIFIER = "";
587 | SWIFT_VERSION = 5.0;
588 | };
589 | name = Release;
590 | };
591 | 33CC111C2044C6BA0003C045 /* Debug */ = {
592 | isa = XCBuildConfiguration;
593 | buildSettings = {
594 | CODE_SIGN_STYLE = Manual;
595 | PRODUCT_NAME = "$(TARGET_NAME)";
596 | };
597 | name = Debug;
598 | };
599 | 33CC111D2044C6BA0003C045 /* Release */ = {
600 | isa = XCBuildConfiguration;
601 | buildSettings = {
602 | CODE_SIGN_STYLE = Automatic;
603 | PRODUCT_NAME = "$(TARGET_NAME)";
604 | };
605 | name = Release;
606 | };
607 | /* End XCBuildConfiguration section */
608 |
609 | /* Begin XCConfigurationList section */
610 | 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
611 | isa = XCConfigurationList;
612 | buildConfigurations = (
613 | 33CC10F92044A3C60003C045 /* Debug */,
614 | 33CC10FA2044A3C60003C045 /* Release */,
615 | 338D0CE9231458BD00FA5F75 /* Profile */,
616 | );
617 | defaultConfigurationIsVisible = 0;
618 | defaultConfigurationName = Release;
619 | };
620 | 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
621 | isa = XCConfigurationList;
622 | buildConfigurations = (
623 | 33CC10FC2044A3C60003C045 /* Debug */,
624 | 33CC10FD2044A3C60003C045 /* Release */,
625 | 338D0CEA231458BD00FA5F75 /* Profile */,
626 | );
627 | defaultConfigurationIsVisible = 0;
628 | defaultConfigurationName = Release;
629 | };
630 | 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
631 | isa = XCConfigurationList;
632 | buildConfigurations = (
633 | 33CC111C2044C6BA0003C045 /* Debug */,
634 | 33CC111D2044C6BA0003C045 /* Release */,
635 | 338D0CEB231458BD00FA5F75 /* Profile */,
636 | );
637 | defaultConfigurationIsVisible = 0;
638 | defaultConfigurationName = Release;
639 | };
640 | /* End XCConfigurationList section */
641 | };
642 | rootObject = 33CC10E52044A3C60003C045 /* Project object */;
643 | }
644 |
--------------------------------------------------------------------------------