Google Gemini in einer Android-App (Kotlin, über dein eigenes Backend)
Ein KI-Feature in eine Kotlin-App bringen – mit Google Gemini. Warum der API-Key nie in die App gehört, wie der generateContent-Aufruf aussieht und wie du ihn sauber aus einer Coroutine startest.
Du willst ein KI-Feature in deine Android-App bringen – eine Textgenerierung, eine Zusammenfassung, einen Assistenten? Google Gemini ist dafür eine naheliegende Wahl. Der wichtigste Grundsatz vorweg: Der API-Key gehört nicht in die App. Eine APK lässt sich dekompilieren; jeder eingebettete Schlüssel ist damit öffentlich. Die App spricht deshalb mit deinem eigenen Backend, das den Key hält und an Gemini weiterreicht.
Der Aufruf über dein Backend (Retrofit + Coroutines)
import retrofit2.http.Body
import retrofit2.http.POST
// 1) Datenmodelle für deinen eigenen Endpunkt
data class AskRequest(val prompt: String)
data class AskResponse(val text: String)
// 2) Retrofit-Interface – zeigt auf DEIN Backend, nicht auf Google
interface AiApi {
@POST("api/gemini")
suspend fun ask(@Body body: AskRequest): AskResponse
}
// 3) Aufruf aus dem ViewModel, main-sicher dank suspend
class ChatViewModel(private val api: AiApi) : ViewModel() {
private val _answer = MutableStateFlow("")
val answer: StateFlow<String> = _answer.asStateFlow()
fun ask(prompt: String) {
viewModelScope.launch {
_answer.value = try {
api.ask(AskRequest(prompt)).text // Netzwerk läuft off-main (Retrofit)
} catch (e: Exception) {
"Fehler: ${e.message}"
}
}
}
}Dein Backend ruft dann Gemini auf – hier liegt der Key sicher:
// Server-Seite (Ktor/Spring o.ä.) – nur zur Veranschaulichung des Gemini-Calls
// POST https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$KEY
// Body:
// { "contents": [ { "parts": [ { "text": "<prompt>" } ] } ] }
// Antwort: candidates[0].content.parts[0].textWarum dieser Umweg – und was er dir bringt
- Sicherheit: Der Key bleibt auf dem Server. Wird er kompromittiert, tauschst du ihn an einer Stelle, ohne ein App-Update auszurollen.
- Kontrolle: Im Backend kannst du Anfragen begrenzen (Rate-Limiting), protokollieren und den System-Prompt zentral pflegen – ohne die App neu zu veröffentlichen.
- Austauschbarkeit: Ob dahinter Gemini, Claude oder ChatGPT steckt, merkt die App nicht. Du kannst den Anbieter wechseln, ohne eine Zeile Kotlin anzufassen.
Das StateFlow liest du in Compose übrigens am besten mit collectAsStateWithLifecycle() – so wird nur gesammelt, wenn der Screen sichtbar ist.
Du willst eine Android-App in Kotlin & Compose mit sinnvollem KI-Feature? Melde dich.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
callbackFlow – Listener-APIs in einen Flow verwandeln
Android steckt voller Callback-APIs mit `register`/`unregister`. Mit `callbackFlow` machst du daraus einen ganz normalen Flow – inklusive automatischem Abmelden, wenn niemand mehr zuhört.
kotlinx.serialization: JSON und data class ohne Handarbeit verbinden
Eine API antwortet mit JSON, deine App will eine data class. Dazwischen steht in vielen Projekten ein handgeschriebener Parser. Mit kotlinx.serialization sind es eine Annotation und eine Zeile – und ein Schalter, ohne den deine App beim nächsten API-Update abstürzt.
snapshotFlow in Jetpack Compose – aus Compose-Zustand einen Flow machen
Manchmal willst du auf einen Compose-Zustand reagieren wie auf einen Datenstrom – entprellen, kombinieren, sammeln. Genau das macht snapshotFlow. Ich zeige dir das an der häufigsten Aufgabe: mehr laden, wenn der Nutzer ans Listenende scrollt.