dartpub.dev DartNative · beta
plugins / battery_kit
ba

battery_kit

v0.1.0 MIT

Battery level and charging state for iOS and Android over FFI.

On-demand battery level and charging state for DartNative apps on iOS and Android, read over FFI with no permissions, polling, or listeners.

by saitojo1106/battery_kit · DartNative ≥ 3.0 · updated 5 days ago
Install
Free
pubspec.yaml
dependencies:
  battery_kit:
    hosted: https://dartpub.dev
    version: ^0.1.0
Weekly installs
0
Active apps
0
Rating
0.0 · 0
Open issues
0

battery_kit

On-demand battery level and charging state for DartNative apps on iOS and Android.

  • iOS reads UIDevice; Android reads the sticky ACTION_BATTERY_CHANGED broadcast. Both are called over FFI in a single native round trip.
  • No extra permissions, no background work, no persistent listeners.
  • An unavailable level is reported as null, never silently as 0.

Install

battery_kit is published on dartpub.dev. Add a plain version dependency to your app's pubspec.yaml; it resolves the same way the DartNative framework itself does:

dependencies:
  battery_kit: ^0.1.0

Then fetch it with:

dn pub get

The generated dartnative_plugin_registrant.dart loads the FFI symbols; call DartNativePluginRegistrant.registerAll() in main() as usual. Android requires minSdk 26 or higher; iOS requires iOS 15 or higher.

Usage

import 'package:battery_kit/battery_kit.dart';

final battery = Battery();
print(await battery.level);      // 0..100, throws BatteryUnavailableException
print(await battery.state);      // BatteryState.charging, ...
print(await battery.isCharging); // false for full / notCharging

// One read for both values:
final info = await battery.info;
print(info.level); // null when the OS cannot report a percentage

Public API

Member Description
Battery.level Future<int> from 0 to 100. Throws BatteryUnavailableException when unknown.
Battery.state Future<BatteryState>: unknown, charging, discharging, full, notCharging.
Battery.isCharging Future<bool>; full and notCharging are false.
Battery.info Future<BatteryInfo> with level (int?) and state from the same OS reading.

notCharging is Android's "connected but not charging" state. iOS never reports it. Simulators and emulators may report an unknown level.

On iOS 17 and later the system rounds UIDevice.batteryLevel to the nearest 5%, so level can differ from the status bar by up to 2 points (for example 89% is reported as 90). This is an OS limitation, not something the plugin can work around.

On iOS, battery monitoring is enabled only for the duration of the read and restored to its previous setting afterwards. Continuous monitoring is out of scope for this version.

How it works

Read in this order:

  1. lib/src/battery.dart – public API and result types
  2. lib/src/battery_ffi_bindings.dart – Dart side of the FFI call
  3. ios/Classes/DNBattery.swift – iOS implementation
  4. android/src/main/kotlin/io/github/saitojo1106/battery_kit/DNBatteryBridge.kt – Android implementation
  5. android/src/main/cpp/dn_battery.cpp – JNI glue between Dart and Kotlin

The native side returns one integer, state * 256 + (level + 1). A zero low byte means the level is unavailable. No strings or callbacks cross the FFI boundary.

Example

example/ is a dn create app that depends on this plugin via path: ../.

cd example
dn pub get
dn run -d <device-id>

The screen shows the current level and state with a refresh button.

Tested on

Platform Device Result
Android 16 Pixel 8a Level and state match the OS, including full and notCharging.
iOS 18.7 iPhone 16e Level matches the OS within the 5% rounding above; charging and discharging follow the cable.

Verified 2026-09-15 with DartNative SDK 3.45.0. Run dart test for the decoding tests.

License

MIT. See LICENSE.