Flutter多平台打包发布
Flutter多平台打包发布 Android ios Windows macos web linux
本文档将详细讲解如何使用 Flutter 和工具打包发布多平台应用,包括 Android、iOS、Windows、macOS、Web 和 Linux。并通过 flutter_distributor
工具来实现高级打包功能。
准备工作
安装 Flutter SDK
下载并安装 Flutter SDK:Flutter 官网
配置环境变量:
export PATH="$PATH:/path-to-flutter/bin"
检查环境配置
flutter doctor
安装
flutter_distributor
工具安装 flutter_distributor
dart pub global activate flutter_distributor
项目初始化
创建一个新的 Flutter 项目或打开现有项目:
flutter create my_app cd my_app
Android 打包
使用 Flutter 命令打包 APK
打包 APK 文件并分离 ABI:
flutter build apk --release --split-per-abi
输出的打包文件位于
build/app/outputs/flutter-apk/
。
发布 AAB 文件
如果需要发布 AAB 文件到 Google Play:
flutter build appbundle --release
iOS 打包
打包 iOS 应用
不签名的 Release 构建:
flutter build ios --release --no-codesign
生成 IPA 文件
进入构建输出目录:
cd build/ios/iphoneos/
创建 Payload 文件夹并移动应用:
mkdir Payload cp -r Runner.app Payload/
打包成 IPA 文件:
zip -r Runner.ipa Payload
Web 打包
打包 Web 应用
flutter build web --release
打包结果
- 构建输出位于
build/web
目录中。 - 可以将其部署到任何支持静态文件托管的服务(如 Nginx、Firebase Hosting)。
- 构建输出位于
Windows 打包
打包 Windows 应用
使用 Flutter 构建:
flutter build windows
构建结果位于
build/windows/runner/Release
目录。
高级打包工具
- 使用
flutter_distributor
打包为 EXE 或 MSIX(详细见 高级功能)。
- 使用
macOS 打包
打包 macOS 应用
flutter build macos
构建输出
- 构建结果位于
build/macos/Build/Products/Release
目录。
- 构建结果位于
高级打包工具
- 使用
flutter_distributor
打包为 DMG(详细见 高级功能)。
- 使用
Linux 打包
打包 Linux 应用
flutter build linux
构建输出
- 构建结果位于
build/linux/x64/release/bundle
目录。
- 构建结果位于
高级打包工具
- 使用
flutter_distributor
打包为 DEB、RPM 或 AppImage(详细见 高级功能)。
- 使用
flutter_distributor
高级功能:flutter_distributor
是一个强大的工具,支持跨平台发布和高级打包选项。
安装
确保 flutter_distributor
已安装:
dart pub global activate flutter_distributor
配置文件
为高级打包配置所需的文件:
macOS:
如果打包 DMG 安装包:
macos/packaging/dmg/make_config.yaml
title: 应用名称 contents: - x: 448 y: 244 type: link path: "/Applications" - x: 192 y: 244 type: file path: 应用名称.app
如果打包 PKG 安装包:
macos/packaging/pkg/make_config.yaml
install-path: /Applications #sign-identity: <your-sign-identity>
distribute_options.yaml
output: dist/
Windows:
如果打包 exe 安装包:
windows/packaging/exe/inno_setup.sas
[Setup] AppId={{APP_ID}} AppVersion={{APP_VERSION}} AppName={{DISPLAY_NAME}} AppPublisher={{PUBLISHER_NAME}} AppPublisherURL={{PUBLISHER_URL}} AppSupportURL={{PUBLISHER_URL}} AppUpdatesURL={{PUBLISHER_URL}} DefaultDirName={{INSTALL_DIR_NAME}} DisableProgramGroupPage=yes OutputDir=. OutputBaseFilename={{OUTPUT_BASE_FILENAME}} Compression=lzma SolidCompression=yes SetupIconFile={{SETUP_ICON_FILE}} WizardStyle=modern PrivilegesRequired={{PRIVILEGES_REQUIRED}} ArchitecturesAllowed=x64 ArchitecturesInstallIn64BitMode=x64 CloseApplications=force [Languages] {% for locale in LOCALES %} {% if locale == 'en' %}Name: "english"; MessagesFile: "compiler:Default.isl"{% endif %} {% if locale == 'hy' %}Name: "armenian"; MessagesFile: "compiler:Languages\\Armenian.isl"{% endif %} {% if locale == 'bg' %}Name: "bulgarian"; MessagesFile: "compiler:Languages\\Bulgarian.isl"{% endif %} {% if locale == 'ca' %}Name: "catalan"; MessagesFile: "compiler:Languages\\Catalan.isl"{% endif %} {% if locale == 'zh' %}Name: "chinesesimplified"; MessagesFile: "compiler:Languages\\ChineseSimplified.isl"{% endif %} {% if locale == 'co' %}Name: "corsican"; MessagesFile: "compiler:Languages\\Corsican.isl"{% endif %} {% if locale == 'cs' %}Name: "czech"; MessagesFile: "compiler:Languages\\Czech.isl"{% endif %} {% if locale == 'da' %}Name: "danish"; MessagesFile: "compiler:Languages\\Danish.isl"{% endif %} {% if locale == 'nl' %}Name: "dutch"; MessagesFile: "compiler:Languages\\Dutch.isl"{% endif %} {% if locale == 'fi' %}Name: "finnish"; MessagesFile: "compiler:Languages\\Finnish.isl"{% endif %} {% if locale == 'fr' %}Name: "french"; MessagesFile: "compiler:Languages\\French.isl"{% endif %} {% if locale == 'de' %}Name: "german"; MessagesFile: "compiler:Languages\\German.isl"{% endif %} {% if locale == 'he' %}Name: "hebrew"; MessagesFile: "compiler:Languages\\Hebrew.isl"{% endif %} {% if locale == 'is' %}Name: "icelandic"; MessagesFile: "compiler:Languages\\Icelandic.isl"{% endif %} {% if locale == 'it' %}Name: "italian"; MessagesFile: "compiler:Languages\\Italian.isl"{% endif %} {% if locale == 'ja' %}Name: "japanese"; MessagesFile: "compiler:Languages\\Japanese.isl"{% endif %} {% if locale == 'no' %}Name: "norwegian"; MessagesFile: "compiler:Languages\\Norwegian.isl"{% endif %} {% if locale == 'pl' %}Name: "polish"; MessagesFile: "compiler:Languages\\Polish.isl"{% endif %} {% if locale == 'pt' %}Name: "portuguese"; MessagesFile: "compiler:Languages\\Portuguese.isl"{% endif %} {% if locale == 'ru' %}Name: "russian"; MessagesFile: "compiler:Languages\\Russian.isl"{% endif %} {% if locale == 'sk' %}Name: "slovak"; MessagesFile: "compiler:Languages\\Slovak.isl"{% endif %} {% if locale == 'sl' %}Name: "slovenian"; MessagesFile: "compiler:Languages\\Slovenian.isl"{% endif %} {% if locale == 'es' %}Name: "spanish"; MessagesFile: "compiler:Languages\\Spanish.isl"{% endif %} {% if locale == 'tr' %}Name: "turkish"; MessagesFile: "compiler:Languages\\Turkish.isl"{% endif %} {% if locale == 'uk' %}Name: "ukrainian"; MessagesFile: "compiler:Languages\\Ukrainian.isl"{% endif %} {% endfor %} [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: {% if CREATE_DESKTOP_ICON != true %}unchecked{% else %}checkedonce{% endif %} Name: "launchAtStartup"; Description: "{cm:AutoStartProgram,{{DISPLAY_NAME}}}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: {% if LAUNCH_AT_STARTUP != true %}unchecked{% else %}checkedonce{% endif %} [Files] Source: "{{SOURCE_DIR}}\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] Name: "{autoprograms}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}" Name: "{autodesktop}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"; Tasks: desktopicon Name: "{userstartup}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"; WorkingDir: "{app}"; Tasks: launchAtStartup [Run] Filename: "{app}\\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: {% if PRIVILEGES_REQUIRED == 'admin' %}runascurrentuser{% endif %} nowait postinstall skipifsilent [Code] function InitializeSetup(): Boolean; var ResultCode: Integer; begin Exec('taskkill', '/F /IM 应用名称.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) Result := True; end;
windows/packaging/exe/make_config.yaml
app_id: 6L913538-42B1-4596-G479-BJ779F21A65D publisher: 应用名称 publisher_url: https://github.com/aaa/aaa display_name: 应用名称 executable_name: 应用名称.exe output_base_file_name: 应用名称.exe create_desktop_icon: true install_dir_name: "{autopf64}\\应用名称" setup_icon_file: ..\..\windows\runner\resources\app_icon.ico locales: - ar - en - fa - ru - pt - tr script_template: inno_setup.sas
如果打包 msix
windows/packaging/msix/make_config.yaml
display_name: 应用名称 publisher_display_name: 应用名称 identity_name: 应用名称.appioi msix_version: 2.5.7.0 logo_path: windows\runner\resources\app_icon.ico capabilities: internetClient, internetClientServer, privateNetworkClientServer languages: en-us, zh-cn, zh-tw, tr-tr,fa-ir,ru-ru,pt-br,es-es protocol_activation: 应用名称 execution_alias: 应用名称 certificate_path: windows\sign.pfx certificate_password: publisher: CN=8CB43675-F44B-4AA5-9372-E8727781BDC4 install_certificate: "false" enable_at_startup: "true" startup_task: parameters: --autostart
Linux:
linux/packaging/appimage
有两个文件
linux/packaging/appimage/AppRun
#!/bin/bash cd "$(dirname "$0")" export LD_LIBRARY_PATH=usr/lib # Usage info show_help() { cat << EOF Usage: ${0##*/} ... start app or app, when no parameter is given, app is executed. -v show version EOF } show_version() { printf "app version " jq .version <./data/flutter_assets/version.json } # Initialize variables: service=0 #declare -i service OPTIND=1 # Resetting OPTIND is necessary if getopts was used previously in the script. # It is a good idea to make OPTIND local if you process options in a function. # if no arg is provided, execute app if [[ $# == 0 ]];then exec ./app else # processing arguments case $1 in appCli) exec ./appCli ${@:3} exit 0 ;; h) show_help exit 0 ;; v) show_version exit 0 ;; *) show_help >&2 exit 1 ;; esac fi
linux/packaging/appimage/make_config.yaml
display_name: App名称 icon: ./assets/images/source/ic_launcher_border.png keywords: - Hi generic_name: App名称 actions: - name: Start label: start arguments: - --start - name: Stop label: stop arguments: - --stop categories: - Network startup_notify: true app_run_file: AppRun # You can specify the shared libraries that you want to bundle with your app # # flutter_distributor automatically detects the shared libraries that your app # depends on, but you can also specify them manually here. # # The following example shows how to bundle the libcurl library with your app. # # include: # - libcurl.so.4 include: []
linux/packaging/deb
文件linux/packaging/deb/make_config.yaml
display_name: Hiddify package_name: hiddify maintainer: name: hiddify email: linux@hiddify.com priority: optional section: x11 installed_size: 6604 essential: false icon: ./assets/images/source/ic_launcher_border.png postinstall_scripts: - echo "Installed Hiddify" postuninstall_scripts: - echo "Surprised Why?" keywords: - Hiddify - Proxy - VPN - V2ray - Nekoray - Xray - Psiphon - OpenVPN generic_name: Hiddify categories: - Network startup_notify: true
linux/packaging/rpm
linux/packaging/rpm/make_config.yaml
display_name: App url: https://github.com/app/app-next/ license: Other packager: App packagerEmail: linux@App.com priority: optional section: x11 installed_size: 6604 essential: false icon: ./assets/images/source/ic_launcher_border.png keywords: - Hi generic_name: App group: Applications/Internet startup_notify: true
命令示例
打包 macOS (DMG 和 PKG)
flutter_distributor package --flutter-build-args=verbose --platform macos --targets dmg,pkg
打包 Windows (EXE 和 MSIX)
flutter_distributor package --flutter-build-args=verbose --platform windows --targets exe,msix
打包 Linux (DEB、RPM 和 AppImage)
flutter_distributor package --flutter-build-args=verbose --platform linux --targets deb,rpm,appimage
常见问题
1. 如何调试打包错误?
使用 -v
查看详细日志:
flutter build apk -v
flutter_distributor
不工作?
2. 确保 dart
的全局路径已配置:
export PATH="$PATH:$HOME/.pub-cache/bin"
3. 打包 Web 访问问题?
检查服务器配置是否正确,确保支持 HTML5 路由。
结语
通过本文档,您可以轻松完成 Flutter 多平台应用的打包与发布。高级用户还可以利用 flutter_distributor
工具实现更复杂的打包需求。如有问题,请参考 Flutter 官方文档 或加入社区寻求帮助。
- 准备工作
- Android 打包
- iOS 打包
- Web 打包
- Windows 打包
- macOS 打包
- Linux 打包
- 高级功能:flutter_distributor
- 安装
- 配置文件
- 命令示例
- 常见问题
- 1. 如何调试打包错误?
- 2. flutter_distributor 不工作?
- 3. 打包 Web 访问问题?
- 结语