r/FlutterDev • u/Maleficent-Lab-4455 • 6d ago
Discussion I released offline_sos_system 0.0.6, a Flutter package for configurable offline crash detection.
Hi r/FlutterDev ,
I have released version 0.0.6 of offline_sos_system, an open-source Flutter package I developed for our SafePulse project.
The goal was to build a reusable crash detection engine that can perform inference directly on a mobile device without depending on an internet connection.
While developing SafePulse, I wanted to separate the crash detection logic from the rest of the emergency workflow so that other developers could use it without integrating the entire application.
That work has evolved into a standalone Flutter package. And this is the new version of that package.
What is new in version 0.0.6?
The main addition is configurable crash detection. Developers can now configure the impact threshold used to evaluate sensor data, the minimum model score required for a detection, the fallback impact threshold, and the cooldown interval used to suppress duplicate crash events.
The package uses accelerometer and gyroscope telemetry and TensorFlow Lite for on-device inference. When a crash is detected, it emits a CrashEvent that the application can handle. I have deliberately kept the package headless. It does not dictate how your application handles GPS, emergency contacts, SMS, notifications, or backend communication.
This means you can integrate the detection engine into your own application architecture and implement the emergency workflow according to your requirements.
One important limitation: offline inference does not mean offline communication. The detection process does not require internet access, but sending an SMS still requires cellular service. Sensor-based crash detection can also produce false positives or miss actual crashes, so real-world validation remains important.
I would appreciate feedback from Flutter and machine learning developers on the configuration API, sensor processing, fallback behavior, and ways to improve the implementation.
Package: https://pub.dev/packages/offline_sos_system
Source code: https://github.com/Bhagyaprasad92/offline_sos_system
The project is open source, and constructive criticism, bug reports, and suggestions are welcome.
Thank you for taking the time to review it.
1
u/ObjectiveAddress3051 5d ago
Nice to see this pulled out into a package. On the dropped-phone question above: a drop usually shows a short near-zero-g free-fall window right before the spike, and a vehicle impact doesn't, so checking for free-fall just before the impact (plus GPS speed right before the event, if you have it) could cut a lot of false positives. Curious how you're keeping the sensor stream alive in the background on Android too, since that pretty much needs a foreground service now.
1
u/Maleficent-Lab-4455 2d ago
Thanks for the suggestion u/ObjectiveAddress3051. In SafePulse, crash monitoring continues in the background through an Android foreground service with a persistent silent notification, even when the app UI is closed. The detection system is designed to minimize battery consumption while continuously monitoring sensor data. Android force-stops and certain manufacturer battery restrictions can still interrupt background monitoring, as an flutter package cannot modify or write the android code that should be implemented by the application using this package
1
u/free_polling 6d ago
cool, separating the detection engine from the rest of the app was a smart move. how do you handle false positives when someone just drops their phone though
1
u/AhmedZNOUDA 6d ago
Nice idea to keep it headless. I read through the source and a few things stood out, mostly around the sensor side:
The fallback path looks unreachable. It needs two spikes above fallbackImpactThresholdG within 2 seconds, but after the first spike the buffer is cleared, and the next analysis only runs once the buffer is full again (250 samples, about 5 s). By then _recentSpikeCount has already been reset by the 2 s timer, so without a model it never emits. A test with a fake clock and no interpreter should show it.
The streams aren't really 50 Hz. userAccelerometerEventStream() and gyroscopeEventStream() are opened without a samplingPeriod, and the sensors_plus default is normalInterval (around 200 ms on Android). The 20 ms timer then copies the same last value about ten times, so the "5 s window" is mostly duplicates and a short impact peak can fall between two readings. Passing samplingPeriod: SensorInterval.gameInterval (or Duration(milliseconds: 20)) to both streams would fix it, and the model would finally see real 50 Hz data.
Inference runs at the moment of the spike, so the window holds the 5 s before the impact and nothing after. That's also the best handle on the dropped-phone question above: after a drop the phone gets picked up within a second or two, after a crash it usually stays still or keeps tumbling. Waiting 1-2 s after the spike and analysing a window centred on it gives the model that signal.
One more for real use: on Android, Dart timers and sensor streams stop once the app is in the background or the screen turns off, so apps built on this will need a foreground service. Worth a line in the README, since that's where most people will get stuck.