Zum Hauptinhalt springen

Gemini Nano in einer Capacitor App nutzen

Nutze Gemini Nano in einer Capacitor App für On-Device AI auf Android: Geräteunterstützung, AICore-Checks, Streaming mit @capgo/capacitor-llm und ein Gemma-Fallback.

Gemini Nano in einer Capacitor App nutzen

Um Gemini Nano in einer Capacitor App zu nutzen, installiere @capgo/capacitor-llm, rufe setModel({ path: 'Gemini Nano' }) auf Android, erstelle dann einen Chat und streame die Antwort über das textFromAi Event. Das Plugin kommuniziert mit Gemini Nano über Googles ML Kit GenAI Prompt API, welches das Modell innerhalb des Android AICore System-Services ausführt, sodass der Text das Telefon nie verlässt.

Dieser Guide erklärt die Funktionsweise von Gemini Nano, unterstützte Geräte, die exakten Plugin-Aufrufe, Streaming, Quotas und Limits, einen Gemma-Fallback für nicht unterstützte Phones sowie wie derselbe code Apple Intelligence auf iOS erreicht.

So läuft Gemini Nano auf Android

Gemini Nano ist Googles kleinstes Gemini-Modell, optimiert für Smartphones. Apps bündeln es nicht. Der Android AICore Service lädt es herunter, aktualisiert es und führt die Inferenz aus; Apps greifen über die ML Kit GenAI APIs:

  • Prompt API: Freitext-Prompts, der API, den dieses Plugin nutzt (com.google.mlkit:genai-prompt).
  • Feature-APIs: feste Aufgaben wie Zusammenfassungen, Korrekturlesen, Umschreiben und Bildbeschreibungen.

Google veröffentlicht den Prompt API als Beta, ohne SLA oder Deprecation-Policy. Rechne also mit Verhaltensänderungen zwischen Releases und kapsle die Integration in einen eigenen kleinen Wrapper.

Da die Inferenz lokal läuft, bekommst du drei Dinge, die ein Cloud-Modell nicht liefern kann: Es funktioniert offline, 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: umschreiben, eine Notiz zusammenfassen, eine Nachricht klassifizieren, Felder extrahieren, kurze Antworten entwerfen.

Unterstützte Geräte und Anforderungen

Google veröffentlicht die Liste der unterstützten Geräte pro API auf der ML-Kit-GenAI-Seite, gruppiert nach Gemini-Nano-Version (nano-v2, nano-v3, nano-v4). Für den Prompt API umfasst sie das Pixel 9 und neuer, aktuelle Samsung Galaxy S- und Z-Flagships sowie aktuelle Flagships von OnePlus, OPPO, Xiaomi, vivo, Honor, realme, Motorola und anderen. Prüfe die Live-Liste, bevor du ein Feature für ein bestimmtes Gerät zusagst.

Jedes unterstützte Gerät benötigt außerdem:

Anforderung Details
Android-Version API Level 26 oder höher (das Plugin prüft das)
Bootloader Gesperrt. Google unterstützt die GenAI-APIs auf entsperrten Bootloadern nicht
AICore Präsent und bereit zur Einrichtung. Direkt nach einem Geräte-Setup oder -Reset kann der Vorgang einen Moment dauern.
App-Status Deine App muss während der Inferenz im Vordergrund sein.

Unterschiedliche Nano-Versionen können bei demselben Prompt unterschiedliche Ergebnisse liefern. Teste deine Prompts auf mindestens einem Gerät pro Version, die für dich relevant ist.

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 über den speziellen Pfad 'Gemini Nano' fragt den Modellstatus via ML Kit ab. Das Promise wird aufgelöst, sobald der Status verfügbar ist, andernfalls mit einer Fehlermeldung inklusive Status:

Status von AICore Plugin-Verhalten
verfügbar setModel löst auf, readinessChange gibt aus ready
downloadbar Rejects: „Gemini Nano ist downloadbar, wurde aber auf diesem Gerät noch nicht heruntergeladen“
downloading Rejects mit dem Status „downloading“
nicht verfügbar Rejects: „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 AICore-Modell-Download nicht selbst. Wenn ein Gerät „downloadable“ meldet, wird das Modell meist erst nach einer Anfrage durch eine andere App oder das System geladen. Prüfe es also lieber beim nächsten App-Start erneut, anstatt 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 der Text kommt per Event an. 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 um eine Antwort auf eine Kundenbewertung zu entwerfen:

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() akzeptiert keine Optionen, also setze Anweisungen an den Anfang der ersten Nachricht. Erstelle pro Task einen neuen Chat. Beim Gemini Nano Pfad speichert das Plugin den Verlauf im Speicher und sendet ihn bei jeder Nachricht mit; daher verbrauchen lange Chats das Input-Budget schnell.

Design-Limits berücksichtigen

Limit Wert Vorgehensweise
Input Unter ca. 4.000 Tokens pro Request (Google) Chats kurz halten, lange Dokumente kürzen
Output Das Plugin begrenzt Gemini Nano Antworten auf 256 Tokens Kurze Antworten anfordern, lange Aufgaben splitten
Foreground Inferenz nur, wenn die App im Vordergrund ist Niemals über Background-Tasks ausführen
Quota App-spezifische Quotas, BUSY und Battery-Quota-Fehler Debouncing nutzen, Generierung nicht bei jedem Tastendruck
Concurrency Eine Generierung pro Chat Sende-Button während des Streamings deaktivieren
Speed Einige Sekunden pro Absatz Immer an das UI streamen

Behandle Quota-Fehler als temporär. Zeige eine Retry-Option statt eines Error-Dialogs.

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 nur ein API benötigst. Das Modell ist groß, oft über 1 GB, daher erst nach dem Opt-in des Nutzers herunterladen, 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 beim Start die Engine:

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 nutze ein Cloud-Modell. Blockiere keine Core-Flows durch lokale KI.

Dasselbe code auf iOS

Auf 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 obige Helper übernimmt bereits das iOS-Streaming-Format. Die Hardware-Anforderungen unterscheiden sich (iOS 18 und ein Apple Intelligence-fähiges Gerät). Unser Guide zu Apple Intelligence in einer Capacitor App behandelt diesen Aspekt.

Das Testen von

  • Nutze ein echtes, unterstütztes Smartphone. Emulatoren stellen AICore nicht für Gemini Nano bereit.
  • Logge die setModel Rejection-Message. Sie zeigt dir genau an, welchen Status AICore meldet.
  • Warte auf einem neu eingerichteten oder zurückgesetzten Gerät, bis AICore die initiale Einrichtung online abgeschlossen hat, und versuche es dann erneut.
  • Teste deine Prompts mit der ältesten Nano-Version, die du unterstützt. Kürzere, explizite Prompts laufen über verschiedene Versionen hinweg stabiler.

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 verfügbar, aber nicht heruntergeladen“. Das Gerät unterstützt es, aber das Modell fehlt. 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. Das Output-Limit wurde erreicht. Bitte um eine kürzere Antwort oder teile die Aufgabe auf.

Fehler, wenn die App in den Hintergrund geht. Inference erfolgt nur im Vordergrund. UI-Status bei Pause abbrechen und dem Nutzer einen Retry ermöglichen.

Datenschutz und Store-Review

Mit Gemini Nano bleiben Prompts und Antworten auf dem Gerät, was dein Formular zur Datensicherheit vereinfacht. Die Bedingungen von Googles ML Kit erwähnen weiterhin die Verarbeitung von Metriken; beschreibe die On-Device-KI daher in deiner Datenschutzerklärung. Falls du Gemma als Fallback nutzt, erfolgt der Modell-Download über Hugging Face – erwähne diesen Netzwerkaufruf ebenfalls.

Prompts und UI-Texte für KI-Features ändern sich oft. Wenn du sie nach dem Release anpassen musst, Capgo Live Updates lässt code dich neue Web-code ausrollen, ohne auf die Store-Review zu warten. Für einen tieferen Einblick in KI in Hybrid-Apps lies, warum Capacitor ideal für KI-Mobile-Apps ist.

Fazit

Gemini Nano bietet Capacitor Apps kostenlose, private und Offline-Textgenerierung auf unterstützten Android-Phones. 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 ohne Unterstützung bei.

Live-Updates für Capacitor-Apps

Wenn ein Bug im Web-Layer live ist, rollst du den Fix über Capgo aus, statt Tage auf die App-Store-Freigabe zu warten. Nutzer bekommen das Update im Hintergrund, während native Änderungen weiter den normalen Review-Prozess durchlaufen.

Neuestes aus unserem Blog

Capgo bietet dir die besten Insights für eine wirklich professionelle Mobile App.