Um Gemini Nano in einer Capacitor-App zu nutzen, installieren Sie @capgo/capacitor-llm, rufe setModel({ path: 'Gemini Nano' }) unter Android, erstellen Sie dann einen Chat und streamen Sie die Antwort über das textFromAi Event. Das Plugin spricht mit Gemini Nano über Googles ML Kit GenAI Prompt API, wodurch das Modell im AICore-Systemdienst von Android läuft, sodass der Text das Telefon nie verlässt.
Dieser Leitfaden behandelt, wie Gemini Nano läuft, welche Geräte es unterstützen, die genauen Plugin-Aufrufe, Streaming, Kontingente und Limits, einen Gemma-Fallback für nicht unterstützte Telefone und wie dasselbe code Apple Intelligence unter iOS erreicht.
So läuft Gemini Nano auf Android
Gemini Nano ist Googles kleinste Gemini-Modell, entwickelt für Smartphones. Apps bündeln es nicht. Androids AICore Service lädt es herunter, aktualisiert es und führt die Inferenz aus; Apps greifen darüber auf die ML Kit GenAI APIs:
- Prompt API: freie Textprompts, die das Plugin über API nutzt (
com.google.mlkit:genai-prompt). - Feature-APIs: feste Aufgaben wie Zusammenfassung, Korrekturlesen, Umformulierung und Bildbeschreibung.
Google liefert die Prompt API als Beta aus, ohne SLA oder Deprecation-Policy. Erwarte daher Verhaltensänderungen zwischen den Releases und halte die Integration hinter einem eigenen kleinen Wrapper.
Da die Inferenz lokal läuft, bekommst du drei Dinge, die ein Cloud-Modell nicht bieten kann: Es funktioniert offline, es kostet nichts pro Token, und der Nutzertext bleibt auf dem Gerät. Der Trade-off ist ein kleineres Modell mit kurzem Kontext und Output. Wähle daher passende Aufgaben: Umformulieren, Notizen zusammenfassen, Nachrichten klassifizieren, Felder extrahieren, kurze Antworten entwerfen.
Unterstützte Geräte und Anforderungen
Google veröffentlicht die unterstützte Liste pro API auf der ML Kit GenAI-Seite, gruppiert nach Gemini-Nano-Version (nano-v2, nano-v3, nano-v4). Für die Prompt API umfasst sie Pixel 9 und neuer, aktuelle Samsung Galaxy S- und Z-Flaggschiffe sowie aktuelle Flaggschiffe von OnePlus, OPPO, Xiaomi, vivo, Honor, realme, Motorola und anderen. Prüfe die aktuelle Liste, bevor du eine Funktion für ein bestimmtes Gerät versprichst.
Jedes unterstützte Gerät benötigt außerdem:
| Voraussetzung | Details |
|---|---|
| Android-Version | API Level 26 oder höher (das prüft das Plugin) |
| Bootloader | Gesperrt. Google unterstützt die GenAI-APIs auf entsperrten Bootloadern nicht |
| AICore | Vorhanden und eingerichtet. Direkt nach dem Setup oder Reset eines Geräts kann es eine Weile dauern, bis es fertig ist |
| App-Status | Deine App muss während der Inferenz im Vordergrund sein |
Verschiedene Nano-Versionen können für denselben Prompt unterschiedliche Ausgaben liefern. Teste deine Prompts auf mindestens einem Gerät pro Version, die dich interessiert.
Plugin installieren
bun add @capgo/capacitor-llm
bunx cap sync
Das Plugin folgt der Major-Version von Capacitor: Nutze 8.x mit Capacitor 8. Für Gemini Nano sind keine Änderungen am Android-Manifest nötig. Vollständige Referenz: Plugin-Docs und Plugin-Seite.
Schritt 1: Gemini Nano laden und Bereitschaft prüfen
setModel mit dem speziellen Pfad 'Gemini Nano' fragt den Modellstatus bei ML Kit ab. Das Promise wird erfüllt, sobald der Status verfügbar ist, andernfalls abgelehnt – mit einer Meldung, die den Status enthält:
| Status von AICore | Plugin-Verhalten |
|---|---|
| verfügbar | setModel wird aufgelöst, readinessChange emittiert ready |
| downloadbar | Lehnt ab: „Gemini Nano ist downloadbar, aber auf diesem Gerät nicht heruntergeladen“ |
| Laden | Lehnt mit dem Status „downloading“ ab |
| nicht verfügbar | Lehnt ab: „Gemini Nano ist auf diesem Gerät nicht verfügbar“ |
import { Capacitor } from '@capacitor/core';
import { CapgoLLM } from '@capgo/capacitor-llm';
export async function loadGeminiNano(): Promise<boolean> {
if (Capacitor.getPlatform() !== 'android') return false;
try {
await CapgoLLM.setModel({
path: 'Gemini Nano',
temperature: 0.3,
topk: 16,
});
} catch (error) {
console.warn('Gemini Nano not ready:', error);
return false;
}
const { readiness } = await CapgoLLM.getReadiness();
return readiness === 'ready';
}
Das Plugin startet den Download des AICore-Modells nicht selbst. Meldet ein Gerät „downloadable“, kommt das Modell meist erst, nachdem eine andere App oder das System es angefordert hat. Prüfe daher beim nächsten Start erneut, statt die Funktion dauerhaft auszublenden.
Schritt 2: Chat erstellen und Antwort streamen
Ein Chat speichert den Gesprächsverlauf. Auf Android sendMessage wird aufgelöst, sobald die Generierung startet und Text über Events eintrifft. Wickle es in ein Promise ein, das bei aiFinished:
import { CapgoLLM } from '@capgo/capacitor-llm';
// Android sends deltas. iOS Apple Intelligence sends the full text so far.
// This merge handles both.
function mergeChunk(current: string, chunk: string) {
return chunk.startsWith(current) ? chunk : current + chunk;
}
export async function ask(
chatId: string,
message: string,
onText: (textSoFar: string) => void,
): Promise<string> {
let text = '';
let finish!: (value: string) => void;
let fail!: (error: Error) => void;
const done = new Promise<string>((resolve, reject) => {
finish = resolve;
fail = reject;
});
const handles = await Promise.all([
CapgoLLM.addListener('textFromAi', (event) => {
if (event.chatId !== chatId) return;
text = mergeChunk(text, event.text);
onText(text);
}),
CapgoLLM.addListener('aiFinished', (event) => {
if (event.chatId === chatId) finish(text);
}),
CapgoLLM.addListener('generationError', (event) => {
if (!event.chatId || event.chatId === chatId) fail(new Error(event.error));
}),
]);
// If the app is backgrounded mid-answer, neither event may arrive
const timeout = setTimeout(() => fail(new Error('Generation timed out')), 60_000);
try {
await CapgoLLM.sendMessage({ chatId, message });
return await done;
} finally {
clearTimeout(timeout);
await Promise.all(handles.map((h) => h.remove()));
}
}
Nutze es für ein echtes Feature, zum Beispiel für einen Antwortentwurf auf eine Kundenbewertung:
const INSTRUCTIONS =
'You write short, polite replies to customer reviews for a small shop. ' +
'Answer each point, stay under 60 words, never promise refunds.';
export async function draftReply(review: string, render: (t: string) => void) {
const { id } = await CapgoLLM.createChat();
return ask(id, `${INSTRUCTIONS}\n\nReview:\n${review}\n\nReply:`, render);
}
createChat() benötigt keine Optionen; füge Anweisungen daher am Anfang der ersten Nachricht hinzu. Erstelle pro Aufgabe einen neuen Chat. Beim Gemini-Nano-Pfad hält das Plugin den Verlauf im Speicher und sendet ihn bei jeder Nachricht mit, weshalb lange Chats das Input-Budget schnell aufbrauchen.
Grenzen, die du einplanen musst
| Limit | Wert | Was zu tun ist |
|---|---|---|
| Eingabe | Unter ca. 4.000 Tokens pro Request (Google) | Chats kurz halten, lange Dokumente kürzen |
| Ausgabe | Das Plugin begrenzt die Antworten von Gemini Nano auf 256 Tokens | Kurze Outputs anfordern, lange Aufgaben aufteilen |
| Vordergrund | Inferenz nur, wenn deine App im Vordergrund ist | Niemals aus Hintergrundtasks ausführen |
| Quota | Quotas pro App, BUSY und Akku-Quota-Fehler |
Debounce, nicht bei jedem Tastendruck generieren |
| Concurrency | Eine Generierung pro Chat | Sende-Button während des Streamings deaktivieren |
| Tempo | Einige Sekunden pro Absatz | Immer in die UI streamen |
Behandle Quotenfehler als temporär. Zeige eine Retry-Option anstelle eines Fehlerdialogs.
Fallback: Gemma 4, falls Gemini Nano fehlt
Die meisten heute genutzten Android-Phones haben kein Gemini Nano. Dasselbe Plugin kann offene Gemma-Modelle via LiteRT-LM ausführen, sodass du bei einem API bleibst. Das Modell ist groß, oft über ein Gigabyte, also lade es erst herunter, wenn der Nutzer zustimmt, idealerweise über WLAN.
import { Preferences } from '@capacitor/preferences';
import { CapgoLLM } from '@capgo/capacitor-llm';
const GEMMA_URL =
'https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it.litertlm?download=true';
export async function loadGemma(onProgress: (pct: number) => void) {
const saved = await Preferences.get({ key: 'gemmaPath' });
if (saved.value) {
try {
await CapgoLLM.setModel({ path: saved.value, modelType: 'litertlm', maxTokens: 4096 });
return;
} catch {
// File missing or corrupt, download again
}
}
const sub = await CapgoLLM.addListener('downloadProgress', (e) => onProgress(e.progress));
try {
const { path } = await CapgoLLM.downloadModel({
url: GEMMA_URL,
filename: 'gemma-4-E2B-it.litertlm',
});
await Preferences.set({ key: 'gemmaPath', value: path });
await CapgoLLM.setModel({ path, modelType: 'litertlm', maxTokens: 4096 });
} finally {
await sub.remove();
}
}
Wähle dann die Engine beim Start:
export async function initOnDeviceAI(userAcceptedDownload: boolean, onProgress: (p: number) => void) {
if (await loadGeminiNano()) return 'gemini-nano';
if (userAcceptedDownload) {
await loadGemma(onProgress);
return 'gemma';
}
return 'none';
}
Falls beides nicht möglich ist, blende das Feature aus oder rufe ein Cloud-Modell auf. Lokale KI darf keine Core-Flows blockieren.
Dasselbe code auf iOS
Unter iOS nutzt das Plugin Apple Intelligence über das Foundation Models Framework. Ändere eine Zeile:
await CapgoLLM.setModel({ path: 'Apple Intelligence' });
createChat, sendMessage, und die Events bleiben gleich, und das mergeChunk Der oben genannte Helper behandelt bereits das iOS-Streaming-Format. Die Geräteanforderungen unterscheiden sich (iOS 26 und ein Apple-Intelligence-fähiges Gerät). Unser Guide zu Apple Intelligence in einer Capacitor-App deckt diesen Aspekt ab.
Testen
- Verwende ein echtes, unterstütztes Smartphone. Emulatoren stellen AICore mit Gemini Nano nicht bereit.
- Logge die
setModelAblehnungsnachricht. Sie zeigt dir genau an, welchen Status AICore meldet. - Warte auf einem frisch eingerichteten oder zurückgesetzten Gerät, bis AICore seine Initialeinrichtung online abgeschlossen hat, und versuche es dann erneut.
- Teste deine Prompts mit der niedrigsten Nano-Version, die du unterstützt. Kürzere, explizite Prompts sind stabiler über verschiedene Versionen hinweg.
Fehlerbehebung
„Gemini Nano ist auf diesem Gerät nicht verfügbar“. Das Gerät steht nicht auf Googles Liste, der Bootloader ist entsperrt oder AICore ist noch nicht eingerichtet.
„Gemini Nano ist herunterladbar, aber noch nicht heruntergeladen“. Das Gerät unterstützt es, aber das Modell ist nicht vorhanden. Biete den Gemma-Fallback an oder versuche es später erneut.
„Chat-Session nicht gefunden“. Du hast sendMessage mit einem Chat aufgerufen, der vor einem neuen setModelerstellt wurde. Das Laden eines Modells löscht bestehende Chats, also erstelle einen neuen.
„Modell nicht bereit“. setModel ist fehlgeschlagen oder wurde nicht vor createChat.
Die Ausgabe bricht mitten im Satz ab. Du hast das Ausgabe-Limit erreicht. Bitte um eine kürzere Antwort oder teile die Aufgabe auf.
Fehler, wenn die App in den Hintergrund wechselt. Inference läuft nur im Vordergrund. Bei Pause UI-Status zurücksetzen und Nutzer zum erneuten Versuch auffordern.
Datenschutz und Store-Review
Mit Gemini Nano bleiben Prompts und Antworten auf dem Gerät, was das Formular zur Datensicherheit vereinfacht. Die ML-Kit-Bedingungen von Google erwähnen weiterhin die Verarbeitung von Metriken; beschreibe die On-Device-KI-Nutzung daher in deiner Datenschutzerklärung. Falls du Gemma als Fallback nutzt, kommt der Modell-Download von Hugging Face – erwähne diese Netzwerkanfrage ebenfalls.
Prompts und UI-Texte für KI-Features ändern sich oft. Wenn du sie nach dem Release anpassen musst, Capgo Live Updates so kannst du neue Web-code ausrollen, ohne auf die Store-Review zu warten. Für einen tieferen Einblick in KI in Hybrid-Apps lies warum Capacitor für mobile KI-Apps ideal ist.
Fazit
Gemini Nano bietet Capacitor Apps kostenlose, private und Offline-Textgenerierung auf unterstützten Android-Smartphones. Lade es mit setModel({ path: 'Gemini Nano' }), streame über textFromAi, halte Prompts und Outputs kurz, beachte die Foreground- und Quota-Regeln und behalte einen Gemma- oder Cloud-Fallback für die vielen Geräte, die es nicht haben, bei.