AAB manifest: read aapt2 Resources.proto field numbers (element name 3, attribute 4, child 5); real AGP bundles failed with 'AAB manifest without package / versionCode'

This commit is contained in:
CRTkafa 2026-10-12 08:40:27 +08:00
parent 720cb2a13a
commit 78be1304ec
2 changed files with 33 additions and 8 deletions

View file

@ -71,6 +71,22 @@ describe('zip + IPA + AAB', () => {
expect(ipaInfo(f).build).toBe('42');
expect(() => ipaInfo(makeZip([{ name: 'x', data: 'y' }]))).toThrow('not an iOS app archive');
});
test('aabInfo reads the manifest as AGP writes it (Resources.proto: element name = 3, attribute = 4, child = 5)', () => {
// a real Capacitor 8 / AGP bundle failed with "AAB manifest without package / versionCode": the parser read the
// element fields one number too high. These bytes are written by tag, independent of encodeProtoManifest.
const len = (n: number) => Buffer.from(n < 128 ? [n] : [(n & 127) | 128, n >> 7]);
const ld = (tag: number, b: Buffer) => Buffer.concat([Buffer.from([tag]), len(b.length), b]);
const str = (tag: number, t: string) => ld(tag, Buffer.from(t));
const NS = 'http://schemas.android.com/apk/res/android';
const attr = (name: string, value: string, int?: number) => ld(0x22, Buffer.concat([name === 'package' ? Buffer.alloc(0) : str(0x0a, NS), str(0x12, name), str(0x1a, value),
...(int === undefined ? [] : [ld(0x32, ld(0x3a, Buffer.from([0x30, int])))])]));
const usesSdk = ld(0x0a, Buffer.concat([str(0x1a, 'uses-sdk'), attr('minSdkVersion', '24', 24)]));
const manifest = ld(0x0a, Buffer.concat([ld(0x0a, Buffer.concat([str(0x0a, 'android'), str(0x12, NS)])), str(0x1a, 'manifest'),
attr('versionCode', '7', 7), attr('versionName', '1.0.0'), attr('package', 'com.example.game'), ld(0x2a, usesSdk)]));
const aab = makeZip([{ name: 'base/manifest/AndroidManifest.xml', data: manifest }]);
expect(aabInfo(aab)).toEqual({ packageName: 'com.example.game', versionCode: 7, versionName: '1.0.0', minSdk: 24, targetSdk: undefined });
});
test('aabInfo reads the proto manifest', () => {
expect(aabInfo(makeAab('com.example.game', 1234, '2.0.1'))).toEqual({ packageName: 'com.example.game', versionCode: 1234, versionName: '2.0.1', minSdk: 24, targetSdk: 35 });
expect(() => aabInfo(makeZip([{ name: 'x', data: 'y' }]))).toThrow('not an Android App Bundle');