flutter_native_ai 0.5.0 copy "flutter_native_ai: ^0.5.0" to clipboard
flutter_native_ai: ^0.5.0 copied to clipboard

A Flutter plugin for native on-device generative AI through Apple Foundation Models and Android Gemini Nano.

flutter_native_ai #

A Flutter plugin for private, on-device text generation using native platform AI models. It gives Flutter apps one small Dart API over Apple Foundation Models on Apple platforms and Gemini Nano through ML Kit Prompt API on Android.

The package exposes one Dart API for checking status, optionally initializing a local model, creating a local model session, generating a complete response, and streaming cumulative text updates.

Platform Support #

Platform Minimum app target Native model requirement Runtime behavior
iOS iOS 13.0 Apple Foundation Models on supported OS/device combinations Installs on older iOS versions; status() reports unsupported/not ready when Foundation Models are not present
macOS macOS 13.0 Apple Foundation Models on supported OS/device combinations Installs on macOS 13.0+; status() reports unsupported/not ready when Foundation Models are not present
Android minSdk 26 Gemini Nano through ML Kit Prompt API on supported devices Installs on Android 8.0+; status() reports readiness and whether the model can be initialized/downloaded
Other platforms Not supported None Returns unsupported status

This package does not send prompts or generated text to a server. Generation is performed by native on-device model APIs when those APIs are available.

Use Case #

The package was extracted from Pooka, where it powers short private collection insights without sending collection data to a backend model.

Usage #

import 'package:flutter_native_ai/flutter_native_ai.dart';

final ai = OnDeviceAi();

final status = await ai.status();
if (!status.isAvailable) {
  print(status.reason);
  return;
}

final session = await ai.createSession(
  instructions: 'You are a concise assistant. Keep answers practical.',
);

try {
  final result = await session.generateText(
    prompt: 'Write one sentence about on-device AI.',
    config: const OnDeviceAiGenerationConfig(
      maxTokens: 80,
      temperature: 0.4,
    ),
  );

  print(result.text);
} finally {
  await session.dispose();
}

Streaming:

final session = await ai.createSession();
try {
  await for (final chunk in session.generateTextStream(
    prompt: 'Summarize this in two short sentences.',
  )) {
    print(chunk.text);
  }
} finally {
  await session.dispose();
}

Stream chunks are cumulative snapshots. If the model emits "Hello" and then "Hello world", the stream emits both snapshots rather than only the delta. Only one streaming generation should be active at a time for a plugin instance. Reuse the same OnDeviceAiSession for related prompts when you want native session context to be retained. Dispose the session when that flow is finished.

Status and model initialization #

Always call status() before creating a session. Native model readiness depends on the OS, device, regional/account settings, and whether the local model is present.

The minimum app target only describes where the plugin can be installed. It does not guarantee that native AI is available. For example, iOS versions below the Foundation Models runtime still work as app targets, but this package reports the model as unsupported/not ready. Foundation Models currently requires iOS 26.0 or macOS 26.0 or later at runtime.

OnDeviceAiStatus separates support from readiness:

  • isSupported: the platform/device/OS can support local AI.
  • isReady: generation can run now.
  • isAvailable: convenience getter for isSupported && isReady.
  • canInitialize: the platform can attempt to make the model ready.
  • isInitializing: initialization/download is currently running.
  • initializationProgress: nullable 0..100 progress, only when the platform reports real progress.
  • platformStatus: raw native status for diagnostics.

Android can report a supported model as not ready when Gemini Nano is downloadable. The package never invents progress values. On Android it computes initializationProgress only from ML Kit download byte counts; if progress is not available, the value stays null.

Flow 1: explicit status gate #

Use this when your app wants to decide where and when to initialize the model (for example, behind a user action or on a dedicated setup screen).

final status = await ai.status();
if (status.isAvailable) {
  // Create a session.
} else if (status.canInitialize) {
  // Show a "Download model" or "Prepare AI" action.
} else {
  // Show status.reason or disable local AI.
}

Flow 2: startup or setup initialization #

Use this when your app has a setup step and wants the model ready before the user enters an AI-powered flow.

final status = await ai.ensureReady();
if (!status.isAvailable) {
  print(status.reason);
  return;
}

To show real initialization progress, subscribe before calling ensureReady():

final subscription = ai.statusStream().listen((status) {
  final progress = status.initializationProgress;
  if (status.isInitializing && progress != null) {
    print('Initializing local model: $progress%');
  }
});

try {
  await ai.ensureReady();
} finally {
  await subscription.cancel();
}

Flow 3: just-in-time initialization during session creation #

Use this when you want the smallest app code and are comfortable initializing the model at the moment a session is needed. The default remains safe: createSession() does not initialize or download unless you opt in.

final session = await ai.createSession(
  instructions: 'You are a concise assistant.',
  initializationPolicy: OnDeviceAiInitializationPolicy.whenNeeded,
);

API #

Main entry point:

  • OnDeviceAi

Models:

  • OnDeviceAiGenerationConfig
  • OnDeviceAiGenerationResult
  • OnDeviceAiInitializationPolicy
  • OnDeviceAiStatus
  • OnDeviceAiStreamChunk

Methods:

  • status()
  • ensureReady({OnDeviceAiInitializationPolicy policy})
  • statusStream()
  • createSession({String? instructions, OnDeviceAiInitializationPolicy initializationPolicy})

Session methods:

  • generateText({required String prompt, OnDeviceAiGenerationConfig config})
  • generateTextStream({required String prompt, OnDeviceAiGenerationConfig config})
  • cancelStreamingText()
  • dispose()

Regenerating Platform Bindings #

Platform channels are generated with Pigeon from pigeons/on_device_ai.dart.

dart run pigeon --input pigeons/on_device_ai.dart
dart format lib/src/generated/on_device_ai.g.dart pigeons/on_device_ai.dart

The generated Swift binding is written to darwin/flutter_native_ai/Sources/flutter_native_ai/OnDeviceAi.g.swift so the same Apple implementation can be used by both CocoaPods and Swift Package Manager.

Apple Package Managers #

The iOS and macOS implementations share one Darwin source package under darwin/flutter_native_ai. Flutter apps can consume it through Swift Package Manager or CocoaPods. Both bundled Apple example runners use Swift Package Manager; the macOS example does not include CocoaPods integration.

Pigeon currently emits open fun modifiers in the generated Kotlin event-channel wrapper. Those are removed in the checked-in generated Kotlin binding because the local lint configuration rejects them.

AI-Assisted Development #

This package was built with AI assistance for parts of the implementation, especially around the Pigeon contract, generated platform-channel integration, and native bridge scaffolding. AI was used as an engineering tool in a deliberate implementation process; the package is not vibe-coded.

Notes #

This package is pre-1.0. Apple Foundation Models and Gemini Nano APIs are new and may change. The Dart API is intentionally small so platform-specific changes can be handled behind the plugin boundary.

Android Runtime Limits #

Android generation runs through ML Kit GenAI and AICore. AICore enforces per-app inference quotas, so repeated requests may fail with a busy or quota error. Apps should retry with backoff rather than looping immediately.

Android GenAI inference is only allowed while the app is the top foreground app. Requests from the background, including foreground services, can be blocked by AICore.

Different supported devices may run different Gemini Nano base model versions, so output can vary across Android devices.

3
likes
160
points
634
downloads

Documentation

API reference

Publisher

verified publisherpooka.app

Weekly Downloads

A Flutter plugin for native on-device generative AI through Apple Foundation Models and Android Gemini Nano.

Repository (GitHub)
View/report issues

Topics

#ai #generative-ai #on-device-ai #text-generation #flutter-plugin

License

MIT (license)

Dependencies

flutter, meta

More

Packages that depend on flutter_native_ai

Packages that implement flutter_native_ai