资讯详情

资讯详情

纯Flutter项目Android打包全流程解析与避坑指南

1. 项目概述为什么一个纯Flutter项目打包成Android包值得花整整一篇长文来拆解“Flutter 学习之打包——纯Flutter项目生成Android包”这个标题看起来平平无奇甚至有点“教科书目录感”。但如果你真在一线带过团队、做过交付、被线上崩溃和商店拒收折磨过就会明白打包不是开发的终点而是质量验证的第一道生死线。我见过太多团队功能写得飞起一到打包环节就卡住——签名配置错一行APK装不上混淆规则漏一条热更新直接失效targetSdkVersion没对齐上架Google Play被秒拒甚至只是build.gradle里多了一个空格CI流水线就红得刺眼。这不是玄学是Flutter工程化落地中最真实、最密集踩坑的环节。核心关键词“纯Flutter项目”四个字恰恰划出了最关键的边界它不包含原生Android模块比如自定义View、JNI调用、旧Activity嵌入也不混编Java/Kotlin业务逻辑整个App的UI、路由、状态管理、网络请求全部由Dart完成。这意味着打包流程理论上更“干净”但同时也更“脆弱”——所有依赖、资源、构建链路都必须严格遵循Flutter官方工具链的约定任何偏离都会被放大。你不能靠“在Android Studio里点一下Build APK”蒙混过关也不能指望flutter build apk命令自动解决一切。它背后是一整套从Dart AOT编译、Gradle构建、ProGuard/R8混淆、APK签名、ABI适配到最终包体分析的完整工程链条。这篇文章适合三类人第一类是刚学完StatefulWidget、正准备把第一个TodoList Demo发给朋友试用的新手你需要知道哪几步绝对不能跳、哪些报错可以忽略、哪个命令能立刻看到结果第二类是正在从React Native或原生Android转Flutter的中阶开发者你熟悉Gradle和签名体系但需要理解Flutter如何与这套体系耦合比如local.properties里的sdk.dir怎么影响构建、android/app/build.gradle里flutter { source ../.. }这行代码到底在做什么第三类是负责CI/CD搭建或App Store上架的工程同学你需要的是可复现、可审计、可自动化的打包规范比如如何用--split-per-abi生成多个轻量包、为什么--release必须配合--shrink、以及flutter build appbundle和flutter build apk在分发策略上的本质区别。全文不讲“什么是Flutter”不堆砌API文档只聚焦一件事当你敲下flutter build apk --release之后发生了什么每一步谁在干活出错了怎么看日志包大了怎么瘦身上线前该验什么所有内容均来自某跨平台系统交付过程中累计的27次正式打包、147次CI失败排查、3次应用商店拒收后的回溯复盘每一个参数、每一处配置、每一条报错提示都对应着真实场景里的血泪教训。2. 整体设计与思路拆解为什么必须坚持“纯Flutter”路径三种常见误入歧途的打包方式很多开发者第一次打包失败根本原因不是技术问题而是对“纯Flutter项目”的认知偏差。他们下意识地把Flutter当成“另一个UI框架”试图用原生Android开发的老经验去套用结果越走越偏。下面这三种典型做法我在某高校Flutter工作坊和某公司内部培训中反复见过每一次都导致至少半天的无效调试。2.1 误入歧途一绕过Flutter CLI直接在Android Studio里Build APK这是新手最容易犯的错误。看到Android Studio右上角有个绿色三角形Run按钮手一抖就点了。结果呢生成的APK根本打不开或者打开后白屏、闪退。为什么因为Android Studio的Build流程完全忽略了Flutter的核心机制——Dart代码的AOTAhead-of-Time编译。Flutter的Dart代码不是像Java那样编译成字节码再由JVM解释执行而是在构建阶段就被gen_snapshot工具编译成针对目标CPU架构arm64-v8a、armeabi-v7a等的本地机器码然后打包进APK的lib/目录下。Android Studio的默认Build只处理android/app/src/main/java下的Java/Kotlin代码对lib/main.dart里的Dart逻辑视而不见。它生成的APK里没有libflutter.so也没有libapp.so自然无法启动。正确做法永远是所有构建动作必须通过Flutter CLI发起即flutter build apk或flutter build appbundle。这个命令会先调用Dart编译器生成so文件再触发Gradle构建最后将so、资源、清单文件等一并打包。你可以把Flutter CLI看作整个构建流程的“总指挥”而Android Studio只是个“辅助编辑器”。2.2 误入歧途二手动修改android/app/src/main/AndroidManifest.xml却忽略flutter插件的注入逻辑有些开发者为了加推送、改主题色直接去改AndroidManifest.xml比如把application android:themestyle/LaunchTheme改成自定义样式或者在activity里加android:exportedtrue。乍一看没问题但很快会发现App启动时黑屏时间变长或者某些页面导航异常。这是因为Flutter的flutter插件在android/app/build.gradle中声明会在构建时动态向Manifest注入关键配置比如io.flutter.embedding.android.FlutterActivity的声明、meta-data标签指定的初始路由和背景色。如果你手动修改了Manifest又没同步更新这些注入点就相当于“拔掉了心脏起搏器还自己接了根电线”。更隐蔽的问题是flutter插件会根据pubspec.yaml中的flutter.sdk路径自动计算Dart代码的入口位置并生成对应的FlutterApplication子类。你手动改Manifest却没动build.gradle里的flutter { source ../.. }构建时就会找不到Dart入口导致白屏。所以我的实操心得是Manifest的修改必须和flutter插件的配置联动。比如要改启动页主题应该在android/app/src/main/res/values/styles.xml里修改LaunchTheme而不是在Manifest里硬编码要加android:exported必须确认你的minSdkVersion是否≥31Android 12强制要求否则Gradle会报错这时你应该优先升级minSdkVersion而不是强行加属性。2.3 误入歧途三混淆Obfuscation开启后Dart代码崩溃日志完全不可读这是中阶开发者最容易栽跟头的地方。为了减小包体积、防止代码被反编译很多人会开启R8混淆。但在纯Flutter项目中混淆有两个致命陷阱第一R8只混淆Java/Kotlin代码对Dart生成的so文件完全无效——so文件里的符号表是静态链接的混淆不了第二如果你在Dart代码里用了反射比如Type.typeName、dart:mirrors库虽然Flutter官方不推荐混淆后Java层的类名变了Dart反射就找不到对应类直接崩溃。我遇到过一个真实案例某图像处理Demo用json_serializable生成序列化代码其中大量使用Type判断开启R8后所有JSON解析都返回null日志里只有一句NoSuchMethodError根本看不出是反射失败。解决方案很简单纯Flutter项目应关闭R8混淆改用Dart自身的--obfuscate和--split-debug-info。flutter build apk --obfuscate --split-debug-info./symbols这条命令会由Dart编译器在AOT编译阶段对Dart代码进行符号混淆并将原始符号表单独导出到symbols目录。这样生成的APK里so文件是混淆过的但崩溃日志可以通过symbols目录还原既保护了核心逻辑又保留了可调试性。而Gradle里的minifyEnabled true在纯Flutter项目中应该始终设为false除非你明确知道自己在混淆哪些Java桥接代码。这三条误入歧途的本质都是混淆了“Flutter构建”和“Android构建”的责任边界。Flutter CLI是主干Gradle是分支Manifest是接口文档。只有理清这个主次关系后续的所有配置才不会南辕北辙。3. 核心细节解析与实操要点从pubspec.yaml到build.gradle每个文件的关键字段都在干什么打包不是魔法它是一系列配置文件协同工作的结果。我把整个流程拆解成四个核心文件每个文件里只挑出3个最关键、最容易填错的字段告诉你它们的作用、填错的后果以及我踩过的坑。3.1pubspec.yamlDart世界的“宪法”三个字段决定包的基因pubspec.yaml是Flutter项目的元数据中心它不直接参与编译但决定了整个构建的输入源。新手常犯的错误是把它当成“资源清单”随便填结果导致打包时找不到图标、字体或者版本号混乱。version字段1.0.01中的1不是小数点是构建号build number这个字段格式是x.y.zbuild_number比如2.3.142。x.y.z是语义化版本42是每次构建的唯一递增号。很多团队只改前面的2.3.1忘了改后面的42结果上架时商店提示“版本号重复”。更严重的是如果后面跟的是字母或负数flutter build会直接报错Invalid version format。我的实操心得是在CI流水线里用Git提交次数自动生成build_number比如git rev-list --count HEAD这样每次push都能保证唯一性。本地开发时可以用VS Code的pubspec-assist插件一键递增。flutter.icons下的android路径指向的是mipmap目录不是drawable当你运行flutter pub get后Flutter会根据这里配置的路径把assets/icon.png复制到android/app/src/main/res/mipmap-*/下。注意是mipmap不是drawable因为Android Launcher Icon必须放在mipmap目录系统会根据设备密度自动选择最优图标。如果你错误地配置成drawable/icon.png构建时不会报错但生成的APK安装后桌面图标可能模糊、拉伸甚至在某些厂商ROM上显示为默认Android机器人。正确路径应该是android: assets/icon.png然后确保assets/icon.png是512x512的正方形PNGFlutter工具会自动缩放生成各尺寸。flutter.assets下的路径必须是相对pubspec.yaml的路径且不能以/开头比如你想加载assets/images/logo.jpg配置必须是- assets/images/logo.jpg而不是- /assets/images/logo.jpg。多一个/flutter build会静默失败APK里根本没有这个文件运行时rootBundle.loadString(assets/images/logo.jpg)直接抛FileNotFoundError。我踩过这个坑在某模拟项目X中因为IDE自动补全加了斜杠花了两小时查AssetBundle加载失败的原因。现在我的习惯是所有assets路径在VS Code里用CtrlSpace触发自动补全绝不手打。3.2android/app/src/main/AndroidManifest.xmlAndroid世界的“宪法”三个属性决定App能否见光这个文件是Android系统的“门禁卡”填错一个属性App可能根本启动不了或者被系统限制功能。application的android:usesCleartextTraffic属性HTTP请求的生死开关Android 9API 28开始默认禁止明文HTTP流量。如果你的App里有http://api.example.com这样的请求不加这个属性网络请求会直接失败日志里只有Cleartext HTTP traffic to xxx not permitted。正确做法是在开发阶段设为true上线前必须改为false并确保所有后端接口升级为HTTPS。更稳妥的方案是在android/app/src/main/res/xml/network_security_config.xml里配置域名白名单这样既能允许特定HTTP域名比如本地调试用的http://10.0.2.2:8080又不影响全局安全策略。activity的android:exported属性Android 12的强制门禁API 31Android 12起所有带有intent-filter的activity、service、receiver都必须显式声明android:exported。Flutter的主Activity默认有intent-filter用于响应android.intent.action.MAIN和android.intent.category.LAUNCHER所以android:exportedtrue是必须的。填错成falseApp安装后根本不会出现在桌面adb shell pm list packages也查不到。这个属性没有灰色地带非true即false不存在“默认值”。meta-data的io.flutter.embedding.android.SplashScreenDrawable启动页的“画布”这个属性指向一个drawable资源ID比如drawable/launch_background。它定义了App启动时的Native Splash Screen。很多人以为这只是个背景图其实它控制着整个启动流程的视觉连贯性。如果你在这里引用了一个不存在的drawableApp会黑屏几秒后才显示Flutter界面如果drawable里用了vector矢量图某些低版本Android21会崩溃。我的经验是启动页drawable必须用PNG位图尺寸按mipmap标准提供且不要做任何复杂动画。复杂动画应该交给Dart层的SplashScreenWidget实现Native层只负责静态展示。3.3android/app/build.gradle构建引擎的“油门和刹车”三个配置项决定成败这个文件是Gradle构建的“驾驶舱”里面大部分配置是Flutter工具自动生成的但有三个地方必须人工干预。android.defaultConfig下的applicationId包名的“身份证号”这个值必须和你在Google Play Console或华为AppGallery注册的包名完全一致一个字母都不能错。填错的后果是APK能安装但无法连接到已有的Firebase项目、无法接收推送、无法使用Google Sign-In。更隐蔽的问题是如果你之前用com.example.myapp发布过测试版现在想改成com.mycompany.myapp必须在商店后台创建全新应用旧用户无法无缝升级。所以我的建议是在项目初始化时就定死applicationId用公司域名倒序项目名比如com.yourcompany.flutterdemo并在README.md里高亮标注。android.buildTypes.release下的signingConfig签名的“法律效力”signingConfig signingConfigs.release这一行告诉Gradle用哪个密钥对APK签名。密钥配置在android/app/key.properties里。新手常犯的错误是把key.properties文件直接提交到Git导致密钥泄露或者在CI环境里key.properties路径写错构建时报Key store file not found。正确做法是key.properties必须加入.gitignoreCI环境通过环境变量注入密钥内容再用脚本动态生成key.properties。例如在GitHub Actions里用echo ${{ secrets.KEYSTORE_CONTENT }} android/app/key.properties。flutter块下的source路径Dart世界的“寻路GPS”flutter { source ../.. }这行代码告诉Gradle“Dart代码的根目录在哪”。../..是相对于android/app/build.gradle的路径指向项目根目录即pubspec.yaml所在目录。如果你把Flutter模块挪到了子目录比如android/app/src/main/flutter_module就必须改成source ../src/main/flutter_module。填错的后果是Gradle找不到lib/main.dart构建时提示Could not find the Flutter SDK即使你本地flutter doctor一切正常。这个路径是Flutter CLI和Gradle之间的“暗号”必须精确匹配。3.4android/local.properties本地环境的“罗盘”一个路径决定构建能否启航这个文件通常被.gitignore忽略因为它存储的是你本机的SDK路径不同开发者的路径千差万别。sdk.dir属性Android SDK的“绝对坐标”它的值类似sdk.dir /Users/yourname/Library/Android/sdkmacOS或sdk.dir C\:\\Users\\yourname\\AppData\\Local\\Android\\SdkWindows。填错的后果是flutter build apk第一步就失败报错Android sdkdir is not configured或Failed to find Build Tools revision 33.0.0。注意路径里的反斜杠在Windows上要双写\\单写会解析失败。我的实操技巧是不要手打用Android Studio的File Project Structure SDK Location复制路径粘贴后检查斜杠。另外这个路径必须指向完整的Android SDK目录不能只到platform-tools或emulator。这四个文件就像四把钥匙缺一不可。我建议新手在第一次打包前用文本对比工具如VS Code的Compare Files把你的配置和flutter create myapp生成的模板逐行对比重点核对上述12个关键字段。少一个多一个/都可能让你在打包环节卡住一整天。4. 实操过程与核心环节实现从零开始一次成功的flutter build apk --release全流程记录现在我们把所有理论付诸实践。以下是我在一个全新创建的纯Flutter项目flutter create flutter_packaging_demo上从零开始执行flutter build apk --release的完整过程。每一步我都记录了命令、输出、关键日志片段、耗时以及我当时的真实操作意图。这不是理想化的教程而是带着呼吸感的现场实录。4.1 环境准备与首次校验flutter doctor不是摆设是构建前的CT扫描第一步永远是flutter doctor -v。这不是仪式是构建前的全面体检。我执行后得到如下关键信息[✓] Flutter (Channel stable, 3.19.5, on macOS 14.4 23E224 darwin-arm64, locale zh-Hans-CN) • Flutter version 3.19.5 on channel stable • Upstream repository https://github.com/flutter/flutter.git • Framework revision 30625a2e39 (3 weeks ago), 2024-03-22T15:03:15-07:00 • Engine revision 1f1c8967a5 • Dart version 3.3.3 • DevTools version 2.31.1 [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/john/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • ANDROID_HOME /Users/john/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.80-17.0.8b1087.7-11185870) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 15.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15E204a • CocoaPods version 1.14.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2023.2) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.80-17.0.8b1087.7-11185870) [✓] VS Code (version 1.87.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.86.0 • Dart extension version 3.86.0 [✓] Connected device (1 available) • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 14 (API 34) (emulator) [✓] Network resources • All expected network resources are available.提示重点关注Android toolchain部分。Platform android-34表示SDK Platform 34已安装build-tools 34.0.0表示构建工具版本匹配。如果这里显示[!]比如Missing Android SDK Build-Tools 34.0.0就必须先运行sdkmanager build-tools;34.0.0安装否则flutter build必然失败。All Android licenses accepted也很关键如果没接受构建时会卡在License Agreement界面。4.2 配置签名生成密钥库Keystore并安全注入纯Flutter项目打包必须签名否则APK无法安装到真机debug包除外。我用keytool生成一个新密钥库keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key执行后终端会交互式提问Enter keystore password:输入密码我设为flutter123Re-enter new password:再次输入What is your first and last name?输入John Doe随意不重要What is the name of your organizational unit?输入DevWhat is the name of your organization?输入MyCompanyWhat is the name of your City or Locality?输入BeijingWhat is the name of your State or Province?输入BJWhat is the two-letter country code for this unit?输入CNIs CNJohn Doe, OUDev, OMyCompany, LBeijing, STBJ, CCN correct?输入yes生成成功后~/key.jks就是我的密钥库文件。接下来创建android/app/key.propertiesstoreFile/Users/john/key.jks keyAliaskey storeFilePasswordflutter123 keyPasswordflutter123注意storeFile路径必须是绝对路径keyAlias必须和keytool命令里的-alias一致。storeFilePassword和keyPassword是两个独立密码可以相同但概念不同。4.3 修改build.gradle激活签名配置打开android/app/build.gradle找到android {块在buildTypes {内添加release配置android { compileSdkVersion flutter.compileSdkVersion // ... 其他配置 signingConfigs { release { keyAlias keystoreProperties[keyAlias] keyPassword keystoreProperties[keyPassword] storeFile keystoreProperties[storeFile] ? file(keystoreProperties[storeFile]) : null storePassword keystoreProperties[storeFilePassword] } } buildTypes { release { signingConfig signingConfigs.release // 这一行是关键 // ... 其他release配置 } } }同时在android {块的最上方添加读取key.properties的代码def keystoreProperties new Properties() def keystorePropertiesFile rootProject.file(key.properties) if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) }4.4 执行构建flutter build apk --release的127秒全程解剖一切就绪执行终极命令flutter build apk --release整个过程耗时约127秒MacBook Pro M2终端输出分为五个清晰阶段阶段一Dart编译0-45秒Running Gradle task assembleRelease...之前Flutter CLI先启动Dart编译器。日志显示Initializing gradle... 1.2s Resolving dependencies... 2.8s Running Gradle task assembleRelease... 0.5s这其实是Dart编译的前置准备。真正的AOT编译在Running Gradle task之后开始你会看到[ 123 ms] executing: /usr/bin/xcodebuild -version [ 156 ms] Exit code 0 from: /usr/bin/xcodebuild -version [ ] Xcode 15.3 [ 123 ms] Building AOT snapshot in release mode (android-arm64, android-arm, android-x64)... [21456 ms] Built to build/aot/.这里Built to build/aot/是关键信号表示Dart代码已成功编译成三个ABI的so文件arm64-v8a/libapp.so、armeabi-v7a/libapp.so、x86_64/libapp.so。耗时21秒占总时间1/6。阶段二Gradle构建45-110秒Running Gradle task assembleRelease...启动Gradle开始工作[12345 ms] Task :app:mergeReleaseResources [2345 ms] Task :app:processReleaseManifest [3456 ms] Task :app:compileReleaseKotlin [4567 ms] Task :app:packageReleasemergeReleaseResources合并所有资源图标、字符串、布局processReleaseManifest处理AndroidManifest.xml注入Flutter必需的activity和meta-datacompileReleaseKotlin编译android/app/src/main/kotlin/下的Kotlin代码纯Flutter项目这里基本是空的所以很快packageRelease是最后一步把so文件、资源、dex、清单文件打包成APK。阶段三签名与优化110-125秒Gradle完成打包后自动调用jarsigner和zipalign[1234 ms] Task :app:signReleaseBundle [567 ms] Task :app:zipAlignReleasesignReleaseBundle用key.jks对APK签名zipAlignRelease对APK进行字节对齐优化减小内存占用。阶段四输出与验证125-127秒最后两行是胜利的宣言[ 2 ms] Built build/app/outputs/flutter-apk/app-release.apk (15.2MB). [ 1 ms] Running Gradle task assembleRelease... (completed in 127.0s)APK生成在build/app/outputs/flutter-apk/app-release.apk大小15.2MB。这个大小是合理的包含了Flutter引擎libflutter.so、Dart代码libapp.so、所有资源。4.5 包体分析与瘦身为什么15.2MB还能再砍掉30%15.2MB对于一个纯Flutter TodoList来说显然偏大。我们用flutter build apk --analyze-size深入看看flutter build apk --analyze-size --release输出关键数据Total size: 15.2 MB ├── libflutter.so (arm64-v8a): 8.1 MB (53.3%) ├── libapp.so (arm64-v8a): 3.2 MB (21.1%) ├── assets/: 2.1 MB (13.8%) │ ├── fonts/: 1.5 MB │ └── images/: 0.6 MB └── res/: 1.8 MB (11.8%)瘦身策略有三ABI拆分flutter build apk --release --split-per-abi生成三个APKarm64、armv7、x64每个约8-10MB用户下载时只下对应CPU的包。字体精简pubspec.yaml里只保留真正用到的字体删除MaterialIcons等未使用的字体包。图片压缩用squoosh或ImageOptim批量压缩assets/images/下的PNG/JPG实测可减小40%体积。执行flutter build apk --release --split-per-abi后build/app/outputs/flutter-apk/下出现app-arm64-v8a-release.apk(8.7MB)app-armeabi-v7a-release.apk(8.5MB)app-x86_64-release.apk(9.1MB)这才是面向市场的合理包体。5. 常见问题与排查技巧实录147次CI失败后总结的12个高频问题速查表在某跨平台系统交付过程中我们的CI流水线GitHub Actions共触发147次flutter build apk失败。我把这些问题归类、复现、验证整理成这张速查表。每个问题都附带错误日志特征、根本原因、三步定位法和永久解决方案。这不是理论是血的教训。序号错误日志特征直接复制搜索根本原因三步定位法永久解决方案1Execution failed for task :app:lintVitalRelease.lintVitalRelease任务启用但项目里有未处理的Lint警告如硬编码字符串① 查看完整日志找到lintVitalRelease前一行的warning② 在android/app/build.gradle里搜索lintOptions③ 运行./gradlew app:lintDebug本地复现在android/app/build.gradle的android {块内添加lintOptions {br disable HardcodedTextbr checkReleaseBuilds falsebr}2Could not find method implementation() for arguments [project :path_provider]android/app/build.gradle里dependencies块中implementation写成了implement少一个t① 检查dependencies块内所有行② 用VS Code的CtrlF搜索implement③ 对比flutter create生成的模板使用VS Code的Flutter插件它会自动高亮语法错误implement会被标为红色波浪线3A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacadeandroid/app/src/main/res/values/styles.xml里style nameLaunchTheme继承了不存在的父主题如android:style/Theme.Black.NoTitleBar① 打开styles.xml② 查看LaunchTheme的parent属性③ 在android/sdk/platforms/android-34/data/res/values/themes.xml里搜索该父主题是否存在将parent改为android:style/Theme.Translucent.NoTitleBar兼容性最好或style/Theme.AppCompat.Light.DarkActionBar需添加AppCompat依赖4java.lang.NullPointerException: Cannot invoke java.util.List.size() because this.mergedManifests is nullandroid/app/src/main/AndroidManifest.xml里application标签没有闭合或者activity标签嵌套错误① 用XML格式化工具如VS Code的XML Tools插件格式化Manifest② 检查所有标签是否成对③ 特别注意meta-data是否在application内在VS Code设置中启用xml.format.enable保存时自动格式化错误标签会立即报错5The supplied javaHome seems to be invalid. I cannot find the java executable.CI环境里JAVA_HOME指向了JRE而非JDK或者路径错误① 在CI脚本里加echo $JAVA_HOME② 加ls -la $JAVA_HOME/bin/java③ 如果输出No such file说明路径错在GitHub Actions的steps中用actions/setup-javav3明确指定JDK版本- uses: actions/setup-javav3br with:br distribution: temurinbr java-version: 176Execution failed for task :app:processReleaseResources. Android resource linking failedpubspec.yaml里flutter.assets配置的路径文件实际不存在或者文件名大小写不匹配Linux/macOS区分大小写① 复制assets路径到终端用ls查看② 检查文件名如logo.pngvsLogo.PNG③ 运行flutter pub get后检查build/app/intermediates/flutter/release/assets/目录在pubspec.yaml里配置assets后立即在VS Code里用CtrlClick点击路径如果能跳转到文件说明路径正确7Error: Execution failed for task :app:mergeReleaseResources. Could not resolve all files for configuration :app:releaseCompileClasspath.android
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →