Skip to content

Commit 9c37e12

Browse files
authored
feat(sign:android): support passing key alias (#267)
* feat(sign:android): support passing key alias * changeset
1 parent de24926 commit 9c37e12

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

.changeset/tall-days-flash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rnef/platform-android': patch
3+
---
4+
5+
feat(sign:android): support passing key alias

packages/platform-android/src/lib/commands/signAndroid/command.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export type SignFlags = {
77
output?: string;
88
keystore?: string;
99
keystorePassword?: string;
10+
keyAlias?: string;
11+
keyPassword?: string;
1012
buildJsbundle?: boolean;
1113
jsbundle?: string;
1214
noHermes?: boolean;
@@ -32,6 +34,14 @@ const OPTIONS = [
3234
name: '--keystore-password <string>',
3335
description: 'Password for keystore file',
3436
},
37+
{
38+
name: '--key-alias <string>',
39+
description: 'Alias for key in keystore file',
40+
},
41+
{
42+
name: '--key-password <string>',
43+
description: 'Password for key in keystore file',
44+
},
3545
{
3646
name: '--output <string>',
3747
description: 'Path to the output APK file.',
@@ -61,6 +71,8 @@ export const registerSignCommand = (api: PluginApi) => {
6171
apkPath,
6272
keystorePath: flags.keystore,
6373
keystorePassword: flags.keystorePassword,
74+
keyAlias: flags.keyAlias,
75+
keyPassword: flags.keyPassword,
6476
outputPath: flags.output,
6577
buildJsBundle: flags.buildJsbundle,
6678
jsBundlePath: flags.jsbundle,

packages/platform-android/src/lib/commands/signAndroid/signAndroid.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'node:fs';
22
import path from 'node:path';
3+
import type { SubprocessError } from '@rnef/tools';
34
import {
45
color,
56
getDotRnefPath,
@@ -18,6 +19,8 @@ export type SignAndroidOptions = {
1819
apkPath: string;
1920
keystorePath?: string;
2021
keystorePassword?: string;
22+
keyAlias?: string;
23+
keyPassword?: string;
2124
outputPath?: string;
2225
buildJsBundle?: boolean;
2326
jsBundlePath?: string;
@@ -63,14 +66,13 @@ export async function signAndroid(options: SignAndroidOptions) {
6366
loader.start('Initializing output APK...');
6467
try {
6568
const zip = new AdmZip(options.apkPath);
69+
// Remove old signature files
6670
zip.deleteFile('META-INF/*');
6771
zip.writeZip(tempApkPath);
6872
} catch (error) {
6973
throw new RnefError(
7074
`Failed to initialize output APK file: ${options.outputPath}`,
71-
{
72-
cause: error,
73-
}
75+
{ cause: (error as SubprocessError).stderr }
7476
);
7577
}
7678
loader.stop(`Initialized output APK.`);
@@ -104,6 +106,8 @@ export async function signAndroid(options: SignAndroidOptions) {
104106
apkPath: outputApkPath,
105107
keystorePath,
106108
keystorePassword: options.keystorePassword ?? 'pass:android',
109+
keyAlias: options.keyAlias,
110+
keyPassword: options.keyPassword,
107111
});
108112
loader.stop(
109113
`Signed the APK file with keystore: ${color.cyan(keystorePath)}.`
@@ -145,9 +149,7 @@ async function replaceJsBundle({
145149
} catch (error) {
146150
throw new RnefError(
147151
`Failed to replace JS bundle in destination file: ${apkPath}}`,
148-
{
149-
cause: error,
150-
}
152+
{ cause: (error as SubprocessError).stderr }
151153
);
152154
}
153155
}
@@ -185,9 +187,7 @@ Please follow instructions at: https://reactnative.dev/docs/set-up-your-environm
185187
} catch (error) {
186188
throw new RnefError(
187189
`Failed to align APK file: ${zipAlignPath} ${zipalignArgs.join(' ')}`,
188-
{
189-
cause: error,
190-
}
190+
{ cause: (error as SubprocessError).stderr }
191191
);
192192
}
193193
}
@@ -196,12 +196,16 @@ type SignApkOptions = {
196196
apkPath: string;
197197
keystorePath: string;
198198
keystorePassword: string;
199+
keyAlias?: string;
200+
keyPassword?: string;
199201
};
200202

201203
async function signApkFile({
202204
apkPath,
203205
keystorePath,
204206
keystorePassword,
207+
keyAlias,
208+
keyPassword,
205209
}: SignApkOptions) {
206210
if (!fs.existsSync(keystorePath)) {
207211
throw new RnefError(
@@ -219,23 +223,24 @@ Please follow instructions at: https://reactnative.dev/docs/set-up-your-environm
219223
);
220224
}
221225

222-
// apksigner sign --ks-pass "pass:android" --ks "android/app/debug.keystore" "$OUTPUT2_APK"
226+
// apksigner sign --ks-pass "pass:android" --ks "android/app/debug.keystore" --ks-key-alias "androiddebugkey" --key-pass "pass:android" "$OUTPUT2_APK"
223227
const apksignerArgs = [
224228
'sign',
225229
'--ks',
226230
keystorePath,
227231
'--ks-pass',
228232
formatPassword(keystorePassword),
233+
...(keyAlias ? ['--ks-key-alias', keyAlias] : []),
234+
...(keyPassword ? ['--key-pass', formatPassword(keyPassword)] : []),
229235
apkPath,
230236
];
237+
231238
try {
232239
await spawn(apksignerPath, apksignerArgs);
233240
} catch (error) {
234241
throw new RnefError(
235242
`Failed to sign APK file: ${apksignerPath} ${apksignerArgs.join(' ')}`,
236-
{
237-
cause: error,
238-
}
243+
{ cause: (error as SubprocessError).stderr }
239244
);
240245
}
241246
}

0 commit comments

Comments
 (0)