如何在Codemagic中修改Flutter项目默认应用名称并适配多环境版本逻辑
解决Flutter多Flavor应用名称配置与版本号重置问题(Codemagic工作流)
一、不同Flavor设置自定义应用名称
Flutter多Flavor的应用名称需要分别适配Android和iOS端,结合Codemagic构建参数即可实现不同环境用不同名称:
Android端配置
直接在android/app/build.gradle的productFlavors中为每个环境定义应用名称,无需手动修改多个strings.xml文件:
android { // 保留原有配置,添加以下内容 productFlavors { prod { resValue "string", "app_name", "Fresh Operator 正式版" // 可选:添加applicationId后缀、版本名后缀等 } staging { resValue "string", "app_name", "Fresh Operator 测试版" } dev { resValue "string", "app_name", "Fresh Operator 开发版" } } }
修改android/app/src/main/AndroidManifest.xml,将android:label改为引用动态生成的资源:
<application android:label="@string/app_name" <!-- 其他属性不变 --> >
iOS端配置
在ios/Runner目录下为每个Flavor创建独立的Info.plist文件,比如Info-prod.plist、Info-staging.plist,修改其中的CFBundleDisplayName:
<key>CFBundleDisplayName</key> <string>Fresh Operator 正式版</string>
在ios/Podfile中添加配置,让不同Flavor加载对应的plist:
post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| case config.name when 'Prod' config.build_settings['INFOPLIST_FILE'] = 'Runner/Info-prod.plist' when 'Staging' config.build_settings['INFOPLIST_FILE'] = 'Runner/Info-staging.plist' when 'Dev' config.build_settings['INFOPLIST_FILE'] = 'Runner/Info-dev.plist' end end end end
Codemagic关联Flavor
在Codemagic的构建命令中添加--flavor参数,比如构建正式版时使用:
flutter build apk --flavor prod
构建时会自动加载对应Flavor的应用名称配置。
二、实现主版本变更时补丁号重置的版本逻辑
之前依赖PackageInfo的方案不可行,因为它是运行时API,预构建阶段无法获取正确信息。改用文件操作+缓存记录的方式,完美实现需求:
1. 编写版本生成脚本version_generator.dart
放在项目根目录,负责计算版本号并生成构建名称:
import 'dart:convert'; import 'dart:io'; void main() async { // 从pubspec.yaml读取主版本号 final pubspecFile = File('pubspec.yaml'); final pubspecContent = await pubspecFile.readAsString(); final versionMatch = RegExp(r'version:\s*(\d+)\.\d+\.\d+').firstMatch(pubspecContent); if (versionMatch == null) { print('Error: 无法读取pubspec中的版本号'); exit(1); } final currentMajor = versionMatch.group(1)!; // 读取补丁号记录文件(不存在则自动创建) final patchCounter = File('patch_counter.json'); Map<String, dynamic> patchData = {}; if (await patchCounter.exists()) { patchData = jsonDecode(await patchCounter.readAsString()); } // 计算补丁号:主版本变更则重置为1,否则递增 int currentPatch; final storedMajor = patchData['major'] as String?; final storedPatch = patchData['patch'] as int?; if (storedMajor != currentMajor || storedPatch == null) { currentPatch = 1; patchData['major'] = currentMajor; patchData['patch'] = 1; } else { currentPatch = storedPatch + 1; patchData['patch'] = currentPatch; } // 更新补丁号记录文件 await patchCounter.writeAsString(jsonEncode(patchData)); // 生成最终构建名称 final now = DateTime.now().toLocal(); final flavor = Platform.environment['FLAVOR'] ?? 'prod'; final buildName = 'fresh_operator_${flavor}_${now.year}.$currentMajor.$currentPatch'; // 将构建名称写入Codemagic环境变量,供后续构建步骤使用 print('echo "BUILD_NAME=$buildName" >> $CM_ENV'); }
2. 在Codemagic配置预构建步骤
在工作流的Pre-build script中添加:
# 设置当前构建的Flavor,根据实际任务修改为prod/staging/dev export FLAVOR=prod # 运行版本生成脚本 dart run version_generator.dart
在构建命令中使用生成的BUILD_NAME:
# Android构建 flutter build apk --flavor $FLAVOR --build-name="$BUILD_NAME" # iOS构建 flutter build ipa --flavor $FLAVOR --build-name="$BUILD_NAME"
逻辑说明
- 用
patch_counter.json记录当前主版本对应的补丁号,Codemagic会缓存项目文件,因此该文件会在后续构建中保留 - 从pubspec.yaml读取主版本号,确保版本变更以项目配置为准
- 通过环境变量传递Flavor,保证构建名称与当前环境匹配
可选:直接修改pubspec.yaml版本号
如果不需要单独的构建名称,希望直接更新pubspec中的版本号,可以在脚本中添加以下代码:
// 生成新的版本号,格式:主版本.0.补丁号 final newVersion = '$currentMajor.0.$currentPatch'; // 替换pubspec中的版本号 final updatedPubspec = pubspecContent.replaceFirst( RegExp(r'version:\s*\d+\.\d+\.\d+'), 'version: $newVersion', ); await pubspecFile.writeAsString(updatedPubspec);
内容的提问来源于stack exchange,提问作者Rohan Bhande
相关产品推荐
相关产品推荐

