publish_hwgame.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // v1.0.7
  2. const ideModuleDir = global.ideModuleDir;
  3. const workSpaceDir = global.workSpaceDir;
  4. //引用插件模块
  5. const gulp = require(ideModuleDir + "gulp");
  6. const fs = require("fs");
  7. const path = require("path");
  8. const https = require("https");
  9. const childProcess = require("child_process");
  10. const del = require(ideModuleDir + "del");
  11. const revCollector = require(ideModuleDir + 'gulp-rev-collector');
  12. const iconv = require(ideModuleDir + "iconv-lite");
  13. const request = require(ideModuleDir + "request");
  14. let copyLibsTask = ["copyPlatformLibsJsFile"];
  15. let versiontask = ["version2"];
  16. let
  17. config,
  18. releaseDir,
  19. toolkitPath,
  20. tempReleaseDir, // 华为临时拷贝目录
  21. projDir; // 华为快游戏工程目录
  22. let versionCon; // 版本管理version.json
  23. let commandSuffix,
  24. adbPath,
  25. opensslPath,
  26. layarepublicPath;
  27. let isDevices = false;
  28. // 创建华为项目前,拷贝华为引擎库、修改index.js
  29. gulp.task("preCreate_HW", copyLibsTask, function() {
  30. releaseDir = global.releaseDir;
  31. config = global.config;
  32. commandSuffix = global.commandSuffix;
  33. adbPath = global.adbPath;
  34. opensslPath = global.opensslPath;
  35. layarepublicPath = global.layarepublicPath;
  36. tempReleaseDir = global.tempReleaseDir;
  37. toolkitPath = path.join(layarepublicPath, "pub_huawei");
  38. });
  39. gulp.task("copyPlatformFile_HW", ["preCreate_HW"], function() {
  40. let hwAdapterPath = path.join(layarepublicPath, "LayaAirProjectPack", "lib", "data", "hwfiles");
  41. let copyLibsList = [`${hwAdapterPath}/**/*.*`];
  42. var stream = gulp.src(copyLibsList);
  43. return stream.pipe(gulp.dest(tempReleaseDir));
  44. });
  45. // 新建华为项目-华为项目与其他项目不同,需要安装华为 quickgame node_modules,并打包成.rpk文件
  46. gulp.task("installModules_HW", versiontask, function() {
  47. releaseDir = path.dirname(releaseDir);
  48. projDir = path.join(releaseDir, config.hwInfo.projName);
  49. // 如果IDE里对应华为包已经install node_modules了,忽略这一步
  50. if (fs.existsSync(path.join(toolkitPath, "node_modules"))) {
  51. return;
  52. }
  53. // 安装华为 quickgame node_modules
  54. return new Promise((resolve, reject) => {
  55. console.log("开始安装华为 toolkit node_modules,请耐心等待...");
  56. let cmd = `npm${commandSuffix}`;
  57. let args = ["install"];
  58. let opts = {
  59. cwd: toolkitPath,
  60. shell: true
  61. };
  62. let cp = childProcess.spawn(cmd, args, opts);
  63. cp.stdout.on('data', (data) => {
  64. console.log(`stdout: ${data}`);
  65. });
  66. cp.stderr.on('data', (data) => {
  67. console.log(`stderr: ${data}`);
  68. // reject();
  69. });
  70. cp.on('close', (code) => {
  71. console.log(`子进程退出码:${code}`);
  72. resolve();
  73. });
  74. });
  75. });
  76. // 拷贝文件到华为快游戏
  77. gulp.task("copyFileToProj_HW", ["installModules_HW"], function() {
  78. // 将临时文件夹中的文件,拷贝到项目中去
  79. let originalDir = `${tempReleaseDir}/**/*.*`;
  80. let stream = gulp.src(originalDir);
  81. return stream.pipe(gulp.dest(path.join(projDir)));
  82. });
  83. // 拷贝icon到华为快游戏
  84. gulp.task("copyIconToProj_HW", ["copyFileToProj_HW"], function() {
  85. let originalDir = config.hwInfo.icon;
  86. let stream = gulp.src(originalDir);
  87. return stream.pipe(gulp.dest(path.join(projDir)));
  88. });
  89. // 清除华为快游戏临时目录
  90. gulp.task("clearTempDir_HW", ["copyIconToProj_HW"], function() {
  91. // 删掉临时目录
  92. return del([tempReleaseDir], { force: true });
  93. });
  94. // 生成release签名(私钥文件 private.pem 和证书文件 certificate.pem )
  95. gulp.task("generateSign_HW", ["clearTempDir_HW"], function() {
  96. if (!config.hwSign.generateSign) {
  97. return;
  98. }
  99. // https://doc.quickapp.cn/tools/compiling-tools.html
  100. return new Promise((resolve, reject) => {
  101. let cmd = `${opensslPath}`;
  102. let args = ["req", "-newkey", "rsa:2048", "-nodes", "-keyout", "private.pem",
  103. "-x509", "-days", "3650", "-out", "certificate.pem"];
  104. let opts = {
  105. cwd: projDir,
  106. shell: true
  107. };
  108. let cp = childProcess.spawn(cmd, args, opts);
  109. cp.stdout.on('data', (data) => {
  110. console.log(`stdout: ${data}`);
  111. });
  112. cp.stderr.on('data', (data) => {
  113. console.log(`stderr: ${data}`);
  114. data += "";
  115. if (data.includes("Country Name")) {
  116. cp.stdin.write(`${config.hwSign.countryName}\n`);
  117. console.log(`Country Name: ${config.hwSign.countryName}`);
  118. } else if (data.includes("Province Name")) {
  119. cp.stdin.write(`${config.hwSign.provinceName}\n`);
  120. console.log(`Province Name: ${config.hwSign.provinceName}`);
  121. } else if (data.includes("Locality Name")) {
  122. cp.stdin.write(`${config.hwSign.localityName}\n`);
  123. console.log(`Locality Name: ${config.hwSign.localityName}`);
  124. } else if (data.includes("Organization Name")) {
  125. cp.stdin.write(`${config.hwSign.orgName}\n`);
  126. console.log(`Organization Name: ${config.hwSign.orgName}`);
  127. } else if (data.includes("Organizational Unit Name")) {
  128. cp.stdin.write(`${config.hwSign.orgUnitName}\n`);
  129. console.log(`Organizational Unit Name: ${config.hwSign.orgUnitName}`);
  130. } else if (data.includes("Common Name")) {
  131. cp.stdin.write(`${config.hwSign.commonName}\n`);
  132. console.log(`Common Name: ${config.hwSign.commonName}`);
  133. } else if (data.includes("Email Address")) {
  134. cp.stdin.write(`${config.hwSign.emailAddr}\n`);
  135. console.log(`Email Address: ${config.hwSign.emailAddr}`);
  136. // cp.stdin.end();
  137. }
  138. // reject();
  139. });
  140. cp.on('close', (code) => {
  141. console.log(`子进程退出码:${code}`);
  142. // 签名是否生成成功
  143. let
  144. privatePem = path.join(projDir, "private.pem"),
  145. certificatePem = path.join(projDir, "certificate.pem");
  146. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  147. if (!isSignExits) {
  148. throw new Error("签名生成失败,请检查!");
  149. }
  150. resolve();
  151. });
  152. });
  153. });
  154. // 拷贝sign文件到指定位置
  155. gulp.task("copySignFile_HW", ["generateSign_HW"], function() {
  156. // debug签名拷贝,默认拷贝
  157. let
  158. privatePem = path.join(toolkitPath, "sign", "debug", "private.pem"),
  159. certificatePem = path.join(toolkitPath, "sign", "debug", "certificate.pem");
  160. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  161. if (!isSignExits) {
  162. return;
  163. }
  164. let
  165. signDest = `${projDir}/sign/debug`;
  166. let stream = gulp.src([privatePem, certificatePem]);
  167. stream.pipe(gulp.dest(signDest));
  168. if (config.hwSign.generateSign) { // 新生成的签名
  169. // 移动签名文件到项目中(Laya & 华为快游戏项目中)
  170. let
  171. privatePem = path.join(projDir, "private.pem"),
  172. certificatePem = path.join(projDir, "certificate.pem");
  173. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  174. if (!isSignExits) {
  175. return;
  176. }
  177. let
  178. xiaomiDest = `${projDir}/sign/release`,
  179. layaDest = `${workSpaceDir}/sign/release`;
  180. let stream = gulp.src([privatePem, certificatePem]);
  181. return stream.pipe(gulp.dest(xiaomiDest))
  182. .pipe(gulp.dest(layaDest));
  183. } else if (config.hwInfo.useReleaseSign && !config.hwSign.generateSign) { // 使用release签名,并且没有重新生成
  184. // 从项目中将签名拷贝到华为快游戏项目中
  185. let
  186. privatePem = path.join(workSpaceDir, "sign", "release", "private.pem"),
  187. certificatePem = path.join(workSpaceDir, "sign", "release", "certificate.pem");
  188. let isSignExits = fs.existsSync(privatePem) && fs.existsSync(certificatePem);
  189. if (!isSignExits) {
  190. return;
  191. }
  192. let
  193. xiaomiDest = `${projDir}/sign/release`;
  194. let stream = gulp.src([privatePem, certificatePem]);
  195. return stream.pipe(gulp.dest(xiaomiDest));
  196. }
  197. });
  198. gulp.task("deleteSignFile_HW", ["copySignFile_HW"], function() {
  199. if (config.hwSign.generateSign) { // 新生成的签名
  200. let
  201. privatePem = path.join(projDir, "private.pem"),
  202. certificatePem = path.join(projDir, "certificate.pem");
  203. return del([privatePem, certificatePem], { force: true });
  204. }
  205. });
  206. gulp.task("modifyFile_HW", ["deleteSignFile_HW"], function() {
  207. // 修改manifest.json文件
  208. let manifestPath = path.join(projDir, "manifest.json");
  209. let manifestJson;
  210. if (fs.existsSync(manifestPath)) {
  211. let manifestContent = fs.readFileSync(manifestPath, "utf8");
  212. manifestJson = JSON.parse(manifestContent);
  213. } else {
  214. manifestJson = {
  215. "package": "",
  216. "name": "",
  217. "appType": "fastgame",
  218. "icon": "",
  219. "versionName": "",
  220. "versionCode": 0,
  221. "minPlatformVersion": 1000,
  222. "config": {
  223. "logLevel": "off"
  224. },
  225. "display": {
  226. "orientation": "portrait"
  227. }
  228. }
  229. }
  230. manifestJson.package = config.hwInfo.package;
  231. manifestJson.name = config.hwInfo.name;
  232. manifestJson.display.orientation = config.hwInfo.orientation;
  233. manifestJson.config.logLevel = config.hwInfo.logLevel || "off";
  234. manifestJson.versionName = config.hwInfo.versionName;
  235. manifestJson.versionCode = config.hwInfo.versionCode;
  236. manifestJson.minPlatformVersion = config.hwInfo.minPlatformVersion;
  237. manifestJson.icon = `/${path.basename(config.hwInfo.icon)}`;
  238. if (config.hwInfo.subpack) {
  239. let hwSubpackList = [];
  240. for (let i = 0, len = config.hwSubpack.length; i < len; i++) {
  241. hwSubpackList.push({
  242. name: config.hwSubpack[i].name,
  243. resource: config.hwSubpack[i].root
  244. })
  245. }
  246. manifestJson.subpackages = hwSubpackList;
  247. // 检测分包目录是否有入口文件
  248. console.log('检查分包文件...');
  249. if (manifestJson.subpackages) {
  250. for(let i = 0; i < manifestJson.subpackages.length; i ++) {
  251. let conf = manifestJson.subpackages[i];
  252. if (conf.name) {
  253. let rootPath = path.join(projDir, conf.name);
  254. if (!fs.existsSync(rootPath)) {
  255. throw new Error(`分包文件/目录 ${rootPath} 不存在!`);
  256. }
  257. let jsPath = path.join(rootPath, 'game.js'); ;
  258. if (!fs.existsSync(jsPath)) {
  259. throw new Error(`分包文件/目录 ${jsPath} 不存在!`);
  260. }
  261. }
  262. }
  263. }
  264. } else {
  265. delete manifestJson.subpackages;
  266. }
  267. fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 4), "utf8");
  268. if (config.version) {
  269. let versionPath = projDir + "/version.json";
  270. versionCon = fs.readFileSync(versionPath, "utf8");
  271. versionCon = JSON.parse(versionCon);
  272. }
  273. let indexJsStr = (versionCon && versionCon["index.js"]) ? versionCon["index.js"] : "index.js";
  274. // 华为项目,修改game.js
  275. let filePath = path.join(projDir, "game.js");
  276. if (!fs.existsSync(filePath)) {
  277. let fileContent = `require("./huawei-adapter.js");\nrequire("./libs/laya.hwmini.js");\nrequire("index.js");`;
  278. fs.writeFileSync(filePath, fileContent, "utf8");
  279. }
  280. // 华为项目,修改index.js
  281. let indexFilePath = path.join(projDir, indexJsStr);
  282. if (!fs.existsSync(indexFilePath)) {
  283. return;
  284. }
  285. let indexFileContent = fs.readFileSync(indexFilePath, "utf8");
  286. indexFileContent = indexFileContent.replace(/loadLib(\(['"])/gm, "require$1./");
  287. fs.writeFileSync(indexFilePath, indexFileContent, "utf8");
  288. });
  289. gulp.task("modifyMinJs_HW", ["modifyFile_HW"], function() {
  290. let fileJsPath = path.join(projDir, "game.js");
  291. let content = fs.readFileSync(fileJsPath, "utf-8");
  292. if (!config.useMinJsLibs) { // 默认保留了平台文件,如果同时取消使用min类库,就会出现文件引用不正确的问题
  293. content = content.replace(/min\/laya(-[\w\d]+)?\.hwmini\.min\.js/gm, "laya.hwmini.js");
  294. } else {
  295. content = content.replace(/(min\/)?laya(-[\w\d]+)?\.hwmini(\.min)?\.js/gm, "min/laya.hwmini.min.js");
  296. }
  297. fs.writeFileSync(fileJsPath, content, 'utf-8');
  298. });
  299. gulp.task("version_HW", ["modifyMinJs_HW"], function () {
  300. // main.js默认不覆盖,如果同时开启版本管理,就会出现文件引用不正确的问题
  301. let fileJsPath = path.join(projDir, "game.js");
  302. let content = fs.readFileSync(fileJsPath, "utf-8");
  303. content = content.replace(/laya(-[\w\d]+)?\.hwmini/gm, "laya.hwmini");
  304. content = content.replace(/index(-[\w\d]+)?\.js/gm, "index.js");
  305. fs.writeFileSync(fileJsPath, content, 'utf-8');
  306. if (config.version) {
  307. let versionPath = projDir + "/version.json";
  308. let mainJSPath = projDir + "/game.js";
  309. let srcList = [versionPath, mainJSPath];
  310. return gulp.src(srcList)
  311. .pipe(revCollector())
  312. .pipe(gulp.dest(projDir));
  313. }
  314. });
  315. // 打包rpk
  316. gulp.task("buildRPK_HW", ["version_HW"], function() {
  317. // 在华为快游戏项目目录中执行:
  318. // node .\signtool\package\index.js .\web .\dist com.demo .\release\private.pem .\release\certificate.pem
  319. let
  320. signtoolPath = path.join(toolkitPath, "index.js"),
  321. releasePath = projDir,
  322. distPath = path.join(projDir, "dist"),
  323. name = config.hwInfo.package,
  324. privatePem = path.join(projDir, "sign", "debug", "private.pem"),
  325. certificatePemPath = path.join(projDir, "sign", "debug", "certificate.pem");
  326. if (config.hwInfo.useReleaseSign) {
  327. privatePem = path.join(projDir, "sign", "release", "private.pem"),
  328. certificatePemPath = path.join(projDir, "sign", "release", "certificate.pem");
  329. }
  330. return new Promise((resolve, reject) => {
  331. let cmd = `node`;
  332. let args = [`"${signtoolPath}"`, `"${releasePath}"`, `"${distPath}"`, name, `"${privatePem}"`, `"${certificatePemPath}"`];
  333. let opts = {
  334. cwd: projDir,
  335. shell: true
  336. };
  337. let cp = childProcess.spawn(cmd, args, opts);
  338. // let cp = childProcess.spawn('npx.cmd', ['-v']);
  339. cp.stdout.on('data', (data) => {
  340. console.log(`stdout: ${data}`);
  341. });
  342. cp.stderr.on('data', (data) => {
  343. console.log(`stderr: ${data}`);
  344. console.log(`stderr(iconv): ${iconv.decode(data, 'gbk')}`);
  345. // reject();
  346. });
  347. cp.on('close', (code) => {
  348. console.log(`子进程退出码:${code}`);
  349. // rpk是否生成成功
  350. let distRpkPath = path.join(distPath, `${name}.rpk`);
  351. if (!fs.existsSync(distRpkPath)) {
  352. throw new Error("rpk生成失败,请检查!");
  353. }
  354. resolve();
  355. });
  356. });
  357. });
  358. gulp.task("getDevices_HW", ["buildRPK_HW"], function(cb) {
  359. let cmd = `${adbPath} devices`;
  360. childProcess.exec(cmd, (error, stdout, stderr) => {
  361. if (error) {
  362. console.error("获取设备失败...");
  363. return cb();
  364. }
  365. if (stdout && stdout.match(/\bdevice\b/)) {
  366. isDevices = true;
  367. }
  368. console.log(`检测到设备: ${isDevices}`);
  369. return cb();
  370. });
  371. });
  372. // 更新快应用加载器
  373. gulp.task("updateAPK_HW", ["getDevices_HW"], function(cb) {
  374. if (!config.hwInfo.apkUpdate || !isDevices) {
  375. return cb();
  376. }
  377. let remoteInfo, remoteAPKVer, localAPKVer;
  378. new Promise((resolve, reject) => {
  379. https.get('https://deveco.huawei.com/FastIDE/update/api/update/engineVersion/', (res) => {
  380. res.on('data', (data) => {
  381. remoteInfo = JSON.parse(data);
  382. remoteAPKVer = remoteInfo.version;
  383. console.log("remote apk version: ", remoteAPKVer);
  384. resolve();
  385. });
  386. }).on('error', (e) => {
  387. reject(`获取远端快应用加载器失败: ${e}`);
  388. });
  389. }).then(() => {
  390. return new Promise((resolve, reject) => {
  391. // Unable为找不到快应用加载器
  392. let cmd = `${adbPath} shell dumpsys package com.huawei.fastapp.dev | `;
  393. if (process.platform === "darwin") {
  394. cmd += `grep "versionName\\|Unable"`;
  395. } else {
  396. cmd += `findstr "versionName Unable"`
  397. }
  398. childProcess.exec(cmd, (error, stdout, stderr) => {
  399. if (stdout && stdout.indexOf("Unable") >= 0) {
  400. // 未安装
  401. localAPKVer = '0.0.0.0_dev';
  402. console.log("未安装快应用加载器");
  403. return resolve();
  404. }
  405. if (error) {
  406. console.log("获取快应用加载器本地版本号失败: ");
  407. console.log(error);
  408. console.log(stderr);
  409. return resolve(error);
  410. }
  411. let matchList = stdout.match(/versionName=(.+)/);
  412. if (!Array.isArray(matchList)) {
  413. console.log("获取快应用加载器本地版本号失败: ");
  414. return resolve();
  415. }
  416. localAPKVer = matchList[1];
  417. console.log("local apk version: ", localAPKVer);
  418. resolve();
  419. });
  420. });
  421. }).then(() => {
  422. return new Promise((resolve, reject) => {
  423. if (remoteAPKVer === localAPKVer || donotUpdate(remoteAPKVer, localAPKVer)) {
  424. console.log("您的快应用加载器是最新版本!");
  425. return resolve();
  426. }
  427. let url = remoteInfo.url;
  428. let apkName = path.basename(url);
  429. let apkDownRoot = path.join(toolkitPath, "fastapp");
  430. let apkDownPath = path.join(apkDownRoot, apkName);
  431. // 1) 如果本地已经有最新版本的快应用加载器,则不再下载
  432. if (fs.existsSync(apkDownPath)) {
  433. console.log("您本地有最新版本的快应用加载器,将直接安装!");
  434. return installAPK().then(() => {
  435. return resolve();
  436. }).catch((err) => {
  437. return reject(err);
  438. })
  439. }
  440. // 2) 下载并安装快应用加载器
  441. console.log("正在下载快应用加载器,请稍等...");
  442. !(fs.existsSync(apkDownRoot)) && fs.mkdirSync(apkDownRoot);
  443. downFileToDir(url, apkDownPath).then(() => {
  444. return installAPK();
  445. }).then(() => {
  446. return resolve();
  447. }).catch((err) => {
  448. return reject(err);
  449. })
  450. // 安装apk
  451. function installAPK() {
  452. return new Promise((resolve, reject) => {
  453. console.log("正在安装快应用加载器,请稍等...");
  454. let cmd = `${adbPath} install -r ${apkDownPath}`;
  455. childProcess.exec(cmd, (error, stdout, stderr) => {
  456. if (error) {
  457. console.error("安装快应用加载器本地版本号失败: ");
  458. console.error(error);
  459. console.error(stderr);
  460. return reject(error);
  461. }
  462. console.log("安装快应用加载器成功!");
  463. resolve();
  464. });
  465. })
  466. }
  467. });
  468. }).then(() => {
  469. return cb();
  470. }).catch((re) => {
  471. console.error("更新快应用加载器失败: ", re);
  472. return cb();
  473. });
  474. });
  475. function downFileToDir(uri, dest){
  476. return new Promise((resolve, reject) => {
  477. if (!uri || !dest) {
  478. reject(new Error(`downFileToDir 参数不全: ${uri}/${dest}`));
  479. return;
  480. }
  481. let
  482. totalLen = 9999,
  483. progress = 0,
  484. layaresponse;
  485. var stream = fs.createWriteStream(dest);
  486. request(uri).on('error', function(err) {
  487. console.log("tool down err:" + err);
  488. reject(err);
  489. }).on("data", function(data) {
  490. progress += data.length;
  491. let downPercent = (progress / totalLen * 100).toFixed(3);
  492. // console.log(`down: ${downPercent}%`);
  493. }).on("response", function(response) {
  494. layaresponse = response;
  495. totalLen = response.caseless.dict['content-length'];
  496. }).pipe(stream).on('close', function() {
  497. if (layaresponse.statusCode == 200) {
  498. console.log("下载成功!");
  499. resolve();
  500. } else {
  501. reject(new Error("下载失败,连接关闭"));
  502. }
  503. });
  504. });
  505. }
  506. gulp.task("pushRPK_HW", ["updateAPK_HW"], function() {
  507. if (!config.hwInfo.adbDebug || !isDevices) {
  508. return;
  509. }
  510. // 在华为快游戏项目目录中执行:
  511. // adb shell am force-stop com.huawei.fastapp.dev
  512. // adb push {rpk_file_path} /data/local/tmp/
  513. // adb shell am start --es rpkpath /data/local/tmp/{rpk_file_name} --ei debugmode 1 --activity-clear-top com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity
  514. return new Promise((resolve, reject) => {
  515. // adb shell am force-stop com.huawei.fastapp.dev
  516. console.log(`1) force-stop: `);
  517. let cmd = `${adbPath}`;
  518. let args = ["shell", "am", "force-stop", "com.huawei.fastapp.dev"];
  519. let opts = {
  520. cwd: projDir,
  521. shell: true
  522. };
  523. let cp = childProcess.spawn(cmd, args, opts);
  524. // let cp = childProcess.spawn('npx.cmd', ['-v']);
  525. cp.stdout.on('data', (data) => {
  526. console.log(`stdout: ${data}`);
  527. });
  528. cp.stderr.on('data', (data) => {
  529. console.log(`stderr: ${data}`);
  530. // reject();
  531. });
  532. cp.on('close', (code) => {
  533. console.log(`force-stop 子进程退出码:${code}`);
  534. resolve();
  535. });
  536. }).then(() => {
  537. return new Promise((resolve, reject) => {
  538. // adb push {rpk_file_path} /data/local/tmp/
  539. console.log(`2) push_RPK: `);
  540. let rpkFilePath = path.join(projDir, "dist", `${config.hwInfo.package}.rpk`);
  541. let cmd = `${adbPath}`;
  542. let args = ["push", `"${rpkFilePath}"`, "/data/local/tmp/"];
  543. let opts = {
  544. cwd: projDir,
  545. shell: true
  546. };
  547. let cp = childProcess.spawn(cmd, args, opts);
  548. // let cp = childProcess.spawn('npx.cmd', ['-v']);
  549. cp.stdout.on('data', (data) => {
  550. console.log(`stdout: ${data}`);
  551. });
  552. cp.stderr.on('data', (data) => {
  553. console.log(`stderr: ${data}`);
  554. // reject();
  555. });
  556. cp.on('close', (code) => {
  557. console.log(`push_RPK 子进程退出码:${code}`);
  558. resolve();
  559. });
  560. });
  561. }).then(() => {
  562. return new Promise((resolve, reject) => {
  563. // adb shell am start --es rpkpath /data/local/tmp/{rpk_file_name} --ei debugmode 1 --activity-clear-top com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity
  564. console.log(`3) 启动apk,加载rpk: `);
  565. let cmd = `${adbPath}`;
  566. let args = ["shell", "am", "start", "--es", "rpkpath", `file://data/local/tmp/${config.hwInfo.package}.rpk`, "--ei", "debugmode", "1", "--activity-clear-top", "com.huawei.fastapp.dev/com.huawei.fastapp.app.RpkRunnerActivity"];
  567. let opts = {
  568. cwd: projDir,
  569. shell: true
  570. };
  571. let cp = childProcess.spawn(cmd, args, opts);
  572. // let cp = childProcess.spawn('npx.cmd', ['-v']);
  573. cp.stdout.on('data', (data) => {
  574. console.log(`stdout: ${data}`);
  575. });
  576. cp.stderr.on('data', (data) => {
  577. console.log(`stderr: ${data}`);
  578. // reject();
  579. });
  580. cp.on('close', (code) => {
  581. console.log(`启动apk,加载rpk: 子进程退出码:${code}`);
  582. resolve();
  583. });
  584. });
  585. });
  586. });
  587. function donotUpdate(remoteAPKVer, localAPKVer) {
  588. let remoteAPKVerN = remoteAPKVer.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)/);
  589. let localAPKVerN = localAPKVer.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)/);
  590. let
  591. l1n = Number(localAPKVerN[1]), // local first number
  592. l2n = Number(localAPKVerN[2]),
  593. l3n = Number(localAPKVerN[3]),
  594. l4n = Number(localAPKVerN[4]),
  595. r1n = Number(remoteAPKVerN[1]), // remote first number
  596. r2n = Number(remoteAPKVerN[2]),
  597. r3n = Number(remoteAPKVerN[3]);
  598. r4n = Number(remoteAPKVerN[4]);
  599. if (l1n > r1n) {
  600. return true;
  601. }
  602. if (l1n === r1n && l2n > r2n) {
  603. return true;
  604. }
  605. if (l1n === r1n && l2n === r2n && l3n > r3n) {
  606. return true;
  607. }
  608. if (l1n === r1n && l2n === r2n && l3n === r3n && l4n >= r4n) {
  609. return true;
  610. }
  611. return false;
  612. }
  613. gulp.task("buildHWProj", ["pushRPK_HW"], function() {
  614. console.log("all tasks completed");
  615. });