How to Build Fast Multi‑Channel Android APKs Without Re‑Signing
This article explains various multi‑channel packaging methods for Android APKs, compares traditional Gradle productFlavors and ApkTool approaches, and introduces efficient V1‑ and V2‑based channel insertion techniques that avoid rebuilding or re‑signing, while providing integration steps for the ApkChannelPackage plugin.
Overview
Because Android app distribution markets in China require separate channel packages, developers need to embed different channel identifiers in each APK to track downloads and user statistics.
Common Multi‑Channel Packaging Solutions
Android Gradle Plugin
The Gradle plugin supports channel packaging via productFlavors and a placeholder in AndroidManifest.xml:
<meta-data android:name="InstallChannel" android:value="${InstallChannel}" />Each flavor defines a manifestPlaceholders entry, replacing the placeholder at build time.
Drawbacks:
Each channel requires a full rebuild, which is inefficient for many channels.
Gradle generates a distinct BuildConfig.java per channel, causing different DEX CRCs; this breaks hot‑patch solutions like Tinker that rely on identical base DEX files.
ApkTool
ApkTool can decompile, modify, and repackage an APK:
Copy the original APK.
Decompile with apktool d origin.apk.
Remove existing signatures.
Add channel information to any file.
Rebuild with apktool b newApkDir.
Resign the APK.
Advantages: no full rebuild and supports both V1 and V2 signatures. Disadvantages: ApkTool can be unstable and the process is still time‑consuming for many channels.
Data Digest, Digital Signature, and Certificate
Data digests produce fixed‑length fingerprints (e.g., MD5, SHA) that change with any modification of the original data. Digital signatures use a private key to encrypt the digest, while digital certificates bind the public key to the signer’s identity.
The verification process involves computing the digest, decrypting the signature with the public key from the certificate, and comparing the results.
V1 Signing and Multi‑Channel Packaging
V1 Signing Mechanism
V1 signing stores three files in META-INF: MANIFEST.MF, CERT.SF, and CERT.RSA. MANIFEST.MF lists Base64‑encoded SHA1 digests of every file; CERT.SF records digests of the manifest entries; CERT.RSA contains the signature of CERT.SF and the developer’s certificate.
During installation, Android verifies these files via PackageManagerService → PackageParser.
V1‑Based Multi‑Channel Scheme
Since V1 verification only checks the first part of the ZIP (the file entries), channel data can be placed in the ZIP comment (EOCD) without affecting the signature. The steps are:
Copy the APK.
Locate the EOCD block.
Modify the comment length.
Append the channel string.
Append the length and a magic number.
This method adds only a few seconds per channel but fails when V2 signing is enabled.
V2 Signing and Multi‑Channel Packaging
Why V2 Signing
V2 signing computes a digest over the entire APK (excluding the signature block), eliminating the need to unzip files and providing stronger integrity checks.
V2 Signing Mechanism
V2 adds a signature block before the central directory. The block contains ID‑Value pairs, including the developer’s public key, certificates, and digests. The block size and a magic number are stored at the end.
V2‑Based Multi‑Channel Scheme
Because Android only validates the ID 0x7109871a block, additional ID‑Value pairs can store channel information. The process mirrors the V1 scheme but inserts the channel ID‑Value into the signature block and updates the EOCD offset accordingly.
Strong Verification of Channel Packages
Google’s apksig library (including the apksigner CLI) can verify that a multi‑channel APK passes both V1 and V2 checks across all Android versions.
Comparison of Multi‑Channel Tools
ApkChannelPackage is compared with packer‑ng‑plugin and Meituan’s Walle, highlighting its support for both V1 and V2 schemes and its fast, no‑re‑sign approach.
Integrating ApkChannelPackage Plugin
Selecting a Packaging Method
Disable V2 signing in build.gradle if you want to use the V1‑only scheme:
signingConfigs {
release {
v1SigningEnabled true
v2SigningEnabled false
}
debug {
v1SigningEnabled true
v2SigningEnabled false
}
}Setup Steps
Add the plugin dependency in the root build.gradle.
Apply the plugin in the app module.
Include the helper library to read channel info.
Define the channel file name in gradle.properties.
Configure channel output directories and naming formats.
Optionally use rebuildChannel to generate channels from existing APKs.
Run the generated Gradle tasks (e.g., channelDebug, channelFlavorXRelease) to produce channel‑specific APKs.
Reading Channel Information
Use ChannelReaderUtil.getChannel(context) at runtime; it returns the channel string or null if none is present.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
