Browse Source

把安装sdk的逻辑放到js中

dengdx 1 day ago
parent
commit
d7d76cc64c
2 changed files with 211 additions and 29 deletions
  1. 209 0
      .build/setup-android-sdk.js
  2. 2 29
      .github/workflows/build-linux-arm-appimage.yml

+ 209 - 0
.build/setup-android-sdk.js

@@ -0,0 +1,209 @@
+// setup-android-sdk.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 SDK_URL = 'https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip';
+const SDK_ROOT = 'C:\\android-sdk';
+const CMDLINE_TOOLS_DIR = path.join(SDK_ROOT, 'cmdline-tools', 'latest');
+const TEMP_ZIP = path.join(process.env.TEMP || '/tmp', 'cmdtools.zip');
+
+// 从环境变量获取代理设置
+const PROXY = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
+
+console.log('🚀 开始安装 Android SDK...');
+console.log(`📦 SDK Root: ${SDK_ROOT}`);
+if (PROXY) {
+  console.log(`🌐 使用代理: ${PROXY}`);
+}
+
+// 下载文件(支持代理)
+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}`);
+  }
+}
+
+// 运行 sdkmanager
+function runSdkManager(args) {
+  const sdkManagerPath = path.join(CMDLINE_TOOLS_DIR, 'bin', 'sdkmanager.bat');
+  
+  if (!fs.existsSync(sdkManagerPath)) {
+    throw new Error(`sdkmanager 不存在: ${sdkManagerPath}`);
+  }
+  
+  console.log(`🔧 运行: sdkmanager ${args.join(' ')}`);
+  
+  try {
+    // 构建完整的命令
+    const cmd = `"${sdkManagerPath}" ${args.map(arg => `"${arg}"`).join(' ')}`;
+    execSync(cmd, { 
+      stdio: 'inherit',
+      shell: 'cmd.exe'
+    });
+    console.log('✅ sdkmanager 执行成功');
+  } catch (error) {
+    throw new Error(`sdkmanager 执行失败: ${error.message}`);
+  }
+}
+
+// 主函数
+async function main() {
+  try {
+    // 1. 下载 SDK
+    await downloadFile(SDK_URL, TEMP_ZIP);
+    
+    // 2. 解压
+    extractZip(TEMP_ZIP, CMDLINE_TOOLS_DIR);
+    
+    // 3. 设置环境变量
+    setGitHubEnv('ANDROID_HOME', SDK_ROOT);
+    setGitHubEnv('ANDROID_SDK_ROOT', SDK_ROOT);
+    
+    // 4. 安装 platforms 和 build-tools
+    runSdkManager([
+      '--install',
+      'platforms;android-35',
+      'build-tools;35.0.0',
+      `--sdk_root=${SDK_ROOT}`
+    ]);
+    
+    // 5. 接受 licenses(使用 echo y)
+    console.log('📝 接受 SDK licenses...');
+    const sdkManagerPath = path.join(CMDLINE_TOOLS_DIR, 'bin', 'sdkmanager.bat');
+    const licenseCmd = `echo y | "${sdkManagerPath}" "--licenses" "--sdk_root=${SDK_ROOT}"`;
+    execSync(licenseCmd, { 
+      stdio: 'inherit',
+      shell: 'cmd.exe'
+    });
+    
+    console.log('🎉 Android SDK 安装完成!');
+    
+    // 清理临时文件
+    if (fs.existsSync(TEMP_ZIP)) {
+      fs.unlinkSync(TEMP_ZIP);
+      console.log('🧹 已清理临时文件');
+    }
+    
+  } catch (error) {
+    console.error('❌ 错误:', error.message);
+    process.exit(1);
+  }
+}
+
+// 运行
+main();

+ 2 - 29
.github/workflows/build-linux-arm-appimage.yml

@@ -92,36 +92,9 @@ jobs:
         with:
         with:
           node-version: '22'
           node-version: '22'
 
 
-      - name: 手动安装 Android SDK (Windows) ############为了早点调试到
+      - name: 安装 Android SDK (Windows)
         if: runner.os == 'Windows'
         if: runner.os == 'Windows'
-        shell: powershell
-        run: |
-          $url = "https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip"
-          $output = "$env:TEMP\cmdtools.zip"
-          
-          # 检查是否有代理设置
-          if ($env:HTTP_PROXY -or $env:HTTPS_PROXY) {
-            $proxy = if ($env:HTTPS_PROXY) { $env:HTTPS_PROXY } else { $env:HTTP_PROXY }
-            Write-Host "使用代理: $proxy"
-            Invoke-WebRequest -Uri $url -OutFile $output -Proxy $proxy -ProxyUseDefaultCredentials
-          } else {
-            Write-Host "直接连接(无代理)"
-            Invoke-WebRequest -Uri $url -OutFile $output
-          }
-          
-          $sdkRoot = "C:\android-sdk"
-          $cmdlineTools = "$sdkRoot\cmdline-tools\latest"
-          New-Item -ItemType Directory -Force -Path $cmdlineTools
-          Expand-Archive -Path $output -DestinationPath $cmdlineTools -Force
-          
-          echo "ANDROID_HOME=$sdkRoot" >> $env:GITHUB_ENV
-          echo "ANDROID_SDK_ROOT=$sdkRoot" >> $env:GITHUB_ENV
-          
-          # 使用数组参数避免字符串解析问题
-          $sdkManager = Join-Path $cmdlineTools "bin\sdkmanager.bat"
-          
-          & $sdkManager @("--install", "platforms;android-35", "build-tools;35.0.0", "--sdk_root=$sdkRoot")
-          echo y | & $sdkManager @("--licenses", "--sdk_root=$sdkRoot")
+        run: node .build/setup-android-sdk.js
 
 
       - name: 安装依赖
       - name: 安装依赖
         run: npm install --force --registry=https://registry.npmmirror.com/
         run: npm install --force --registry=https://registry.npmmirror.com/