app_settings_ai

On-device AI settings proposals for the app_settings plugin. Free and MIT licensed.

Turns a natural-language complaint — "I'm not getting message alerts" — into a ranked list of settings screens to open, with a short rationale for each. Inference runs entirely on the device: Apple Foundation Models on iOS 26+ (Apple Intelligence devices) and the ML Kit GenAI Prompt API / Gemini Nano on supported Android devices. Nothing leaves the device.

This is a separate package on purpose. app_settings stays dependency-free, so apps that just want to open a settings screen don't pay for an on-device model runtime or a raised SDK floor.

Installation

flutter pub add app_settings_ai

app_settings comes along as a dependency; import whichever you need.

iOS requires Xcode 26+ to build the real implementation and, like app_settings, Swift Package Manager:

flutter config --enable-swift-package-manager

Usage

import 'package:app_settings_ai/app_settings_ai.dart';

// Gate your UI on this: many devices on both platforms report unavailable.
final availability = await AppSettingsAI.availability();
if (availability.canDownload) await AppSettingsAI.prepareModel();

final result = await AppSettingsAI.proposeSettings(
  request: "I'm not getting message alerts",
  context: {'notificationsEnabled': false},
  allowedSettings: [
    AppSettingsType.notification,
    AppSettingsType.batteryOptimization,
    AppSettingsType.wifi,
  ],
);

if (result.isOk) {
  for (final proposal in result.proposals) {
    print('${proposal.title} (${proposal.setting.name}) — ${proposal.rationale}');
    // await proposal.open();
  }
}

proposeSettings never throws. A device that cannot run the model yields SettingsProposalStatus.unavailable with a unavailableReason; a failed generation yields SettingsProposalStatus.error. Check result.status rather than catching.

Both native handlers test capability themselves before generating, so there is no separate round trip to check it first.

Running the example

cd example && flutter run

Nothing to configure. availability() works everywhere; generating real proposals needs a device that supports on-device inference. See example/lib/main.dart for the availability card and proposal list.

How the two platforms are kept consistent

Both platforms receive the same instructions and prompt, built in Dart, and return the same payload shape:

{
  status:    "ok" | "unavailable" | "error",
  provider:  "apple_foundation_models" | "mlkit_gemini_nano",
  reason?:   unsupportedOsVersion | deviceNotEligible | notEnabled |
             modelDownloadable | modelDownloading | modelNotReady | unknown,
  message?:  String,
  proposals: [ { setting: String, title: String, rationale: String, confidence: double } ]
}

Dart then does all the validation in one place — dropping unknown or duplicate setting keys, clamping confidence, sorting by confidence and capping the count — so iOS and Android are held to identical rules.

Requirements and caveats

  • Gate your UI with availability(). Many devices on both platforms report unavailable, and App Review / Play reviewers need a supported device to see the feature.
  • iOS: needs Xcode 26+ to build the real implementation. FoundationModels is weak-linked, so the plugin still loads and runs on systems without it; those devices report unsupportedOsVersion rather than failing to launch. In practice the floor is iOS 15: the iOS 27 SDK in Xcode 26 sets MinimumDeploymentTarget to 15.0, so no app built with a current Xcode can deploy lower, whatever Package.swift declares. The package itself still declares .iOS("13.0") for older toolchains, where the handler compiles as unavailable.
  • Android: genai-prompt targets API 26+. This plugin keeps minSdk 16 and reports unsupportedOsVersion below 26. Inference must run while the app is in the foreground (BACKGROUND_USE_BLOCKED); AICore also enforces a per-app quota and blocks devices with an unlocked bootloader.
  • Output differences: iOS uses guided generation, so its structure is guaranteed. Android asks Gemini Nano for JSON and parses it; malformed output returns SettingsProposalStatus.error.

License

MIT. See LICENSE.

Libraries

app_settings_ai
On-device AI settings proposals for the app_settings plugin.