Android¶
Use the android/app product type in a module to build an Android application.
Using IntelliJ IDEA?
Make sure to install the Android plugin to get proper support for Android-specific features.
Module layout¶
Here is an overview of the module layout for an Android application:
my-android-app/
├─ assets/ # (1)!
├─ res/ # (2)!
│ ├─ drawable/
│ │ ╰─ graphic.png
│ ├─ layout/
│ │ ├─ main.xml
│ │ ╰─ info.xml
│ ╰─ ...
├─ resources/
├─ src/
│ ├─ AndroidManifest.xml # (3)!
│ ╰─ MainActivity.kt # (4)!
├─ test/
│ ╰─ MainTest.kt
├─ module.yaml
╰─ proguard-rules.pro # (5)!
assetsandresare standard Android resource directories. See the official Android docs.assetsandresare standard Android resource directories. See the official Android docs.- The manifest file of your application.
- An activity (screen) of your application.
- Optional configuration for R8 code shrinking and obfuscation. See code shrinking.
Entry point¶
The application's entry point is specified in the AndroidManifest.xml file according to the
official Android documentation:
<manifest ... >
<application ... >
<activity android:name="com.example.myapp.MainActivity" ... >
</activity>
</application>
</manifest>
You can run your application using the ./amper run command.
Run in IntelliJ IDEA
IntelliJ IDEA with the Amper plugin automatically detects the android/app product type and provides a run
configuration for it:

Packaging¶
You can use the build command to create an APK, or the package command to create an Android Application Bundle (AAB).
The package command will not only build the APK, but also minify/obfuscate it with ProGuard, and sign it.
See the dedicated signing and code shrinking sections to learn how to configure this.
Code shrinking¶
When creating a release build with Amper, R8 will be used automatically, with minification and shrinking enabled. This is equivalent to the following Gradle configuration:
// in Gradle
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
You can create a proguard-rules.pro file in the module folder to add custom rules for R8.
├─ src/
├─ test/
├─ proguard-rules.pro
╰─ module.yaml
It is automatically used by Amper if present.
An example of how to add custom R8 rules can be found in the android-app module of the compose-multiplatform example project.
Signing¶
In a module containing an Android application (using the android/app product type) you can enable signing under
settings:
settings:
android:
signing: enabled
This will use a keystore.properties file located in the module folder for the signing details by default. This
properties file must contain the following signing details. Remember that these details should usually not be added
to version control.
storeFile=/Users/example/.keystores/release.keystore
storePassword=store_password
keyAlias=alias
keyPassword=key_password
To customize the path to this file, you can use the propertiesFile option:
settings:
android:
signing:
enabled: true
propertiesFile: ./keystore.properties # default value
You can use ./amper tool generate-keystore to generate a new keystore if you don't have one yet.
This will create a new self-signed certificate, using the details in the keystore.properties file.
Note
You can also pass in these details to generate-keystore as command line arguments. Invoke the tool with --help
to learn more.
Parcelize¶
If you want to automatically generate your Parcelable implementations, you can enable
Parcelize as follows:
settings:
android:
parcelize: enabled
With this simple toggle, the following class gets its Parcelable implementation automatically without spelling it out
in the code, just thanks to the @Parcelize annotation:
import kotlinx.parcelize.Parcelize
@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable
While this is only relevant on Android, sometimes you need to share your data model between multiple platforms.
However, the Parcelable interface and @Parcelize annotation are only present on Android.
But fear not, there is a solution described in the
official documentation.
In short:
- For
android.os.Parcelable, you can use theexpect/actualmechanism to define your own interface as typealias ofandroid.os.Parcelable(for Android), and as an empty interface for other platforms. - For
@Parcelize, you can simply define your own annotation instead, and then tell Parcelize about it (see below).
For example, in common code:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
annotation class MyParcelize
expect interface MyParcelable
actual typealias MyParcelable = android.os.Parcelable
// empty because nothing is generated on non-Android platforms
actual interface MyParcelable
You can then make Parcelize recognize this custom annotation using the additionalAnnotations option:
settings:
kotlin:
# for the expect/actual MyParcelable interface
freeCompilerArgs: [ -Xexpect-actual-classes ]
android:
parcelize:
enabled: true
additionalAnnotations: [ com.example.MyParcelize ]
Google Services and Firebase¶
To enable the google-services plugin, place
your google-services.json file in the module containing an android/app product, next to module.yaml.
╰─ androidApp/
├─ src/
├─ google-services.json
╰─ module.yaml
This file will be found and consumed automatically.