Para usar Gemini Nano en una Capacitor aplicación, instale @capgo/capacitor-llmllame setModel({ path: 'Gemini Nano' }) en Android, luego cree un chat y transmita la respuesta a través de textFromAi El plugin se comunica con Gemini Nano a través de la plantilla de Google ML Kit GenAI API, que ejecuta el modelo dentro del sistema de servicio AICore de Android, por lo que el texto nunca sale del teléfono.
Esta guía cubre cómo funciona Gemini Nano, qué dispositivos lo soportan, las llamadas de plugin exactas, streaming, cuotas y límites, un fallback de Gemma para teléfonos no compatibles y cómo la misma code llega a Apple Intelligence en iOS.
Cómo funciona Gemini Nano en Android
Gemini Nano es el modelo Gemini más pequeño de Google, diseñado para teléfonos. Las aplicaciones no lo incluyen. AICore servicios descargan, actualizan y ejecutan inferencia, y las aplicaciones acceden a través de La plantilla __CAPGO_KEEP_0__::
- Prompt API: textos de entrada libre, el API que utiliza este plugin (
com.google.mlkit:genai-prompt). - Funciones de API tareas fijas como resumen, corrección de errores, redacción y descripción de imágenes.
Google ships the Prompt API as a beta, without an SLA or deprecation policy, so expect behavior changes between releases and keep the integration behind your own small wrapper.
Porque la inferencia es local, obtienes tres cosas que un modelo en la nube no puede darte: funciona sin conexión, no tiene un costo por token, y el texto del usuario se queda en el dispositivo. El trueque es un modelo más pequeño con un contexto y una salida cortos, así que elige tareas que se adapten: reescribir, resumir un nota, clasificar un mensaje, extraer campos, redactar respuestas cortas.
Dispositivos y requisitos soportados
Google publica la lista de dispositivos soportados por API en el sitio de ML Kit GenAI, agrupados por versión de Gemini Nano (nano-v2, nano-v3, nano-v4). Para la Promp API cubre el Pixel 9 y posterior, los últimos Samsung Galaxy S y Z, y los últimos flagships de OnePlus, OPPO, Xiaomi, vivo, Honor, realme, Motorola y otros. Verifica la lista en vivo antes de prometer una característica a un dispositivo específico.
Every supported device also needs:
| Requisito | Detalles |
|---|---|
| Versión de Android | Nivel API 26 o superior (el plugin verifica esto) |
| Bootloader | Bloqueado. Google no soporta las API GenAI en bootloaders desbloqueados |
| AICore | Presente y configurado. Después de una configuración o reinicio del dispositivo puede tardar un rato en terminar |
| App state | Su aplicación debe ser la aplicación de primer plano durante la inferencia |
Las diferentes versiones de Nano pueden devolver diferentes resultados para el mismo prompt. Pruebe sus prompts en al menos un dispositivo por versión que le interese.
Instale el plugin
bun add @capgo/capacitor-llm
bunx cap sync
Sigue la versión mayor de Capacitor: utilice 8.x con Capacitor 8. No se necesitan cambios en el archivo AndroidManifest.xml para Gemini Nano. Referencia completa: plugin docs y página del plugin.
Paso 1: Cargue Gemini Nano y verifique la disponibilidad
setModel con la ruta especial 'Gemini Nano' Pide al kit de ML el estado del modelo. Resuelve cuando el estado está disponible y rechaza en caso contrario, con un mensaje que incluye el estado.
| Estado de AICore | Comportamiento del plugin |
|---|---|
| disponible | setModel se resuelve readinessChange emite ready |
| descargable | Rechaza: “Gemini Nano es descargable pero no descargado en este dispositivo” |
| descargando | Rechaza con el estado de descarga |
| inaccesible | Rechaza: “Gemini Nano no está disponible en este dispositivo” |
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';
}
El plugin no inicia la descarga del modelo AICore por sí mismo. Si un dispositivo informa que es descargable, el modelo suele llegar después de que otra aplicación o el sistema lo solicite, por lo que compruebe de nuevo en una posterior ejecución en lugar de ocultar la característica permanentemente.
Step 2: Crea un chat y transmite la respuesta
Una conversación mantiene el historial de la conversación. En Android, sendMessage resuelve tan pronto como comienza la generación, y el texto llega a través de eventos. Envuélvelo en una promesa que resuelve cuando 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()));
}
}
Utilízalo para una característica real, por ejemplo, redactar una respuesta a una reseña de un cliente:
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() no toma opciones, así que coloca instrucciones al principio del primer mensaje. Crea una nueva conversación por tarea. En el camino de Gemini Nano, el plugin mantiene el historial en memoria y lo envía con cada mensaje, por lo que las conversaciones largas consumen rápidamente el presupuesto de entrada.
Limitaciones para diseñar
| Límite | Valor | Qué hacer |
|---|---|---|
| Entrada | Mantén las conversaciones cortas, recorta documentos largos | Keep chats short, trim long documents |
| Output | El plugin limita las respuestas de Gemini Nano a 256 tokens | Pedir salidas cortas, dividir tareas largas |
| Antecedente | Inference only while your app is on top | Never ejecutarla desde tareas de fondo |
| Límite | Cuotas por aplicación BUSY Evitar generar en cada tecleado |
Debounce, avoid generating on every keystroke |
| Concurrency | Una generación por chat | Desactiva el botón de envío mientras se transmite |
| Velocidad | Algunos segundos para un párrafo | Siempre transmitir a la interfaz de usuario |
Trata un error de cuota como temporal. Muestra una opción de reintento en lugar de un diálogo de error.
Alternativa: Gemma 4 cuando el Gemini Nano está ausente
La mayoría de los teléfonos Android en uso hoy en día no tienen Gemini Nano. El mismo plugin puede ejecutar modelos Gemma abiertos a través de LiteRT-LM, por lo que mantén uno API. El modelo es grande, a menudo supera un gigabyte, así que descárgalo solo después de que el usuario acepte, idealmente en 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();
}
}
Entonces elige el motor al arrancar:
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 ninguna es posible, oculta la característica o llama a un modelo en la nube. No bloquear flujos de núcleo en IA local.
La misma code en iOS
En iOS el plugin utiliza Inteligencia de Apple a través del marco de modelos Fundamentales. Cambia una línea:
await CapgoLLM.setModel({ path: 'Apple Intelligence' });
createChat, sendMessage, y los eventos siguen siendo los mismos, y el mergeChunk ayudante anterior ya maneja el formato de transmisión de iOS. Los requisitos del dispositivo difieren (iOS 26 y un dispositivo capaz de Inteligencia de Apple). Nuestra guía sobre Inteligencia de Apple en una Capacitor app aborda ese lado.
Pruebas
- Utilice un teléfono real compatible. Los emuladores no proporcionan AICore con Gemini Nano.
- Registre el
setModelmensaje de rechazo. Le dice exactamente qué estado informa AICore. - Espera a que AICore termine su configuración inicial mientras estás conectado a Internet, luego vuelve a intentarlo.
- Prueba tus solicitudes en la versión Nano más baja que soportes. Las solicitudes más cortas y explícitas son más estables entre versiones.
Solución de problemas
“El Gemini Nano no está disponible en este dispositivo.” El dispositivo no está en la lista de Google, el arranque de carga está desbloqueado o AICore no está configurado aún.
“Gemini Nano es descargable pero no descargado”. El dispositivo lo soporta, pero el modelo no está presente. Ofrezca la Gemma de respaldo o inténtelo más tarde.
“No se encontró la sesión de chat”. Llamó sendMessage con un chat creado antes de un nuevo setModel. Cargar un modelo elimina los chats existentes, así que crea uno nuevo.
“El modelo no está listo”. setModel o falló o no se llamó antes createChat.
La salida se detiene en medio de la oración. Usted golpeó el límite de salida. Pida una respuesta más corta o divida la tarea.
Errores cuando la aplicación se pone en segundo plano. Inference is foreground-only. Cancel UI state on pause and let the user retry.
Privacidad y revisión de la tienda
Prompts y respuestas se mantienen en el dispositivo con Gemini Nano, lo que simplifica tu formulario de seguridad de datos. Los términos de Google ML Kit todavía mencionan el procesamiento de métricas, así que describe el uso de inteligencia artificial en el dispositivo en tu política de privacidad. Si agregas la Gemma de fallback, la descarga del modelo proviene de Hugging Face, así que menciona esa solicitud de red también.
Prompts and UI copy for AI features change often. If you need to tune them after release, Capgo live updates Deje que envíe nuevos sitios web code sin esperar la revisión de la tienda. Para una visión más amplia sobre el AI en aplicaciones híbridas, lea why Capacitor works well for AI mobile apps.
Wrap-up
Gemini Nano ofrece a las Capacitor aplicaciones textos generados gratuitos, privados y offline en teléfonos Android compatibles. Cargue con setModel({ path: 'Gemini Nano' }), transmitir 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.