Aller directement au contenu principal

How to Use Gemini Nano in a Capacitor App

Utilisez Gemini Nano dans une application Capacitor pour l'intelligence artificielle sur appareil Android : prise en charge des appareils, vérifications AICore, streaming avec @capgo/capacitor-llm, et un fallback Gemma.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Relecteur

Jordan

Éditeur

Comment utiliser Gemini Nano dans une Capacitor application

Pour utiliser Gemini Nano dans une Capacitor application, installez @capgo/capacitor-llmappeler setModel({ path: 'Gemini Nano' }) sur Android, puis créez un chat et diffusez la réponse à travers le textFromAi l'événement. Le plugin communique avec Gemini Nano à l'aide du kit ML de Google GenAI Prompt API, qui exécute le modèle dans le système de service AICore d'Android, de sorte que le texte ne quitte jamais le téléphone.

Cette guide couvre la façon dont Gemini Nano fonctionne, les appareils qui le supportent, les appels de plugin précis, le streaming, les quotas et les limites, un fallback Gemma pour les téléphones non pris en charge, et la façon dont le même code atteint l'intelligence Apple sur iOS.

Comment Gemini Nano fonctionne sur Android

Le Gemini Nano est le modèle Gemini le plus petit de Google, conçu pour les téléphones. Les applications ne le définissent pas. AICore Le service qui télécharge, met à jour et exécute Gemini Nano Les API ML Kit GenAI:

  • Prompt API : des prompts de texte libres, l’API que ce plugin utilise (com.google.mlkit:genai-prompt).
  • Les API de fonctionnalités : des tâches fixes telles que la rédaction, la réécriture, la description d'image et la rédaction.

Google livre le Prompt API en version bêta, sans politique SLA ou de dépréciation, donc attendez-vous à des changements de comportement entre les mises à jour et gardez l'intégration derrière votre propre petit wrapper.

Parce que l'inference est local, vous obtenez trois choses que le modèle cloud ne peut pas vous donner : cela fonctionne hors ligne, il n'y a pas de coût par jeton, et le texte de l'utilisateur reste sur le dispositif. Le compromis est un modèle plus petit avec un contexte et une sortie courts, donc choisissez des tâches qui s'adaptent : réécrire, résumer un note, classer un message, extraire des champs, rédiger des réponses courtes.

Appareils et exigences pris en charge

Google publie la liste des appareils pris en charge par API sur le site ML Kit GenAI, groupés par version Gemini Nano (nano-v2, nano-v3, nano-v4). Pour le Prompt API elle couvre le Pixel 9 et ultérieur, les derniers Samsung Galaxy S et Z flagships, et les derniers flagships de OnePlus, OPPO, Xiaomi, vivo, Honor, realme, Motorola et autres. Vérifiez la liste en direct avant de promettre une fonctionnalité à un appareil spécifique.

Tout appareil pris en charge nécessite également :

Exigence Détail
Version d'Android API niveau 26 ou supérieur (le plugin vérifie cela)
Bootloader Verrouillé. Google ne prend pas en charge les API GenAI sur les bootloaders déverrouillés
AICore Présent et configurer. Il peut prendre un moment pour s'achever après une mise en route ou un redémarrage du dispositif.
App state Votre application doit être l'application de premier plan pendant l'inference

Diverses versions de Nano peuvent retourner des résultats différents pour la même requête. Testez vos requêtes sur au moins un appareil par version que vous souhaitez prendre en compte.

Installez le plugin

bun add @capgo/capacitor-llm
bunx cap sync

Le plugin suit la version majeure de Capacitor : utilisez 8.x avec Capacitor 8. Aucune modification du fichier AndroidManifest.xml n'est nécessaire pour Gemini Nano. Référence complète : docs du plugin et page du plugin.

Étape 1 : Chargez Gemini Nano et vérifiez la disponibilité

setModel avec le chemin spécial 'Gemini Nano' demande à ML Kit le statut du modèle. Il se résout lorsque le statut est disponible et rejette sinon, avec un message qui inclut le statut :

Statut de AICore Comportement du plugin
disponible setModel résout readinessChange émet ready
téléchargeable Rejetés : « Gemini Nano est téléchargeable mais non téléchargé sur cet appareil »
téléchargement Rejet avec l'état de téléchargement
indisponible Rejetés : « Gemini Nano est indisponible sur cet appareil »
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';
}

Le plugin ne démarre pas le téléchargement du modèl’AICore lui-même. Si un appareil signale que le modèl’est téléchargeable, le modèl’arrive généralement après que l'autre application ou le système l'a demandé, donc vérifiez à nouveau à une mise à jour ultérieure plutôt que de cacher la fonctionnalité définitivement.

Étape 2 : Créez un chat et diffusez la réponse

A un chat, l'historique de la conversation est conservé. Sur Android, sendMessage se résout dès le début de la génération, et les textes arrivent par événements. Enveloppez-le dans une promesse qui se résout à 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()));
  }
}

Utilisez-le pour une fonctionnalité réelle, par exemple, rédiger une réponse à une critique de client :

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() ne prend pas d'options, donc placez les instructions au début du premier message. Créez un nouveau chat par tâche. Sur le chemin Gemini Nano, le plugin conserve l'historique en mémoire et l'envoie avec chaque message, donc les longs chats consomment rapidement le budget d'entrée.

Limites à prendre en compte

Limiter Valeur Faire
Entrée Sous environ 4 000 jetons par requête (Google) Keep chats short, trim long documents
Sortie Le plugin limite les réponses Gemini Nano à 256 jetons Demander des sorties courtes, diviser les tâches longues
Principale Seule inférence lorsque votre application est en haut Ne jamais l'exécuter à partir de tâches de fond
Quota Plages de quotas par application, BUSY erreurs de batterie et de quota Évitez la génération à chaque touche clavier
Concurrency Désactiver le bouton d'envoi pendant la diffusion Quotas par application, et erreurs de quota de batterie
Vitesse Plusieurs secondes pour un paragraphe Flux permanent vers l'interface utilisateur

Gérer l'erreur de quota comme temporaire. Afficher une option de réessai plutôt qu'un dialogue d'erreur.

Fallback : Gemma 4 en cas d'absence de Gemini Nano

Most Android phones in use today do not have Gemini Nano. The same plugin can run open Gemma models through LiteRT-LM, so you keep one API. The model is large, often over a gigabyte, so download it only after the user opts in, ideally on Wi-Fi.

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();
  }
}

Choisissez ensuite le moteur au démarrage :

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';
}

Si cela n'est pas possible, masquer la fonctionnalité ou appeler un modèle cloud. N'empêchez pas les flux de base sur l'IA locale.

Le même code sur iOS

Sur iOS, le plugin utilise l'intelligence d'Apple à travers le cadre de modèles de Foundation. Changer une ligne :

await CapgoLLM.setModel({ path: 'Apple Intelligence' });

createChat, sendMessage, et les événements restent les mêmes, et le mergeChunk l'aide ci-dessus gère déjà le format de streaming iOS. Les exigences matérielles diffèrent (iOS 26 et un appareil capable d'Intelligence Apple). Notre guide sur Intelligence Apple dans une application Capacitor couvre cette partie.

Test

  • Utilisez un téléphone réel pris en charge. Les émulateurs ne fournissent pas AICore avec Gemini Nano.
  • Enregistrez le setModel message de refus. Il vous indique exactement quel statut AICore signale.
  • Sur un appareil récemment configuré ou réinitialisé, attendez que AICore termine son initialisation en ligne, puis réessayez.
  • Testez vos requêtes sur la version Nano la plus basse que vous supportez. Les requêtes plus courtes et plus explicites sont plus stables entre versions.

Troubleshooting

“Le Gemini Nano n'est pas disponible sur cet appareil.” Le dispositif n'est pas sur la liste de Google, le bootloader n'est pas verrouillé ou AICore n'est pas configuré encore.

“Le Gemini Nano est téléchargeable mais non téléchargé.” Le dispositif le supporte mais le modèle n'est pas présent. Proposez le Gemma par défaut ou réessayez plus tard.

Session de chat non trouvée. Vous avez appelé sendMessage avec une conversation créée avant une nouvelle setModelCharger un modèl’efface les conversations existantes, créez donc une nouvelle.

“Le modèle n'est pas prêt”. setModel échoué ou n'a pas été appelé avant createChat.

La sortie s'arrête au milieu de phrase. Vous avez atteint la limite de sortie. Demandez une réponse plus courte ou divisez la tâche.

Erreurs lors de la mise en pause de l'application. Inference is foreground-only. Cancel UI state on pause and let the user retry.

Confidentialité et évaluation de l'application

Les prompts et les réponses restent sur le dispositif avec Gemini Nano, ce qui simplifie votre formulaire de sécurité des données. Les termes de Google ML Kit mentionnent toujours la traitement des métriques, donc décrivez l'utilisation de l'IA sur le dispositif dans votre politique de confidentialité. Si vous ajoutez la fallback Gemma, le téléchargement du modèle provient de Hugging Face, donc mentionnez également cette demande de réseau.

Prompts and UI copy for AI features change often. If you need to tune them after release, Capgo live updates let you ship new web code without waiting on store review. For the bigger picture on AI in hybrid apps, read Pourquoi Capacitor convient bien aux applications mobiles AI.

Wrap-up

Gemini Nano offre aux applications Capacitor une génération de texte gratuite, privée et hors ligne sur les téléphones Android pris en charge. Chargez-l’avec setModel({ path: 'Gemini Nano' }), gardez les prompts et les sorties courtes, respectez les règles de fond et de quota, et gardez une fallback Gemma ou cloud pour les nombreux appareils qui ne l'ont pas. textFromAi, keep prompts and outputs short, respect the foreground and quota rules, and keep a Gemma or cloud fallback for the many devices that do not have it.

Live updates for Capacitor apps

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

Actualités de notre Blog

Capgo vous offre les meilleures informations nécessaires pour créer une application mobile véritablement professionnelle.