You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

149 lines
4.5 KiB

import 'dart:io';
import 'dart:convert';
import 'package:yaml/yaml.dart'; // 用于解析 pubspec.yaml
import 'package:args/args.dart'; // 用于解析命令行参数
// --- 配置区 ---
const String pubspecPath = 'pubspec.yaml';
const String baseApkPath = 'build/app/outputs/flutter-apk/';
const String sourceApkName = 'app-release.apk';
// ---
Future<void> main(List<String> rawArgs) async {
// 使用 args 包来专业地解析命令行参数
final parser = ArgParser()
..addFlag('arm64-only', negatable: false, help: '只构建 ARM64 架构的 APK。')
..addOption(
'description',
abbr: 'd',
help: '版本更新的描述。',
defaultsTo: '常规更新。',
);
final args = parser.parse(rawArgs);
final isArm64Only = args['arm64-only'] as bool;
final description = args['description'] as String;
print('🚀 开始构建Flutter Android应用...');
final targetPlatform = isArm64Only
? 'android-arm64'
: 'android-arm64,android-arm';
final finalApkName = isArm64Only ? 'app-arm64-release.apk' : sourceApkName;
final finalApkPath = '$baseApkPath$finalApkName';
try {
await checkFlutterEnvironment();
await buildFlutterApp(targetPlatform, finalApkPath);
await generateVersionJson(finalApkPath, targetPlatform, description);
print('✅ 构建全部完成!');
print('📦 APK位置: $finalApkPath');
} catch (e) {
print('❌ 构建过程中出现错误: $e');
exit(1);
}
}
Future<void> buildFlutterApp(String targetPlatform, String finalApkPath) async {
print('📱 正在构建Flutter Android应用...');
print('🎯 目标平台: $targetPlatform');
await runProcess('flutter', ['clean']);
await runProcess('flutter', ['pub', 'get']);
print('🔨 构建Release APK...');
await runProcess('flutter', [
'build',
'apk',
'--release',
'--target-platform=$targetPlatform',
]);
final sourceApkFile = File('$baseApkPath$sourceApkName');
if (await sourceApkFile.exists()) {
print(' 正在重命名APK为: ${finalApkPath.split('/').last}');
await sourceApkFile.rename(finalApkPath);
} else {
throw Exception('构建产物 $sourceApkName 未找到!');
}
print('✅ Flutter应用构建成功!');
}
Future<void> generateVersionJson(
String apkPath,
String targetPlatform,
String description,
) async {
print('📄 正在生成version.json文件...');
final apkFile = File(apkPath);
String fileSize = '未知';
if (await apkFile.exists()) {
final apkSize = await apkFile.length();
fileSize = '${(apkSize / (1024 * 1024)).toStringAsFixed(1)}MB';
print('📦 APK文件大小: $fileSize');
}
final pubspecInfo = getPubspecInfo();
final buildTime = getFormattedDateTime();
final versionInfo = {
"version": pubspecInfo['version_name'],
"build_number": pubspecInfo['build_number'],
"build_time": buildTime,
"target_platform": targetPlatform,
"file_size": fileSize,
// [已修正] 从 apkPath 中提取文件名
"url": "http://xhota.anxincloud.cn/problem/${apkPath.split('/').last}",
"description": description,
"platform": "android",
};
final jsonFile = File('${baseApkPath}version.json');
await jsonFile.writeAsString(
const JsonEncoder.withIndent(' ').convert(versionInfo),
);
print('✅ version.json文件生成成功!');
}
// --- 辅助函数 ---
Future<void> runProcess(String executable, List<String> arguments) async {
print(' 执行命令: $executable ${arguments.join(' ')}');
final result = await Process.run(executable, arguments, runInShell: true);
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
throw Exception('命令执行失败: $executable ${arguments.join(' ')}');
}
}
Future<void> checkFlutterEnvironment() async {
try {
await runProcess('flutter', ['--version']);
print('✅ Flutter环境正常');
} catch (e) {
throw Exception('Flutter环境检查失败');
}
}
Map<String, String> getPubspecInfo() {
final file = File(pubspecPath);
final content = file.readAsStringSync();
final doc = loadYaml(content);
final versionString = doc['version'] as String;
final parts = versionString.split('+');
return {
'version_name': parts[0],
'build_number': parts.length > 1 ? parts[1] : '1',
};
}
String getFormattedDateTime() {
final now = DateTime.now();
return '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
}