Skip to content

Commit 8e4b9c4

Browse files
committed
extractapk
# Conflicts: # src/package.ts
1 parent 6b68f46 commit 8e4b9c4

16 files changed

Lines changed: 568 additions & 347 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ Each workflow step contains:
227227
- `parseApp`: Parse APP file information
228228
- `parseIpa`: Parse IPA file information
229229
- `parseApk`: Parse APK file information
230+
- `extractApk`: Extract a universal APK from an AAB (supports `--output`, `--includeAllSplits`, `--splits`)
230231
- `packages`: List packages
231232

232233
### User Module (`user`)

README.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ const workflowResult = await moduleManager.executeWorkflow('my-workflow', {
225225
- `parseApp`: 解析 APP 文件信息
226226
- `parseIpa`: 解析 IPA 文件信息
227227
- `parseApk`: 解析 APK 文件信息
228+
- `extractApk`: 从 AAB 提取通用 APK(支持 `--output``--includeAllSplits``--splits`
228229
- `packages`: 列出包
229230

230231
### User 模块 (`user`)

cli.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@
5656
"parseIpa": {},
5757
"parseApk": {},
5858
"parseAab": {},
59+
"extractApk": {
60+
"options": {
61+
"output": {
62+
"hasValue": true
63+
},
64+
"includeAllSplits": {
65+
"default": false
66+
},
67+
"splits": {
68+
"hasValue": true
69+
}
70+
}
71+
},
5972
"packages": {
6073
"options": {
6174
"platform": {

src/api.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ import FormData from 'form-data';
66
import fetch from 'node-fetch';
77
import ProgressBar from 'progress';
88
import tcpp from 'tcp-ping';
9+
import { getBaseUrl } from 'utils/http-helper';
910
import packageJson from '../package.json';
1011
import type { Package, Session } from './types';
11-
import {
12-
credentialFile,
13-
pricingPageUrl,
14-
} from './utils/constants';
12+
import { credentialFile, pricingPageUrl } from './utils/constants';
1513
import { t } from './utils/i18n';
16-
import { getBaseUrl } from 'utils/http-helper';
1714

1815
const tcpPing = util.promisify(tcpp.ping);
1916

2017
let session: Session | undefined;
2118
let savedSession: Session | undefined;
2219

23-
2420
const userAgent = `react-native-update-cli/${packageJson.version}`;
2521

2622
export const getSession = () => session;

src/locales/en.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
116116
usageDiff: 'Usage: cresc {{command}} <origin> <next>',
117117
usageParseApk: 'Usage: cresc parseApk <apk file>',
118118
usageParseAab: 'Usage: cresc parseAab <aab file>',
119+
usageExtractApk:
120+
'Usage: cresc extractApk <aab file> [--output <apk file>] [--includeAllSplits] [--splits <split names>]',
119121
usageParseApp: 'Usage: cresc parseApp <app file>',
120122
usageParseIpa: 'Usage: cresc parseIpa <ipa file>',
121123
usageUnderDevelopment: 'Usage is under development now.',
@@ -147,4 +149,5 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
147149
'This function needs "node-bsdiff". Please run "{{scriptName}} install node-bsdiff" to install',
148150
nodeHdiffpatchRequired:
149151
'This function needs "node-hdiffpatch". Please run "{{scriptName}} install node-hdiffpatch" to install',
152+
apkExtracted: 'APK extracted to {{output}}',
150153
};

src/locales/zh.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ export default {
110110
usageDiff: '用法:pushy {{command}} <origin> <next>',
111111
usageParseApk: '使用方法: pushy parseApk apk后缀文件',
112112
usageParseAab: '使用方法: pushy parseAab aab后缀文件',
113+
usageExtractApk:
114+
'使用方法: pushy extractApk aab后缀文件 [--output apk文件] [--includeAllSplits] [--splits 分包名列表]',
113115
usageParseApp: '使用方法: pushy parseApp app后缀文件',
114116
usageParseIpa: '使用方法: pushy parseIpa ipa后缀文件',
115117
usageUploadApk: '使用方法: pushy uploadApk apk后缀文件',
@@ -138,4 +140,5 @@ export default {
138140
'此功能需要 "node-bsdiff"。请运行 "{{scriptName}} install node-bsdiff" 来安装',
139141
nodeHdiffpatchRequired:
140142
'此功能需要 "node-hdiffpatch"。请运行 "{{scriptName}} install node-hdiffpatch" 来安装',
143+
apkExtracted: 'APK 已提取到 {{output}}',
141144
};

src/modules/version-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CLIModule} from '../types';
1+
import type { CLIModule } from '../types';
22

33
export const versionModule: CLIModule = {
44
name: 'version',

src/package.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { getAllPackages, post, uploadFile, doDelete } from './api';
22
import { question, saveToLocal } from './utils';
3-
import { t } from './utils/i18n';
43

54
import { getPlatform, getSelectedApp } from './app';
6-
75
import Table from 'tty-table';
86
import type { Platform } from './types';
9-
import { getApkInfo, getAppInfo, getIpaInfo, getAabInfo } from './utils';
7+
import { getAabInfo, getApkInfo, getAppInfo, getIpaInfo } from './utils';
108
import { depVersions } from './utils/dep-versions';
119
import { getCommitInfo } from './utils/git';
10+
import AabParser from './utils/app-info-parser/aab';
11+
import { t } from './utils/i18n';
12+
import path from 'path';
1213

1314
export async function listPackage(appId: string) {
1415
const allPkgs = await getAllPackages(appId) || [];
@@ -214,6 +215,42 @@ export const packageCommands = {
214215
}
215216
console.log(await getAabInfo(fn));
216217
},
218+
extractApk: async ({
219+
args,
220+
options,
221+
}: {
222+
args: string[];
223+
options: Record<string, any>;
224+
}) => {
225+
const source = args[0];
226+
if (!source || !source.endsWith('.aab')) {
227+
throw new Error(t('usageExtractApk'));
228+
}
229+
230+
const output =
231+
options.output ||
232+
path.join(
233+
path.dirname(source),
234+
`${path.basename(source, path.extname(source))}.apk`,
235+
);
236+
237+
const includeAllSplits =
238+
options.includeAllSplits === true || options.includeAllSplits === 'true';
239+
const splits = options.splits
240+
? String(options.splits)
241+
.split(',')
242+
.map((item) => item.trim())
243+
.filter(Boolean)
244+
: null;
245+
246+
const parser = new AabParser(source);
247+
await parser.extractApk(output, {
248+
includeAllSplits,
249+
splits,
250+
});
251+
252+
console.log(t('apkExtracted', { output }));
253+
},
217254
packages: async ({ options }: { options: { platform: Platform } }) => {
218255
const platform = await getPlatform(options.platform);
219256
const { appId } = await getSelectedApp(platform);

0 commit comments

Comments
 (0)