| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- // build-android.js - 统一Android SDK安装和构建脚本
- const fs = require('fs');
- const path = require('path');
- const https = require('https');
- const http = require('http');
- const { execSync } = require('child_process');
- const { URL } = require('url');
- const os = require('os');
- const { rmSync } = require('fs');
- // 配置 - 跨平台设置
- const isWindows = process.platform === 'win32';
- const isMac = process.platform === 'darwin';
- // 根据平台选择相应的 ZIP URL
- const platformZipMap = {
- win32: 'commandlinetools-win-11076708_latest.zip',
- linux: 'commandlinetools-linux-11076708_latest.zip',
- darwin: 'commandlinetools-mac-11076708_latest.zip'
- };
- // 按优先级确定 SDK 安装路径:环境变量 > 平台默认路径
- const defaultSdkRoot = isWindows
- ? path.join(process.env.APPDATA, 'Android', 'Sdk')
- : path.join(os.homedir(), 'android-sdk');
- const SDK_ROOT = process.env.ANDROID_SDK_ROOT || process.env.ANDROID_HOME || defaultSdkRoot;
- const SDK_URL = `https://dl.google.com/android/repository/${platformZipMap[process.platform] || platformZipMap.linux}`;
- const CMDLINE_TOOLS_DIR = path.join(SDK_ROOT, 'cmdline-tools', 'latest');
- const TEMP_ZIP = path.join(process.env.TEMP || (isWindows ? process.env.TMP : '/tmp'), 'cmdtools.zip');
- const VERSION_FILE = path.join(SDK_ROOT, '.sdk-version');
- const EXPECTED_VERSION = 'platforms-35-buildtools-35.0.0';
- // 从环境变量获取代理设置
- const PROXY = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
- // 读取 package.json 获取版本号
- const packageJson = require(path.join(__dirname, '..', 'package.json'));
- // 计算各路径
- const rootDir = path.join(__dirname, '..'); // 项目根目录
- const cordovaPrjDir = path.join(__dirname, 'dros'); // .build/dros
- const srcDir = path.join(rootDir, 'dist', 'h5'); // ../dist/h5
- const dstDir = path.join(cordovaPrjDir, 'www');
- console.log('🚀 Android SDK 安装和构建统一脚本启动...');
- console.log(`📦 SDK Root: ${SDK_ROOT}`);
- if (PROXY) {
- console.log(`🌐 使用代理: ${PROXY}`);
- }
- // 检查 SDK 是否已安装且版本正确
- function isSdkInstalled() {
- console.log('🔍 检测 Android SDK 安装状态...');
- const sdkManagerExe = isWindows ? 'sdkmanager.bat' : 'sdkmanager';
- const sdkManagerPath = path.join(CMDLINE_TOOLS_DIR, 'bin', sdkManagerExe);
- const platformPath = path.join(SDK_ROOT, 'platforms', 'android-35');
- const buildToolsPath = path.join(SDK_ROOT, 'build-tools', '35.0.0');
- // 检查关键文件是否存在
- console.log(' 📂 检查 sdkmanager...');
- if (!fs.existsSync(sdkManagerPath)) {
- console.log(' ❌ sdkmanager 不存在');
- return false;
- }
- console.log(' ✅ sdkmanager 存在');
- console.log(' 📂 检查 platforms;android-35...');
- if (!fs.existsSync(platformPath)) {
- console.log(' ❌ platforms;android-35 不存在');
- return false;
- }
- console.log(' ✅ platforms;android-35 存在');
- console.log(' 📂 检查 build-tools;35.0.0...');
- if (!fs.existsSync(buildToolsPath)) {
- console.log(' ❌ build-tools;35.0.0 不存在');
- return false;
- }
- console.log(' ✅ build-tools;35.0.0 存在');
- // 验证版本标记文件
- console.log(' 📝 检查版本标记...');
- if (fs.existsSync(VERSION_FILE)) {
- const installedVersion = fs.readFileSync(VERSION_FILE, 'utf8').trim();
- console.log(` 已安装版本: ${installedVersion}`);
- console.log(` 期望版本: ${EXPECTED_VERSION}`);
- if (installedVersion === EXPECTED_VERSION) {
- console.log(' ✅ 版本匹配');
- return true;
- } else {
- console.log(' ⚠️ 版本不匹配,需要重新安装');
- return false;
- }
- } else {
- console.log(' ⚠️ 版本标记文件不存在');
- return false;
- }
- }
- // 下载文件(支持代理)
- function downloadFile(url, dest) {
- return new Promise((resolve, reject) => {
- console.log(`📥 下载: ${url}`);
- const file = fs.createWriteStream(dest);
- const urlObj = new URL(url);
- let requestLib = https;
- let options = {
- hostname: urlObj.hostname,
- path: urlObj.pathname + urlObj.search,
- method: 'GET',
- headers: {
- 'User-Agent': 'Node.js'
- }
- };
- // 如果有代理,使用代理设置
- if (PROXY) {
- const proxyUrl = new URL(PROXY);
- requestLib = proxyUrl.protocol === 'https:' ? https : http;
- options = {
- hostname: proxyUrl.hostname,
- port: proxyUrl.port,
- path: url, // 使用完整 URL 作为路径
- method: 'GET',
- headers: {
- 'Host': urlObj.hostname,
- 'User-Agent': 'Node.js'
- }
- };
- }
- const request = requestLib.get(options, (response) => {
- // 处理重定向
- if (response.statusCode === 301 || response.statusCode === 302) {
- const redirectUrl = response.headers.location;
- console.log(`🔀 重定向到: ${redirectUrl}`);
- file.close();
- fs.unlinkSync(dest);
- return downloadFile(redirectUrl, dest).then(resolve).catch(reject);
- }
- if (response.statusCode !== 200) {
- reject(new Error(`下载失败,状态码: ${response.statusCode}`));
- return;
- }
- const totalSize = parseInt(response.headers['content-length'], 10);
- let downloadedSize = 0;
- response.on('data', (chunk) => {
- downloadedSize += chunk.length;
- const percent = ((downloadedSize / totalSize) * 100).toFixed(2);
- process.stdout.write(`\r下载进度: ${percent}% (${downloadedSize}/${totalSize} bytes)`);
- });
- response.pipe(file);
- file.on('finish', () => {
- file.close();
- console.log('\n✅ 下载完成');
- resolve();
- });
- });
- request.on('error', (err) => {
- fs.unlinkSync(dest);
- reject(err);
- });
- file.on('error', (err) => {
- fs.unlinkSync(dest);
- reject(err);
- });
- });
- }
- // 解压 ZIP 文件
- function extractZip(zipPath, destDir) {
- console.log(`📂 解压到: ${destDir}`);
- // 确保目标目录存在
- fs.mkdirSync(destDir, { recursive: true });
- // 在 Windows 上使用 PowerShell 的 Expand-Archive
- if (process.platform === 'win32') {
- try {
- const cmd = `powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`;
- execSync(cmd, { stdio: 'inherit' });
- console.log('✅ 解压完成');
- } catch (error) {
- throw new Error(`解压失败: ${error.message}`);
- }
- } else {
- // Linux 使用 unzip
- try {
- execSync(`unzip -q "${zipPath}" -d "${destDir}"`, { stdio: 'inherit' });
- console.log('✅ 解压完成');
- } catch (error) {
- throw new Error(`解压失败: ${error.message}`);
- }
- }
- }
- // 设置环境变量(写入 GITHUB_ENV)
- function setGitHubEnv(name, value) {
- const envFile = process.env.GITHUB_ENV;
- if (envFile) {
- fs.appendFileSync(envFile, `${name}=${value}\n`);
- console.log(`✅ 设置环境变量: ${name}=${value}`);
- } else {
- console.log(`⚠️ GITHUB_ENV 未定义,跳过设置: ${name}=${value}`);
- }
- }
- // 安装 Gradle 到 PATH
- async function installGradleToPath() {
- const gradleVersion = '9.0.0'; // 使用稳定版本,可根据需要更新
- const gradleUrl = `https://mirrors.cloud.tencent.com/gradle/gradle-${gradleVersion}-bin.zip`;
- const gradleInstallDir = isWindows
- ? path.join(process.env.USERPROFILE, 'gradle')
- : path.join(os.homedir(), 'gradle');
- const gradleBin = path.join(gradleInstallDir, `gradle-${gradleVersion}`, 'bin');
- // 检查 Gradle 是否已存在
- const gradleExe = isWindows ? 'gradle.bat' : 'gradle';
- const fullGradleExe = path.join(gradleBin, gradleExe);
- if (fs.existsSync(fullGradleExe)) {
- console.log('✅ Gradle 已安装');
- // 添加到 PATH(即使已安装也要确保在PATH中)
- const pathEnvFile = process.env.GITHUB_PATH;
- if (pathEnvFile) {
- fs.appendFileSync(pathEnvFile, `${gradleBin}\n`);
- console.log(`✅ Gradle 已添加到 PATH: ${gradleBin}`);
- }
- return;
- }
- console.log(`📦 下载 Gradle ${gradleVersion}...`);
- await downloadFile(gradleUrl, TEMP_ZIP);
- console.log(`📂 解压 Gradle 到: ${gradleInstallDir}`);
- extractZip(TEMP_ZIP, gradleInstallDir);
- // 添加到 PATH
- const pathEnvFile = process.env.GITHUB_PATH;
- if (pathEnvFile) {
- fs.appendFileSync(pathEnvFile, `${gradleBin}\n`);
- console.log(`✅ Gradle 已添加到 PATH: ${gradleBin}`);
- } else {
- console.log(`⚠️ 请手动将 ${gradleBin} 添加到 PATH`);
- }
- // 测试 Gradle
- try {
- execSync(`"${fullGradleExe}" --version`, { stdio: 'pipe' });
- console.log('✅ Gradle 安装成功');
- } catch (error) {
- console.warn('⚠️ Gradle 测试失败:', error.message);
- }
- }
- // 运行 sdkmanager
- function runSdkManager(args) {
- const sdkManagerExe = isWindows ? 'sdkmanager.bat' : 'sdkmanager';
- const sdkManagerPath = path.join(CMDLINE_TOOLS_DIR, 'bin', sdkManagerExe);
- if (!fs.existsSync(sdkManagerPath)) {
- throw new Error(`sdkmanager 不存在: ${sdkManagerPath}`);
- }
- console.log(`🔧 运行: sdkmanager ${args.join(' ')}`);
- try {
- // 分离包名和参数
- const packages = args.filter(arg => !arg.startsWith('--'));
- const flags = args.filter(arg => arg.startsWith('--'));
- // 只对包名加引号,参数不加引号
- const quotedPackages = packages.map(pkg => `"${pkg}"`).join(' ');
- const cmd = `"${sdkManagerPath}" ${quotedPackages} ${flags.join(' ')}`;
- console.log(`执行命令: ${cmd}`);
- // 根据平台设置不同的 shell 选项
- const execOptions = isWindows
- ? { stdio: 'inherit', shell: 'cmd.exe' }
- : { stdio: 'inherit' };
- execSync(cmd, execOptions);
- console.log('✅ sdkmanager 执行成功');
- } catch (error) {
- throw new Error(`sdkmanager 执行失败: ${error.message}`);
- }
- }
- // 安装和配置 Android SDK
- async function setupAndroidSdk() {
- console.log('🔧 检查 Gradle 安装...');
- await installGradleToPath();
- // 0. 检查 SDK 是否已安装
- if (isSdkInstalled()) {
- console.log('\n✅ Android SDK 已安装且版本正确,跳过安装流程');
- console.log(`📦 SDK Root: ${SDK_ROOT}`);
- // 仍然需要设置环境变量(GitHub Actions 每次运行都需要)
- console.log('\n⚙️ 设置环境变量...');
- setGitHubEnv('ANDROID_HOME', SDK_ROOT);
- setGitHubEnv('ANDROID_SDK_ROOT', SDK_ROOT);
- console.log('\n🎉 Android SDK 环境变量设置完成!');
- console.log('⏱️ 耗时: ~1-2秒(本地缓存加速)');
- return;
- }
- console.log('\n📦 未检测到有效的 Android SDK,开始完整安装流程...');
- // 1. 下载 SDK
- await downloadFile(SDK_URL, TEMP_ZIP);
- // 2. 解压到临时目录
- const tempExtractDir = path.join(SDK_ROOT, 'cmdline-tools', 'temp');
- extractZip(TEMP_ZIP, tempExtractDir);
- // 3. 移动内部的 cmdline-tools 到 latest(ZIP 内部包含 cmdline-tools 目录)
- const extractedCmdlineTools = path.join(tempExtractDir, 'cmdline-tools');
- if (fs.existsSync(extractedCmdlineTools)) {
- console.log('📦 重新组织目录结构...');
- // 如果 latest 目录已存在,先删除
- if (fs.existsSync(CMDLINE_TOOLS_DIR)) {
- fs.rmSync(CMDLINE_TOOLS_DIR, { recursive: true, force: true });
- }
- fs.renameSync(extractedCmdlineTools, CMDLINE_TOOLS_DIR);
- // 删除临时目录
- fs.rmSync(tempExtractDir, { recursive: true, force: true });
- console.log('✅ 目录结构已调整');
- } else {
- throw new Error(`解压后未找到 cmdline-tools 目录: ${extractedCmdlineTools}`);
- }
- // 4. 设置环境变量
- setGitHubEnv('ANDROID_HOME', SDK_ROOT);
- setGitHubEnv('ANDROID_SDK_ROOT', SDK_ROOT);
- // 5. 先接受 licenses(使用输入重定向文件)
- console.log('📝 接受 SDK licenses...');
- const sdkManagerExe = isWindows ? 'sdkmanager.bat' : 'sdkmanager';
- const sdkManagerPath = path.join(CMDLINE_TOOLS_DIR, 'bin', sdkManagerExe);
- // 创建包含多个 y 的临时文件(每个 y 一行)
- const tempInputFileDir = isWindows ? process.env.TEMP || process.env.TMP : '/tmp';
- const tempInputFile = path.join(tempInputFileDir, 'sdk-licenses-input.txt');
- // 根据日志显示有 7 个许可证,我们用 20 个 y 确保足够
- fs.writeFileSync(tempInputFile, 'y\n'.repeat(20));
- // 使用输入重定向 < 而不是管道 |
- const licenseCmd = `"${sdkManagerPath}" --licenses --sdk_root=${SDK_ROOT} < "${tempInputFile}"`;
- // 根据平台设置不同的 shell 选项
- const licenseExecOptions = isWindows
- ? { stdio: 'inherit', shell: 'cmd.exe' }
- : { stdio: 'inherit' };
- execSync(licenseCmd, licenseExecOptions);
- console.log('✅ licenses 接受完成');
- // 清理临时文件
- if (fs.existsSync(tempInputFile)) {
- fs.unlinkSync(tempInputFile);
- }
- // 6. 然后安装 platforms 和 build-tools
- console.log('📦 安装 Android SDK 组件...');
- runSdkManager([
- 'platforms;android-35',
- 'build-tools;35.0.0',
- `--sdk_root=${SDK_ROOT}`
- ]);
- console.log('🎉 Android SDK 安装完成!');
- // 7. 创建版本标记文件
- console.log('📝 创建版本标记文件...');
- fs.writeFileSync(VERSION_FILE, EXPECTED_VERSION, 'utf8');
- console.log(`✅ 版本标记已创建: ${EXPECTED_VERSION}`);
- // 清理临时文件
- if (fs.existsSync(TEMP_ZIP)) {
- fs.unlinkSync(TEMP_ZIP);
- console.log('🧹 已清理临时文件');
- }
- }
- // 配置 Gradle Wrapper 使用我们的 Gradle 版本
- function configureGradleWrapper() {
- const gradleWrapperPropsPath = path.join(cordovaPrjDir, 'platforms', 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties');
- if (!fs.existsSync(gradleWrapperPropsPath)) {
- console.log('⚠️ Gradle wrapper 配置文件不存在,跳过配置');
- return;
- }
- console.log('🔧 配置 Gradle wrapper 使用 Gradle 8.13(腾讯云镜像)...');
- try {
- // 读取现有的配置文件
- let content = fs.readFileSync(gradleWrapperPropsPath, 'utf8');
- // 替换 distributionUrl 为腾讯云镜像,并添加超时配置
- const oldUrlPattern = /distributionUrl=.*/;
- const newUrl = 'distributionUrl=https\\://mirrors.cloud.tencent.com/gradle/gradle-8.13-bin.zip';
- if (oldUrlPattern.test(content)) {
- content = content.replace(oldUrlPattern, newUrl);
- fs.writeFileSync(gradleWrapperPropsPath, content, 'utf8');
- console.log('✅ Gradle wrapper 已配置为使用 Gradle 8.13(腾讯云镜像)');
- } else {
- console.log('⚠️ 未找到 distributionUrl 配置,添加新配置');
- content += `\n${newUrl}\n`;
- fs.writeFileSync(gradleWrapperPropsPath, content, 'utf8');
- console.log('✅ 已添加 Gradle 8.13 配置');
- }
- // 添加网络超时配置
- if (!content.includes('networkTimeout')) {
- content += '\n# 网络超时设置(300秒 = 5分钟)\nnetworkTimeout=300000\n';
- fs.writeFileSync(gradleWrapperPropsPath, content, 'utf8');
- console.log('✅ 已添加网络超时配置');
- }
- } catch (error) {
- console.warn('⚠️ 配置 Gradle wrapper 失败:', error.message);
- }
- }
- // 配置全局 Gradle 设置(超时时间、镜像等)
- function configureGradleGlobal() {
- const initGradlePath = path.join(cordovaPrjDir, 'init.gradle');
- console.log('🔧 创建全局 Gradle 配置(init.gradle)...');
- const initGradleContent = `
- allprojects {
- repositories {
- maven { url 'https://maven.aliyun.com/repository/public' }
- maven { url 'https://maven.aliyun.com/repository/google' }
- maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
- mavenCentral()
- google()
- jcenter()
- }
- // 配置所有任务的网络超时
- tasks.withType(JavaCompile) {
- options.fork = true
- options.forkOptions.memoryMaximumSize = '1g'
- }
- }
- task wrapper(type: Wrapper) {
- gradleVersion = '8.13'
- distributionUrl = 'https://mirrors.cloud.tencent.com/gradle/gradle-8.13-bin.zip'
- networkTimeout = 300000 // 5分钟超时
- }
- // 全局超时设置
- gradle.startParameter.taskExecutionTimeout = java.time.Duration.ofMinutes(10)
- `;
- fs.writeFileSync(initGradlePath, initGradleContent, 'utf8');
- console.log('✅ 已创建 init.gradle 全局配置(5分钟超时 + 阿里云镜像)');
- }
- // 配置 Android 构建环境变量
- function getAndroidEnv() {
- // 计算 Gradle bin 路径
- const gradleVersion = '9.0.0';
- const gradleBin = isWindows
- ? path.join(process.env.USERPROFILE || '', 'gradle', `gradle-${gradleVersion}`, 'bin')
- : path.join(process.env.HOME || '/root', 'gradle', `gradle-${gradleVersion}`, 'bin');
- return {
- ...process.env,
- // 使用配置的SDK路径
- ANDROID_HOME: SDK_ROOT,
- ANDROID_SDK_ROOT: SDK_ROOT,
- // 确保 Java 路径正确
- JAVA_HOME: process.env.JAVA_HOME,
- // 将 Gradle 添加到 PATH 前缀,确保 Cordova 子进程能找到它
- PATH: `${gradleBin}${path.delimiter}${process.env.PATH}`
- };
- }
- // 构建 Android APK
- function buildAndroidApk() {
- const androidEnv = getAndroidEnv();
- rmSync('.build/dros', { recursive: true, force: true });
- // 做一些环境检查
- execSync('npx cordova --version', { stdio: 'inherit', env: androidEnv });
- // 1. 在项目根目录执行 cordova create
- execSync('npx cordova create .build/dros zskk.dros dros', { cwd: rootDir, stdio: 'inherit', env: androidEnv });
- // 2. 在 .build/dros 中执行 cordova platform add android
- execSync('npx cordova platform add android', { cwd: cordovaPrjDir, stdio: 'inherit', env: androidEnv });
- // 2.5. 配置 Gradle wrapper 使用我们的 Gradle 版本
- configureGradleWrapper();
- // 2.6. 配置全局 Gradle 设置(超时时间、镜像等)
- configureGradleGlobal();
- // 3. 复制 dist/h5 → .build/dros/www
- fs.rmSync(dstDir, { recursive: true, force: true });
- fs.mkdirSync(dstDir, { recursive: true });
- function copy(src, dst) {
- const stat = fs.statSync(src);
- if (stat.isDirectory()) {
- fs.mkdirSync(dst, { recursive: true });
- for (const entry of fs.readdirSync(src)) {
- copy(path.join(src, entry), path.join(dst, entry));
- }
- } else {
- fs.copyFileSync(src, dst);
- }
- }
- copy(srcDir, dstDir);
- // 3.1 需要修改 index.html,加入 Cordova 脚本引用
- const indexPath = path.join(dstDir, 'index.html');
- let indexContent = fs.readFileSync(indexPath, 'utf8');
- if (!indexContent.includes('cordova.js')) {
- indexContent = indexContent.replace(
- '<head>',
- '<head> \n \
- <!--在业务代码执行之前行加载cordova--> \n \
- <script src="cordova.js"></script>\n'
- );
- fs.writeFileSync(indexPath, indexContent, 'utf8');
- console.log('✅ 已在 index.html 中添加 cordova.js 引用');
- } else {
- console.log('✅ index.html 已包含 cordova.js 引用,跳过添加');
- }
- // 3.2 把.build\dros\platforms\android\platform_www\cordova.js复制到.build\dros\www目录下
- const cordovaJsSrc = path.join(cordovaPrjDir, 'platforms', 'android', 'platform_www', 'cordova.js');
- const cordovaJsDst = path.join(dstDir, 'cordova.js');
- fs.copyFileSync(cordovaJsSrc, cordovaJsDst);
- console.log('✅ 已复制 cordova.js 到 www 目录');
- execSync('npx cordova plugin add cordova-plugin-file', { cwd: cordovaPrjDir, stdio: 'inherit' });
- // 4. 安装插件 : 为了本地保存网络配置等数据
- execSync('npx cordova plugin add cordova-plugin-nativestorage', { cwd: cordovaPrjDir, stdio: 'inherit' });
- execSync('npx cordova plugin add cordova-plugin-camera', { cwd: cordovaPrjDir, stdio: 'inherit' });
- // 5. 复制预配置好的config.xml
- fs.copyFileSync(path.join(__dirname, 'config.xml'), path.join(cordovaPrjDir, 'config.xml'));
- // 6. 在 .build/dros 中执行 cordova build android
- execSync('npx cordova build android --verbose', { cwd: cordovaPrjDir, stdio: 'inherit', env: androidEnv });
- // 7. 重命名apk文件
- const version = packageJson.version;
- const pkg = 'dros';
- const src = path.join(__dirname, 'dros/platforms/android/app/build/outputs/apk/debug/app-debug.apk');
- const dst = path.join(__dirname, `dros/platforms/android/app/build/outputs/apk/debug/${pkg}-v${version}.apk`);
- fs.copyFileSync(src, dst);
- console.log(`✅ 已生成 ${dst}`);
- // 安装到连接的安卓设备(CI 环境跳过)
- if (process.env.CI !== 'true') {
- try {
- execSync(`adb install "${dst}"`, { stdio: 'inherit', env: androidEnv });
- console.log(`✅ 已安装到安卓设备 ${dst}`);
- } catch (error) {
- console.warn('⚠️ ADB 安装失败,可能没有连接设备:', error.message);
- }
- } else {
- console.log('ℹ️ CI 环境,跳过 ADB 安装步骤');
- }
- // 8. 部署到服务器(可选)
- (async () => {
- if (process.env.DEPLOY_ANDROID === 'true') {
- console.log('\n📤 开始部署到服务器...');
- console.log('='.repeat(50));
- try {
- const { deployAndroidToServer } = require('./deploy-android-to-server');
- await deployAndroidToServer({
- privateKey: process.env.DEPLOY_KEY,
- host: process.env.DEPLOY_HOST,
- username: process.env.DEPLOY_USER,
- remotePath: process.env.DEPLOY_PATH,
- apkPath: dst,
- appVersion: version
- });
- console.log('='.repeat(50));
- console.log('✅ 部署完成!');
- } catch (error) {
- console.error('='.repeat(50));
- console.error('❌ 部署失败:', error.message);
- process.exit(1);
- }
- } else {
- console.log('\n💡 提示: 设置 DEPLOY_ANDROID=true 可自动部署到服务器');
- }
- })();
- }
- // 主函数
- async function main() {
- try {
- // 1. 安装和配置 Android SDK
- await setupAndroidSdk();
- // 2. 构建 Android APK
- console.log('\n🏗️ 开始构建 Android APK...');
- buildAndroidApk();
- } catch (error) {
- console.error('❌ 错误:', error.message);
- process.exit(1);
- }
- }
- // 运行
- main();
|