# Ship an LLM on Android and iOS with LiteRT-LM: Lesson 02. Make release builds work

Lesson id: `litert-lm-ship-android-ios/02-release-builds-and-proguard`
Human lesson: https://edgefde.dev/courses/litert-lm-ship-android-ios/02-release-builds-and-proguard.html

## Goal

Make a minified Android release build run LiteRT-LM generation without a JNI abort.

## Prerequisites

- Android app with `isMinifyEnabled = true` for release
- LiteRT-LM AAR

## Inputs

- `app/build.gradle.kts`
- `proguard-rules.pro`
- A small `.litertlm` model on the test device

## Outputs and artifacts

- Keep rule in `proguard-rules.pro`
- `ReleaseSmokeTest` instrumented test
- CI job that runs it on the release build type

## Steps

1. Add `-keep class com.google.ai.edge.litertlm.** { *; }` to `proguard-rules.pro`.
2. Confirm the release build type lists `proguard-rules.pro` in `proguardFiles`.
3. Unzip the AAR and check for `proguard.txt`. Record the result.
4. Write `ReleaseSmokeTest` that creates a Conversation with `SamplerConfig(topK = 1, topP = 1.0, temperature = 0.0)` and sends one message.
5. Set `testBuildType = "release"` (or a staging type) and run the test on a real arm64 phone.

## Constraints

- Do not disable minify to work around the crash.
- Kotlin only.

## Acceptance checks

- The release smoke test passes on device.
- Removing the keep rule makes the test fail with `mid == null` (shows the test covers the bug).

## Key concepts

- #3739: R8 strips Kotlin members that JNI looks up by name, so a minified build aborts with `mid == null`.
- Debug builds are not minified, so the bug only shows in release.
- The keep rule `-keep class com.google.ai.edge.litertlm.** { *; }` is the workaround from the issue.

## Takeaways

- Add the keep rule now and remove it only when the AAR ships consumer rules.
- Run one smoke test on the minified build on a real device in CI.
- Use a non-null SamplerConfig in the test, because that is the path that crashed.
