Skip to content

Instantly share code, notes, and snippets.

@Farbklex
Last active August 5, 2023 05:34
Show Gist options
  • Save Farbklex/dbf96c2426c59a37d681438ade63e416 to your computer and use it in GitHub Desktop.
Save Farbklex/dbf96c2426c59a37d681438ade63e416 to your computer and use it in GitHub Desktop.
Android: Create a signed universal APK with all dynamic feature modules included with gradle wrapper via commandline

Android Studio doesn't automatically include dynamic feature modules when building signed release APKs. But universal APKs can be created via the bundletool and signed later.

The gradle wrapper has a task for this already. This makes creating universal APKs easier since APK creation and signing are executed with one command and no separate download of bundletool is required.

You can use packageReleaseUniversalApk with the name of your base application module (e.g.: app) to create a universal APK:

./gradlew :app:packageReleaseUniversalApk

This will however only create an unsigned APK unless you specify the signing informations in your gradle file or pass the information through the command line as shown below.

Leaving the information in gradle is considered bad practice due to security concerns.

The command in buildUniversalApk.sh passes the information as parameters to the gradlew task in order to make it easily usable in a CI environment.

Notes on the parameters

The path to your keystore must be absolute. In my case it looks like this on macOS:

-Pandroid.injected.signing.store.file=/Users/farbklex/workspace/my_app

The password fields should be enclosed in ' in order to escape characters inside.

Why do we need this?

If you publish app bundles to the play store, you might ask yourself why we still need APKs in our CI. My reasons for this are:

  1. Sharing an APK for testing is easier. Services like Appcenter Dsitribute, Firebase App distribution or direct sharing via email are still simpler than using play store's internal sharing which requires entering the play store accounts of all receipients. Unfortunately, Appcenter and Firebase only support APKs right now.
  2. App bundles aren't supported by all stores. If you intend to publish your app on alternative app stores (e.g. f-droid), you still need an APK.
./gradlew :app:packageReleaseUniversalApk -Pandroid.injected.signing.store.file=ABSOLUTE_PATH \
-Pandroid.injected.signing.store.password='PASSWORD' \
-Pandroid.injected.signing.key.alias=ALIAS \
-Pandroid.injected.signing.key.password='PASSWORD'
@tir38
Copy link

tir38 commented Jan 15, 2022

This will however only create an unsigned APK unless you specify the signing informations in your gradle file or pass the information through the command line as shown below.

I found that having signing configs in build.gradle did not generate signed apk when running packageReleaseUniversalApk. It only worked by including signing configs along as CL arguments.

Thanks for this.

@OltaimerChic
Copy link

hello

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment