cadb
Version:
安卓/鸿蒙系统截图/录屏工具
259 lines (239 loc) • 7.55 kB
JavaScript
/**
* Created by Niki on 2025/2/10 14:12.
* Email: m13296644326@163.com
*/
const path = require('path');
const program = require('commander');
const fs = require('fs');
const _ = require('lodash');
const {execFileSync} = require('child_process');
const {
maybeParseXTaroName,
getValueIgnoreCase,
ls2Array,
} = require('../common/utils/crnBundleUtil');
const {
getCurrModuleInfo,
adbPath,
rcPath,
deletePath,
} = require('../common/utils');
const {logRed, logGreen, shellConfigs} = require('../common/constants');
const qrcode = require('qrcode-terminal');
const bundleParentDir = path.join(process.cwd(), 'bundle_output');
const businessBundleName = 'rn_business.jsbundle';
const commonBundleName = 'common_android.hbc';
const bundlePublishPath = path.join(
bundleParentDir,
'publish',
businessBundleName,
);
const rnCommonBundlePath = path.join(
bundleParentDir,
'publish',
commonBundleName,
);
let finalBundlePath = '';
const adbRootPath = '/data/data/';
const deviceBundleDir = 'app_ctripwebapp5';
let outerFilePath = '';
program
// 使用中括号表示可选参数, 尖括号表示必选参数
.arguments('[filePath]')
// 如果加了 -c 参数, 则不会使用rcConfig的缓存了
.option('-pn --productName', 'Specify a product name')
.option('-c --isCtrip', 'insert to ctrip app')
.option('-z --isZhixing', 'insert to zhixing app')
.option('-zl --isZhixingLight', 'insert to zhixing travel app') // 智行旅行
// .option('-usejs --useJsBundleMode', 'use .jsbundle instead of .hbc') // 后续使用jsbundle模式
.action((filePath, arg) => {
outerFilePath = filePath;
run(arg);
})
.parse(process.argv);
function run(arg) {
const packName = parsePackName(arg);
const moduleName = arg.productName || readModuleName();
checkBundle(moduleName);
// const destPath = assembleAndCheckDestPath(packName, moduleName);
doAdbPush(packName, moduleName);
createQrCode(moduleName);
// adbPush(bundlePublishPath, path.join(destPath, 'rn_business.jsbundle'));
// deleteHermesConfigFile(arg, destPath);
// logGreen('crn bundle插入成功, 请重启app');
}
function checkBundle(moduleName) {
const isRnCommon = moduleName === 'rn_common';
// todo rn_common特殊处理
let tPath;
if (outerFilePath) {
tPath = path.join(outerFilePath, businessBundleName);
if (isRnCommon) {
tPath = path.join(outerFilePath, commonBundleName);
}
} else {
tPath = bundlePublishPath;
if (isRnCommon) {
tPath = rnCommonBundlePath;
}
}
if (!fs.existsSync(tPath)) {
logRed(`bundle文件不存在: ${bundlePublishPath}`);
process.exit();
} else if (isRnCommon) {
// 删除publish目录下除common_android.hbc和common_android.js以外的所有文件
const publishDir = path.dirname(tPath);
const files = fs.readdirSync(publishDir);
files.forEach(file => {
if (file !== commonBundleName && file !== 'common_android.js') {
const filePath = path.join(publishDir, file);
// fs.unlinkSync(filePath);
deletePath(filePath);
}
});
console.log(
`已删除publish目录下除${commonBundleName}和common_android.js以外的所有文件`,
);
}
if (!outerFilePath) {
const finalPath = path.join(bundleParentDir, moduleName);
if (fs.existsSync(finalPath)) {
deletePath(finalPath);
}
fs.renameSync(path.join(bundleParentDir, 'publish'), finalPath);
finalBundlePath = finalPath;
}
}
function parsePackName(arg) {
const {isCtrip, isZhixing, isZhixingLight} = arg;
if (isCtrip) {
return 'ctrip.android.view';
} else if (isZhixing) {
return 'com.yipiao';
} else if (isZhixingLight) {
return 'cn.suanya.zhixing';
}
// 默认返回智行
return 'com.yipiao';
}
/*
* 解析拿到productName
* */
function readModuleName() {
if (outerFilePath) {
return path.basename(outerFilePath);
}
let rcConfig = {};
if (!fs.existsSync(rcPath)) {
fs.writeFileSync(rcPath, JSON.stringify({}));
} else {
rcConfig = JSON.parse(fs.readFileSync(rcPath, 'utf-8'));
}
let {moduleName = ''} = getCurrModuleInfo();
// 如果是xTaro项目的moduleName, 则转换为crn频道名
moduleName = maybeParseXTaroName(moduleName);
console.log('moduleName', moduleName);
if (!moduleName.startsWith('rn_')) {
const moduleMaps = require('../config/module_map.json');
let prdName = getValueIgnoreCase(moduleMaps, moduleName);
const {exModuleMap = {}} = rcConfig;
if (!prdName) {
prdName = getValueIgnoreCase(exModuleMap, moduleName);
}
if (!prdName) {
// 如果仍找不到, 则怀疑是xTaro项目
prdName = maybeParseXTaroName('', true);
}
if (!prdName) {
logRed('未找到对应的crn频道名');
process.exit();
}
return prdName;
} else {
return moduleName;
}
}
// /data/data/com.yipiao/app_ctripwebapp5/rn_order
function assembleAndCheckDestPath(packName, moduleName) {
const destPath = path.join(
adbRootPath,
packName,
deviceBundleDir,
moduleName,
);
console.log(`destPath: ${destPath}`);
const lsResult = ls2Array(destPath, true);
if (!lsResult) {
logRed(
`crn目录不存在: ${deviceBundleDir}/${moduleName}, 请至少进入一次相关crn页面`,
);
process.exit();
}
if (_.isEmpty(lsResult)) {
logRed(
`crn目录不存在任何文件: ${deviceBundleDir}/${moduleName}, 请至少进入一次相关crn页面`,
);
process.exit();
}
return destPath;
}
// push到设备上app的cache目录
function doAdbPush(packName, moduleName) {
const destPath = path.join('/sdcard/Android/data', packName, 'cache');
const modulePath = path.join(destPath, moduleName);
// const cmd = ['push', localBundlePath, destPath];
const exist = ls2Array(modulePath, true);
if (exist) {
const cmd = ['shell', 'rm', '-r', modulePath];
console.log('execute:', `adb ${cmd.join(' ')}`);
const result = execFileSync(adbPath, cmd, shellConfigs);
console.log(result);
}
if (!outerFilePath) {
const mkDirCmd = ['shell', 'mkdir', '-p', modulePath];
console.log('execute:', `adb ${mkDirCmd.join(' ')}`);
const result = execFileSync(adbPath, mkDirCmd, shellConfigs);
console.log(result);
adbPush(finalBundlePath, destPath);
} else {
adbPush(outerFilePath, modulePath);
}
}
function adbPush(localBundlePath, destPath) {
const cmd = ['push', localBundlePath, destPath];
console.log('execute:', `adb ${cmd.join(' ')}`);
const result = execFileSync(adbPath, cmd, shellConfigs);
console.log(result);
}
function createQrCode(moduleName) {
// 在终端输出二维码
const qrText = `_copyRnBundle_://${JSON.stringify({
op: 'copy',
name: moduleName,
})}`;
qrcode.generate(qrText, {small: true}, qrBinary => {
console.log(qrBinary);
});
logGreen('请使用安卓手机扫码, 将bundle复制到work目录');
}
function deleteHermesConfigFile(arg, destPath) {
const {useJsBundleMode} = arg;
const cmdRmHbc = [
'shell',
'rm',
path.join(destPath, 'rn_business.hbcbundle'),
];
const hbcResult = execFileSync(adbPath, cmdRmHbc, shellConfigs);
console.log(hbcResult);
if (!useJsBundleMode) {
const cmdRmConfigV6 = [
'shell',
'rm',
path.join(destPath, '_crn_config_v6'),
];
const configV6Result = execFileSync(adbPath, cmdRmConfigV6, shellConfigs);
console.log(configV6Result);
} else {
console.log('由于设置了-usejs, 不删除_crn_config_v6文件');
}
}