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 main(List 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 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 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 runProcess(String executable, List 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 checkFlutterEnvironment() async { try { await runProcess('flutter', ['--version']); print('✅ Flutter环境正常'); } catch (e) { throw Exception('Flutter环境检查失败'); } } Map 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')}'; }