simple_native_timer 0.1.1
simple_native_timer: ^0.1.1 copied to clipboard
High-precision native timers for Flutter apps on Windows and macOS with background execution support.
simple_native_timer #
High-precision native timers for Flutter apps on Windows and macOS. The plugin uses
platform APIs (QueryPerformanceCounter on Windows, mach_absolute_time and
DispatchSourceTimer on macOS) to provide periodic timers with millisecond-level
accuracy, even during background execution.
Features #
- ✅ High precision foreground timers (±0.1-1 ms)
- ✅ Reliable background timers (±1-5 ms for ≥10 s intervals)
- ✅ Automatic background execution management
- Windows:
SetThreadExecutionState,SetPriorityClass - macOS:
IOPMAssertionCreateWithName
- Windows:
- ✅ Dual callback delivery (EventChannel + MethodChannel fallback only when needed)
- ✅ Thread-safe implementations with drift compensation
- ✅ Flutter-first API with detailed tick metadata
Installation #
Add the dependency to your pubspec.yaml:
dependencies:
simple_native_timer: ^0.1.0
Prerequisites #
This plugin requires:
- Flutter SDK 3.3.0 or higher
- Dart SDK 3.7.0 or higher
- macOS: Xcode 14.0+, CocoaPods 1.16+
- Windows: Visual Studio 2019 or later with C++ desktop development tools
If you're using asdf for version management, create a .tool-versions file in your project root:
ruby 3.2.0
flutter 3.29.0-stable
Then install CocoaPods:
gem install cocoapods
Usage #
import 'package:simple_native_timer/simple_native_timer.dart';
Future<void> main() async {
final timer = await SimpleNativeTimer.periodic(
const Duration(seconds: 10),
(tick) {
debugPrint('[Timer ${tick.id}] seq=${tick.sequence} drift=${tick.drift.inMicroseconds}µs');
},
backgroundMode: true,
);
// Later…
await timer.cancel();
}
Each SimpleNativeTimerTick includes:
id: Unique timer identifiertimestamp: Local timestamp when firedsequence: Sequential tick numbersource: Eitherforegroundorbackgrounddrift: Measured drift vs expected schedule
Background mode #
Passing backgroundMode: true keeps the CPU awake to maintain precision. This
increases power usage; always inform users and disable when not required.
Example app #
The included example (example/lib/main.dart) demonstrates:
- Real-time tick counter with visual statistics
- Average drift and jitter calculations
- Configurable intervals (1s, 5s, 10s, 30s, 1m)
- Background mode toggle with power usage warning
- Platform version display
- Window management with minimum size constraints (using
window_manager)
Running the example #
cd example
flutter pub get
flutter run -d macos # or -d windows
The example app window has a minimum size of 600×690 pixels to ensure proper UI layout.
Platform details #
Windows #
- Dedicated high-priority thread per timer
- Uses
QueryPerformanceCounterfor scheduling - Drift compensation and cooperative waits (Sleep/SRQ)
- EventChannel for foreground delivery; MethodChannel fallback for background
- Tick events marshaled to Flutter's UI thread via WindowProc delegate (PostMessage to view HWND)
macOS #
DispatchSourceTimerwith QoS.userInitiatedand 100 µs leewaymach_absolute_time(viaclock_gettime_nsec_np) for precise drift calculationsIOPMAssertionCreateWithNamewithkIOPMAssertionTypeNoIdleSleepprevents App Nap during background timers- Reference-counted power assertions automatically released when all background timers are cancelled
- Thread-safe
BackgroundModeManagerwith NSLock synchronization - EventChannel for foreground delivery; MethodChannel fallback for background delivery
- Event dispatch on main queue for Flutter integration
API reference #
| Method | Description |
|---|---|
SimpleNativeTimer.periodic(interval, callback, backgroundMode) |
Creates a new timer |
SimpleNativeTimer.shutdown() |
Cancels all timers and releases resources |
SimpleNativeTimer.platformVersion |
Returns underlying platform version |
SimpleNativeTimerTick |
Per-tick metadata |
Logging #
Native implementations emit debug logs when compiled in debug mode. In release mode they remain silent for performance.
macOS #
Logs are emitted via os_log framework with subsystem "simple_native_timer" and category "timer".
What gets logged:
- Timer creation/cancellation with ID, interval, and background mode
- Power assertion lifecycle (creation, release, errors)
- Background mode reference counting
- Timer ticks (every 10th tick to avoid spam) with drift measurements
- Shutdown operations
View logs in Console.app:
- Open Console.app (Applications → Utilities)
- Select your Mac in the sidebar
- Search filter:
subsystem:simple_native_timer
View logs in Terminal:
log stream --predicate 'subsystem == "simple_native_timer"' --level debug
Example log output:
Timer 1 created: interval=10000000 µs, background=1
Power assertion created (ID: 123)
Background mode acquired, active count: 1
Timer 1 tick #10, drift: -234 µs
Timer 1 tick #20, drift: 156 µs
Timer 1 cancelled
Background mode released, active count: 0
Releasing power assertion (ID: 123)
Windows #
Logs are emitted via OutputDebugString (visible in Visual Studio Output window or DebugView).
Error handling #
- Invalid arguments throw
ArgumentErroron Dart side - Platform errors return
FlutterError - Timer callbacks run within
scheduleMicrotaskto avoid blocking native threads
Contribution #
Issues and pull requests are welcome. Please ensure:
- New features include tests or example updates
- Code follows
flutter_lints - Platform code remains thread-safe
License #
See LICENSE.
Testing #
| Command | Description |
|---|---|
flutter test |
Runs unit tests (Dart-side API, channel handling) |
cd example && flutter test integration_test/plugin_integration_test.dart |
Runs integration tests for macOS/Windows (ticks, cancel, shutdown) |
Troubleshooting #
CocoaPods not installed or not in valid state (macOS) #
If you encounter CocoaPods not installed or not in valid state error:
- Ensure you have a
.tool-versionsfile in project root (see Prerequisites) - Install CocoaPods:
gem install cocoapods - Install pods:
cd example/macos && pod install - If using zsh, add to
~/.zshrc:export LANG=en_US.UTF-8
Build errors on macOS #
- Clean build:
flutter clean && cd example/macos && pod install - Ensure Xcode Command Line Tools:
xcode-select --install - Check Flutter doctor:
flutter doctor -v
Overflow errors in example app #
The example app requires a minimum window size of 600×690 pixels. If you see rendering overflow warnings, resize the window or modify WindowOptions in example/lib/main.dart.