Skip to content

Latest commit

 

History

History
161 lines (131 loc) · 8.09 KB

README.md

File metadata and controls

161 lines (131 loc) · 8.09 KB

ADK Kotlin — Android examples

A single installable Android app that collects the ADK Kotlin Android examples behind a launcher menu (HomeActivity). Each menu entry opens one self-contained example Activity:

  • Room session — an on-device agent whose conversation is persisted across restarts by the Room-backed session service.
  • Skills (AssetSkillSource) — an agent whose SkillToolset reads skill definitions from the APK's assets/skills/... tree, backed by the cloud Firebase AI (Gemini) model so its function calling reliably drives the toolset.
  • ML Kit chat — a multi-turn chat with an on-device Gemini Nano agent, with streaming and thinking toggles.
  • LiteRT-LM chat — a multi-turn chat with an on-device agent run by LiteRT-LM from the :google-adk-kotlin-litertlm module, with a streaming toggle and tool calling (via DeviceTools.kt). Downloads its model on first use — see The LiteRT-LM model below.
  • Firebase AI — a chat backed by the cloud Firebase AI (Gemini) model from the :google-adk-kotlin-firebase module, with a streaming toggle and tool calling (via WeatherTools.kt).

Room session, ML Kit chat and LiteRT-LM chat infer fully on-device and need no API key: the first two through ML Kit's Gemini Nano, the third through a model file in the app's own storage. Each uses the network only to obtain that model the first time: Gemini Nano may be downloaded on the first run, and the LiteRT-LM example fetches its weights. The Skills (AssetSkillSource) and Firebase AI examples call the cloud Firebase backend on every turn, so they need a Firebase configuration and network access — see Configure Firebase below.

Build & run

With a device or emulator connected:

./gradlew :google-adk-kotlin-examples-android:installDebug

Then launch "ADK Android Examples" from the launcher and pick an example.

The LiteRT-LM model (for the LiteRT-LM chat example)

LiteRT-LM is handed a path to a .litertlm file and runs whatever model is in it; it does not fetch models itself, so getting one onto the device is the app's job. The other examples don't need any of this.

Nothing to do to try it: open the example and press Download. It streams gemma-4-E2B-it.litertlm (about 2.5 GB) from the LiteRT community on Hugging Face into the app's own files directory, then loads it. Use Wi-Fi, and note the model wants a device with 8 GB of RAM or more. After that it runs offline; loading the weights takes a few seconds at each launch, and generation is slower than the cloud examples — that's the model running on the device's CPU.

To use a different model, edit the REPO / FILE_NAME / REVISION constants in LiteRtLmModelStore.kt. Two things to watch: function calling only works with a model trained for tool use, and repositories that require accepting a license need an access token this sample does not implement. For those, and as a faster loop while developing, push a file yourself — a .litertlm you supply takes precedence over the downloaded one, so there is nothing to delete first:

adb push your-model.litertlm \
    /sdcard/Android/data/com.google.adk.kt.examples.android/files/

How a real app would ship the model

Downloading on first use, as this sample does, is what the Google AI Edge Gallery does too, and it is a reasonable choice — but it leaves you owning the hosting, the storage, the retries and the updates. Bundling the file in the APK is not an option at these sizes.

For an app shipped on Google Play, the delivery path to reach for is Play for On-device AI (currently in beta): the model becomes an AI pack that Play hosts, delivers and updates alongside the app — at install time, fast-follow, or on demand — through the com.google.android.play:ai-delivery library. Play then owns the download, the storage and the updates, and can send a different variant of the model to different device tiers. The runtime side is unchanged: you still hand EngineConfig a file path.

Watch the size limits, which is exactly why this sample does not use it: an individual AI pack is capped at 1.5 GB compressed, and 4 GB is the maximum cumulative size of any version of your app. The 2.5 GB model above does not fit, so taking the AI pack route means choosing a smaller model.

Configure Firebase (for the Firebase-backed examples)

The Skills (AssetSkillSource) and Firebase AI examples need to know which Firebase project to talk to; the on-device examples (Room session, ML Kit chat, LiteRT-LM chat) don't need any of this. Two ways, in order of preference:

1. google-services.json (standard Firebase setup — recommended)

This mirrors what a normal Firebase Android developer does.

  1. In the Firebase console, open your project (or create one) and enable the Firebase AI Logic / Gemini API.
  2. Register an Android app with the package name com.google.adk.kt.examples.android (this is the applicationId in build.gradle.kts; change both if you prefer your own).
  3. Download the generated google-services.json and place it in this directory (examples/android/google-services.json).

This file just points the app at a specific Firebase project; its contents are not secret — the Firebase config/API key is public by design and ships inside the APK anyway, so a normal app can commit it (and often does, especially in a private repo). It's git-ignored here only so that forks of this sample use their own Firebase project instead of ours. When present, the com.google.gms.google-services Gradle plugin is applied automatically and initializes the default FirebaseApp for you.

2. Build-time Firebase config (fallback)

If you don't have a google-services.json, supply the three values directly and they are baked into the APK's manifest at build time. Pass them as Gradle properties:

./gradlew :google-adk-kotlin-examples-android:installDebug \
    -PFIREBASE_API_KEY=your_api_key \
    -PFIREBASE_APP_ID=your_app_id \
    -PFIREBASE_PROJECT_ID=your_project_id

or export the matching FIREBASE_API_KEY / FIREBASE_APP_ID / FIREBASE_PROJECT_ID environment variables before building. (These are read at build time, not from the device's environment.)

If neither method provides a configuration, the Gradle build prints a warning, and the Firebase-backed examples (Skills, Firebase AI) start but show a message explaining what to add instead of calling Firebase with a blank config. The on-device examples are unaffected.

To change the model, edit MODEL_NAME in FirebaseChatAgent.kt (Firebase AI example) or WizardApprenticeAgent.kt (Skills example).

Note: the FIREBASE_* values (like those in google-services.json) are project identifiers, not secrets — they're public by design and always end up inside the APK. What you must keep out of the app and the repo is a genuinely secret key, such as a Gemini Developer API key or an Admin SDK service-account key; this sample uses neither (it talks to the model through Firebase AI Logic).