Files
svn/tech/client/交接文档/谭健交接文档/Script/PocoInstaller/Poco/PocoInstaller.ts
2025-08-04 10:46:00 +08:00

89 lines
3.4 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import compressing from 'compressing';
import child_process from 'child_process';
import XXTea from './XXTea';
const XXTEA_KEY = 'ba5c2f3d-e52f-48';
const ANDROID_BUILD_TOOLS = 'D:\\Android\\SDK\\build-tools\\30.0.3';
const KEYSTOTE = path.join(__dirname, 'lib', 'keystore', 'fish.jks');
const KEYSTOTE_PASSWORD = 'fish123456';
const KEYSTOTE_ALIAS = 'paopaobuyu';
const KEYSTOTE_ALIAS_PASSWORD = 'fish123456';
const unzipApk = async (apkPath: string): Promise<void> => {
const dirPath = path.dirname(apkPath);
const outputPath = path.join(dirPath, '.___apk');
const newApkPath = path.join(dirPath, path.basename(apkPath, '.apk') + '_poco.apk');
console.log('创建输出目录');
fs.existsSync(outputPath) && removeFile(outputPath);
fs.mkdirSync(outputPath);
console.log('游戏解包');
await compressing.zip.uncompress(apkPath, outputPath);
console.log('删除证书');
removeFile(path.join(outputPath, 'META-INF'));
console.log('替换引擎库');
copyFile(path.join(__dirname, 'lib', 'so', 'libcocos2djs.so'), path.join(outputPath, 'lib', 'armeabi-v7a', 'libcocos2djs.so'));
console.log('添加PocoSDK');
copyFile(path.join(__dirname, 'lib', 'sdk', 'Poco.js'), path.join(outputPath, 'assets', 'Poco.js'));
console.log('修改入口脚本');
const scriptPath = path.join(outputPath, 'assets', 'main.js');
fs.existsSync(scriptPath) ? hackMain(scriptPath) : hackMain(scriptPath + 'c');
console.log('游戏打包');
removeFile(newApkPath);
await compressing.zip.compressDir(outputPath, newApkPath, { ignoreBase: true });
console.log('删除临时文件');
removeFile(outputPath);
console.log('游戏重新签名');
const signCmd = `${path.join(ANDROID_BUILD_TOOLS, 'apksigner')} sign --ks ${KEYSTOTE} --ks-pass pass:${KEYSTOTE_PASSWORD} --ks-key-alias ${KEYSTOTE_ALIAS} --key-pass pass:${KEYSTOTE_ALIAS_PASSWORD} ${newApkPath} `;
child_process.execSync(signCmd);
removeFile(newApkPath + '.idsig');
console.log('完成');
}
const removeFile = (filePath: string): void => {
if (!fs.existsSync(filePath)) return;
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
const subFiles = fs.readdirSync(filePath);
subFiles.forEach(value => removeFile(path.join(filePath, value)));
fs.rmdirSync(filePath);
} else {
fs.unlinkSync(filePath);
}
}
const copyFile = (filePath: string, destPath: string): void => {
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
fs.existsSync(destPath) || fs.mkdirSync(destPath);
const subFiles = fs.readdirSync(filePath);
subFiles.forEach(value => copyFile(path.join(filePath, value), path.join(destPath, value)));
} else {
fs.existsSync(destPath) && removeFile(destPath);
fs.copyFileSync(filePath, destPath);
}
}
const hackMain = (scriptPath: string, isEncrypt: boolean = false): void => {
let script = fs.readFileSync(scriptPath).toString();
if (isEncrypt) script = XXTea.decrypt(script, XXTEA_KEY);
script = script.replace(
'var launchScene = settings.launchScene;',
'var launchScene = settings.launchScene; \n' +
'require("Poco.js"); \n'
)
if (isEncrypt) script = XXTea.encrypt(script, XXTEA_KEY);
fs.writeFileSync(scriptPath, script);
}
const apkPath = process.argv[2];
unzipApk(apkPath);