flutter_imin_lark_scanner 1.0.0
flutter_imin_lark_scanner: ^1.0.0 copied to clipboard
Flutter plugin for the built-in barcode scanner on iMIN Lark Android devices, with continuous scanning and lifecycle support.
flutter_imin_lark_scanner #
A Flutter plugin for the built-in barcode scanner on iMIN Lark Android devices. It configures the iMIN scanner service, listens for scan broadcasts, and supports continuous scanning with lifecycle-aware pause and resume.
Features #
- Configure the iMIN built-in scanner to deliver results via Android broadcast
- Stream barcode values to Dart through an
EventChannel - Trigger single or continuous scans programmatically
ContinuousScanSessionhelper with:- Automatic keep-alive while scanning
- Configurable cooldown between scans
- Duplicate barcode suppression
- App lifecycle pause/resume (background/foreground)
- Reliable cold-start behaviour after app stop and relaunch
- Example app included
Platform support #
| Platform | Support |
|---|---|
| Android | Yes — iMIN Lark devices with the built-in scanner service |
| iOS | Not supported |
This plugin communicates with the iMIN scanner API over Android intents and broadcasts. It is intended for iMIN Lark POS / handheld devices only.
Requirements #
- Flutter
>=3.3.0 - Dart
^3.10.7 - Android
minSdk 24 - iMIN device with the built-in scanner service installed
Installation #
Add the dependency to your pubspec.yaml:
dependencies:
flutter_imin_lark_scanner: ^0.0.1
Then run:
flutter pub get
Usage #
Recommended: continuous scanning session #
The easiest way to use the plugin is through ContinuousScanSession, which handles scanner setup, keep-alive, cooldown, and lifecycle management for you.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_imin_lark_scanner/flutter_imin_lark_scanner.dart';
class ScannerPage extends StatefulWidget {
const ScannerPage({super.key});
@override
State<ScannerPage> createState() => _ScannerPageState();
}
class _ScannerPageState extends State<ScannerPage> {
late final ContinuousScanSession _session;
StreamSubscription<String>? _scanSubscription;
StreamSubscription<void>? _stateSubscription;
@override
void initState() {
super.initState();
_session = FlutterIminLarkScanner.instance.createContinuousSession(
config: const ContinuousScanConfig(
rescanDelay: Duration(seconds: 3),
keepAliveInterval: Duration(seconds: 2),
duplicateSuppression: Duration(milliseconds: 500),
),
);
_scanSubscription = _session.scans.listen((barcode) {
debugPrint('Scanned: $barcode');
});
// Rebuild UI when scanner active/starting state changes.
_stateSubscription = _session.stateChanges.listen((_) {
if (mounted) setState(() {});
});
unawaited(_session.start());
}
@override
void dispose() {
_scanSubscription?.cancel();
_stateSubscription?.cancel();
_session.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
_session.isActive ? 'Scanner active' : 'Scanner stopped',
),
),
);
}
}
Session configuration
| Option | Default | Description |
|---|---|---|
rescanDelay |
3 seconds | Wait time after a successful scan before scanning again |
keepAliveInterval |
2 seconds | How often to re-trigger the hardware scan button while active |
duplicateSuppression |
500 ms | Ignore identical barcodes received within this window |
Session API
| Method / property | Description |
|---|---|
start() |
Prepare and start continuous scanning once the app is resumed |
stop() |
User-initiated stop |
resume() |
Resume after stop() |
dispose() |
Clean up listeners and stop the scanner |
scans |
Stream of barcode strings |
stateChanges |
Stream that fires when isActive or isStarting changes |
isActive |
Whether scanning is currently running |
isStarting |
Whether the session is waiting for the app or hardware |
Lifecycle pause and resume are handled automatically by the session. You do not need a separate WidgetsBindingObserver unless you have other lifecycle logic.
Low-level API #
For manual control, use FlutterIminLarkScanner directly:
final scanner = FlutterIminLarkScanner.instance;
await scanner.prepare();
await scanner.start();
scanner.barcodes.listen((barcode) {
print(barcode);
});
await scanner.trigger(); // trigger a single scan
await scanner.stop();
Example #
See the example/ app for a complete working demo with start/stop controls and scan result display.
cd example
flutter run
How it works #
On Android, the plugin:
- Sends a broadcast to configure the iMIN scanner for broadcast output
- Registers a receiver for
com.imin.scanner.api.RESULT_ACTION - Triggers scanning by simulating the hardware scan key (
KeyEventcode 170) viacom.imin.keyevent - Re-arms the scanner on activity resume and after cold start when continuous scanning is active
Troubleshooting #
Scanner does not start after reopening the app
Use ContinuousScanSession.start() rather than calling the low-level API directly from initState. The session waits until the app lifecycle is resumed before triggering the hardware.
UI shows "Start Scanner" while scanning is active
Listen to session.stateChanges and call setState when it fires. Scanning starts asynchronously after app launch.
No scans received
- Confirm you are running on an iMIN Lark device with the built-in scanner service
- Ensure no other app has exclusive control of the scanner
- Check logcat for the
FLUTTER_IMINtag
Contributing #
Issues and pull requests are welcome in the repository:
https://bitbucket.org/patel-apps/imin_lark_scanner_flutter
License #
See LICENSE.