跳过主要内容

如何在 Capacitor 应用中使用 Gemini Nano

在安卓设备上使用Gemini Nano进行Capacitor应用的设备支持、AICore检查、@capgo/capacitor-llm流式处理以及Gemma备用。

文章来源

马丁·多纳迪厄

作者

瓦莱里亚

审稿人

乔丹

编辑

如何在 Capacitor 应用中使用 Gemini Nano

要在 Capacitor 应用中使用 Gemini Nano,请安装 @capgo/capacitor-llm,然后 setModel({ path: 'Gemini Nano' }) 在 Android 设备上,创建一个聊天并通过流式传输回复 textFromAi 通过事件。该插件通过Google的ML Kit GenAI Prompt API与Gemini Nano进行通信,后者在Android的AICore系统服务中运行模型,因此文本永远不会离开手机。

本指南涵盖了Gemini Nano的运行方式、支持的设备、准确的插件调用、流媒体、配额和限制、对不支持手机的Gemma fallback以及如何让相同的 code 在iOS上访问Apple Intelligence。

Android上Gemini Nano的运行方式

Gemini Nano是Google的最小Gemini模型,专为手机设计。应用程序不需要将其打包。Android的 AICore 服务下载它、更新它并运行推理,并且应用程序通过 机器学习 Kit GenAI API:

  • API: 自由形式文本提示,插件使用的 API(com.google.mlkit:genai-prompt).
  • 功能API: 固定任务,如摘要、校对、重写和图像描述。

Google将Prompt API作为beta版本发布,没有SLA或弃用政策,因此在发布之间期望行为变化,并将集成放在自己的小包装后面。

因为推理是本地的,你可以获得三件云模型无法提供的东西:它可以在离线状态下工作,它没有每个令牌的成本,用户文本也会在设备上保留。 交易的代价是使用较小的模型,具有短的上下文和输出,因此选择适合的任务:重写、摘要笔记、分类消息、提取字段、撰写短回复。

支持设备和要求

Google 在 ML Kit GenAI 网站上每个 API 发布支持列表,按 Gemini Nano 版本(nano-v2、nano-v3、nano-v4)分组。对于 Prompt API,它涵盖了 Pixel 9 和更高版本、最近的 Samsung Galaxy S 和 Z 旗舰机型,以及来自 OnePlus、OPPO、Xiaomi、vivo、Honor、realme、Motorola 等的最近旗舰机型。检查实时列表之前,请不要对特定设备承诺特定功能。

每个支持的设备也需要:

要求 详细信息
Android 版本 API 26 或更高(插件会检查这个)
引导程序 锁定。 Google 不支持在解锁引导程序上运行 GenAI API
AI Core 存在并已设置。 在设备设置或重置后,可能需要一段时间才能完成
App 状态 您的应用程序必须在推理期间是前台应用程序

不同版本的 Nano 可能会为相同的提示返回不同的输出。请在您关心的每个版本上测试您的提示

安装插件

bun add @capgo/capacitor-llm
bunx cap sync

插件遵循 Capacitor 的主要版本:使用 8.x 与 Capacitor 8。无需对 Android 清单进行任何更改。详细参考: 插件文档 并且 插件页面.

步骤 1:加载 Gemini Nano 并检查就绪

setModel 与特殊路径 'Gemini Nano' 询问 ML Kit 模型状态。它会在状态可用时解析,否则会拒绝,并包含状态信息的消息:

来自 AICore 的状态 插件行为
可用 setModel 解决 readinessChange 发射 ready
可下载 拒绝:"Gemini Nano 可下载但未在此设备上下载"
下载中 拒绝下载中状态
不可用 拒绝:"Gemini Nano 在此设备上不可用"
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';
}

该插件不会启动 AICore 模型的下载。 如果设备报告可下载,模型通常在另一个应用程序或系统请求它后才会到达,因此请在稍后启动时再次检查,而不是永久隐藏该功能。

步骤 2:创建聊天并流式传输答案

在 Android 上,一个聊天会保留会话历史。 sendMessage Android上, 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()));
  }
}

使用它来实现一个真正的功能,例如撰写回复给客户评论:

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() 用于真实功能,例如为客户评论撰写回复:

takes no options, so put instructions at the start of the first message. Create a new chat per task. On the Gemini Nano path the plugin keeps the history in memory and sends it with every message, so long chats use up the input budget quickly.

Limit Value 设计限制
Limit 限制 Value
值 该插件限制了Gemini Nano响应的最大token数为256 要求短输出,拆分长任务
前台 仅在应用程序处于前台时进行推理 永不从后台任务运行
配额 每个应用程序的配额, BUSY 以及电池配额错误 防抖,避免在每次按键时生成
并发 每次聊天生成一个 禁用发送按钮时进行流式传输
速度 几秒钟内显示一个段落 始终将流式传输到 UI

当遇到配额错误时,视为暂时性错误。显示一个重试选项而不是错误对话框。

fallback:当 Gemini Nano 缺失时使用 Gemma 4

大多数今天使用的 Android 手机都没有 Gemini Nano。同样的插件可以通过 LiteRT-LM 运行开源的 Gemma 模型,所以您可以保留一个 API。该模型很大,通常超过 1GB,因此只在用户同意后下载,理想情况下在 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();
  }
}

然后在启动时选择引擎:

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

如果两者都不可能,隐藏该功能或调用云模型。不要阻塞本地 AI 流程。

同样的 code 在 iOS 上

在 iOS 上,插件使用 Apple Intelligence 通过 Foundation Models 框架。只需修改一行代码:

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

createChat, sendMessage,并且事件保持不变, mergeChunk 上面的助手已经处理了 iOS 流式传输格式。设备要求不同(iOS 26 和 Apple Intelligence 兼容设备)。我们的指南在 Apple Intelligence 在一个 Capacitor 应用中 涵盖了这一方面。

测试

  • 使用一个支持的真实手机。模拟器无法为 Gemini Nano 提供 AICore。
  • 记录 setModel 拒绝消息。它告诉你 AICore 报告的准确状态。
  • 在一个刚刚设置或重置的设备上,等待 AICore 完成其初始设置时在线,然后重试。
  • 在您支持的最低 Nano 版本上测试您的提示。更短、更明确的提示在版本之间更稳定。

故障排除

“Gemini Nano 在此设备上不可用。” “Gemini Nano 在此设备上不可用。”

设备未在 Google 的列表中,引导程序已解锁,或者 AICore 尚未设置好。 该设备支持,但模型未找到。建议使用Gemma fallback或稍后重试。

“会话未找到”。 您打电话 sendMessage 与一个创建在新 setModel之前的会话。加载模型会清除现有的会话,所以请创建一个新的。

“模型未准备好”。 setModel 失败或未被调用 createChat.

输出中断。您已达到输出限制。请要求更短的答案或将任务分解。 应用程序进入后台时出现错误。

推理仅限前台。请在暂停时取消UI状态并让用户重试。 隐私和商店评论

__CAPGO_KEEP_0__

Gemini Nano让数据安全表单变得更加简单,所有的提示和响应都在设备上进行处理。Google的ML Kit条款仍然提到指标处理,因此在隐私政策中描述设备上的AI使用。如果您添加了Gemma fallback,模型下载来自Hugging Face,因此也要提到网络请求。

AI特性的提示和UI复制内容经常会改变。如果您需要在发布后调整它们 Capgo 实时更新 让您在不等待应用商店审核的情况下快速发布新的Web code。有关混合应用中的AI的更大图景,请阅读 为什么Capacitor适合于AI移动应用.

总结

Gemini Nano 为支持的 Android 手机提供了免费、私密、离线的 Capacitor 应用程序的文本生成功能。 setModel({ path: 'Gemini Nano' })流式传输 textFromAi,保持提示和输出短,遵守前景和配额规则,并为无法安装它的许多设备保留一个Gemma或云fallback。

Capacitor应用的即时更新

当web层bug活跃时,通过Capgo将修复推送给用户,而不是等待几天的应用商店审批。用户在后台接收更新,而原生变化仍然在正常审批路径中。

最新博客文章

Capgo 为您提供了创建真正专业的移动应用所需的最佳见解。