MyApp.apk
- device installable containing all resources
- can be installed via Google Play or manually (sideloaded)
- usually larger because they contain all possible resources for different devices, including images and code
MyApp.aab
- contains all resources but Google Play Store uses it to generate optimized APKs for different devices
- AABs are designed to result in smaller APKs, faster downloads and less space used on devices
- can only be installed via Google Play Store
- cannot be installed directly
On Ubuntu:
apt-get install -y android-sdk google-android-build-tools-34.0.0-installerexport ANDROID_HOME="/usr/lib/android-sdk"On Mac, it's easier using DevOps-Bash-tools to download and install Android SDK and command line tools:
install_android_sdk.shinstall_android_commandlinetools.shSet your shell environment variables:
export ANDROID_HOME="$HOME/Android/Sdk"
export PATH="$PATH:$ANDROID_HOME/platform-tools"
export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin"Accept all the licenses so that Gradle builds don't error out:
yes | sdkmanager --licensessdkmanager --listInstall build-tools version 34.0.0:
sdkmanager "build-tools;34.0.0"Add to PATH:
export PATH="$PATH:$ANDROID_HOME/build-tools/34.0.0"See gradle page.
./gradlew clean assembleRelease \
-Dorg.gradle.jvmargs="\
-Xmx4G \
-Dkotlin.daemon.jvm.options=-Xmx2G \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+UseParallelGC \
-Dfile.encoding=UTF-8 \
" \
--build-cache \
--stacktrace \
--inforesults in an .apk artifact such as:
app/build/outputs/apk/release/app-release.apk
Recommended to use Fastlane which has a gradle action but can also handle signing and other things.
Newer recommended command.
apksigner \
sign \
--ks "$JKS" \
--ks-pass "pass:$JKS_KEYSTORE_PASSWORD" \
--key-pass "pass:$JKS_KEY_PASSWORD" \
--ks-key-alias "$JKS_KEY_ALIAS" \
--v1-signing-enabled true \
--v2-signing-enabled true \
--verbose \
"$APK"This actually exits non-zero if it fails to verify, unlike jarsigner which only exits non-zero if there is an error.
This makes this the better choice for scripting and CI/CD.
apksigner verify --verbose "$APK"Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
Fails to verify is signed with the older jarsigner:
DOES NOT VERIFY
ERROR: Target SDK version 34 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme
Older method, if you sign with jarsigner, you won't be able to verify with apksigner in your CI/CD
pipelines.
jarsigner \
-keystore "$JKS" \
-storepass "$JKS_KEYSTORE_PASSWORD" \
-keypass "$JKS_KEY_PASSWORD" \
-sigalg SHA256withRSA \
-digestalg SHA-256 \
-verbose \
"$APK" \
"$JKS_KEY_ALIAS"Does not exit non-zero if jar is unsigned and fails to verify.
It only exits non-zero if there is an error.
Use newer apksigner command instead.
jarsigner -verify "$$APK"jar verified.
or:
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
no manifest.
jar is unsigned.
Fastlane can also do the signing, see this fastlane/Fastfile template.
Ensure the following environment variables are set:
JKSJKS_KEYSTORE_PASSWORDJKS_KEY_ALIASJKS_KEY_PASSWORD
and then set the following properties in the gradle
action in the fastlane/Fastfile:
gradle(
# don't waste the cache with a clean, 1min30sec => 5min30sec
#task: 'clean bundleRelease',
task: "assembleRelease",
flags: "-Dorg.gradle.jvmargs=\"-Xmx4G -Dkotlin.daemon.jvm.options=-Xmx2G -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dfile.encoding=UTF-8\" --build-cache --no-daemon --stacktrace --info",
properties: {
"android.injected.signing.store.file" => ENV["JKS"],
"android.injected.signing.store.password" => ENV["JKS_KEYSTORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["JKS_KEY_ALIAS"],
"android.injected.signing.key.password" => ENV["JKS_KEY_PASSWORD"],
"android.injected.signing.v2.signing.enabled" => "true",
"android.injected.signing.v1.signing.enabled" => "true"
}https://play.google.com/console/developers
https://docs.fastlane.tools/getting-started/android/setup/#setting-up-supply
Upload your APK here to distribute to users.
See also Fastlane doc section on uploading to Google Play Store.