trcr/lib/preferences.dart

154 lines
6 KiB
Dart
Raw Normal View History

2025-05-05 22:43:43 -07:00
import 'dart:io';
import 'dart:math';
2025-05-07 17:42:07 -07:00
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
2025-05-05 22:43:43 -07:00
import 'package:shared_preferences/shared_preferences.dart';
2025-06-03 22:27:07 -07:00
import 'package:shared_preferences_android/shared_preferences_android.dart';
2025-05-05 22:43:43 -07:00
class Preferences {
2025-06-03 22:27:07 -07:00
static late SharedPreferencesWithCache instance;
2025-05-05 22:43:43 -07:00
static const String id = 'id';
static const String url = 'url';
static const String accuracy = 'accuracy';
static const String interval = 'interval';
static const String distance = 'distance';
2025-06-11 17:47:43 -07:00
static const String heartbeat = 'heartbeat';
2025-05-05 22:43:43 -07:00
static const String buffer = 'buffer';
2025-06-11 22:21:50 -07:00
static const String stopDetection = 'stop_detection';
2025-05-05 22:43:43 -07:00
static Future<void> init() async {
2025-06-03 22:27:07 -07:00
instance = await SharedPreferencesWithCache.create(
sharedPreferencesOptions: Platform.isAndroid
? SharedPreferencesAsyncAndroidOptions(backend: SharedPreferencesAndroidBackendLibrary.SharedPreferences)
: SharedPreferencesOptions(),
cacheOptions: SharedPreferencesWithCacheOptions(
allowList: {
2025-06-13 15:11:58 -07:00
id, url, accuracy, interval, distance, buffer, heartbeat, stopDetection,
2025-06-03 22:27:07 -07:00
'device_id_preference', 'server_url_preference', 'accuracy_preference',
'frequency_preference', 'distance_preference', 'buffer_preference',
},
),
);
2025-06-06 10:38:48 -07:00
if (Platform.isAndroid) {
if (instance.get(interval) is String) {
final stringValue = instance.getString(interval);
await instance.setInt(interval, int.tryParse(stringValue ?? '') ?? 300);
}
if (instance.get(distance) is String) {
final stringValue = instance.getString(distance);
2025-06-10 07:37:09 -07:00
final intValue = int.tryParse(stringValue ?? '') ?? 75;
await instance.setInt(distance, intValue > 0 ? intValue : 75);
2025-06-06 10:38:48 -07:00
}
} else {
2025-05-10 09:51:51 -07:00
await _migrate();
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
await instance.setString(id, instance.getString(id) ?? (Random().nextInt(90000000) + 10000000).toString());
await instance.setString(url, instance.getString(url) ?? 'http://demo.traccar.org:5055');
await instance.setString(accuracy, instance.getString(accuracy) ?? 'medium');
await instance.setInt(interval, instance.getInt(interval) ?? 300);
2025-06-10 07:37:09 -07:00
await instance.setInt(distance, instance.getInt(distance) ?? 75);
2025-05-10 09:51:51 -07:00
await instance.setBool(buffer, instance.getBool(buffer) ?? true);
2025-06-11 22:21:50 -07:00
await instance.setBool(stopDetection, instance.getBool(stopDetection) ?? true);
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
static bg.Config geolocationConfig() {
2025-06-13 15:25:53 -07:00
final locationUpdateInterval = (instance.getInt(interval) ?? 0) * 1000;
2025-06-11 22:21:50 -07:00
final heartbeatInterval = instance.getInt(heartbeat) ?? 0;
2025-05-07 17:42:07 -07:00
return bg.Config(
2025-06-13 15:22:38 -07:00
enableHeadless: true,
2025-05-07 17:42:07 -07:00
stopOnTerminate: false,
startOnBoot: true,
2025-05-10 09:51:51 -07:00
desiredAccuracy: switch (instance.getString(accuracy)) {
2025-05-07 17:42:07 -07:00
'high' => bg.Config.DESIRED_ACCURACY_HIGH,
'low' => bg.Config.DESIRED_ACCURACY_LOW,
_ => bg.Config.DESIRED_ACCURACY_MEDIUM,
},
2025-05-31 21:58:52 -07:00
url: _formatUrl(instance.getString(url)),
2025-05-07 17:42:07 -07:00
params: {
2025-05-10 09:51:51 -07:00
"device_id": instance.getString(id),
2025-05-07 17:42:07 -07:00
},
2025-05-10 09:51:51 -07:00
distanceFilter: instance.getInt(distance)?.toDouble(),
2025-06-13 15:25:53 -07:00
locationUpdateInterval: locationUpdateInterval > 0 ? locationUpdateInterval : null,
2025-06-11 17:47:43 -07:00
heartbeatInterval: heartbeatInterval > 0 ? heartbeatInterval : null,
2025-06-10 07:39:30 -07:00
maxRecordsToPersist: instance.getBool(buffer) != false ? -1 : 1,
2025-06-13 15:03:00 -07:00
logLevel: bg.Config.LOG_LEVEL_VERBOSE,
2025-05-09 07:56:34 -07:00
logMaxDays: 1,
2025-05-31 21:58:52 -07:00
locationTemplate: _locationTemplate(),
2025-06-11 17:47:43 -07:00
showsBackgroundLocationIndicator: false,
2025-06-13 15:11:58 -07:00
preventSuspend: heartbeatInterval > 0,
2025-06-13 14:28:18 -07:00
disableElasticity: true,
2025-06-11 22:21:50 -07:00
disableStopDetection: instance.getBool(stopDetection) == false,
pausesLocationUpdatesAutomatically: instance.getBool(stopDetection) == false,
2025-05-07 17:42:07 -07:00
);
}
2025-05-31 21:58:52 -07:00
static String? _formatUrl(String? url) {
if (url == null) return null;
final uri = Uri.parse(url);
if ((uri.path.isEmpty || uri.path == '') && !url.endsWith('/')) return '$url/';
return url;
}
static String _locationTemplate() {
return '''{
"timestamp": "<%= timestamp %>",
"coords": {
"latitude": <%= latitude %>,
"longitude": <%= longitude %>,
"accuracy": <%= accuracy %>,
"speed": <%= speed %>,
"heading": <%= heading %>,
"altitude": <%= altitude %>
},
"is_moving": <%= is_moving %>,
"odometer": <%= odometer %>,
"event": "<%= event %>",
"battery": {
"level": <%= battery.level %>,
"is_charging": <%= battery.is_charging %>
},
"activity": {
"type": "<%= activity.type %>"
},
"extras": {},
"_": "&id=${instance.getString(id)}&lat=<%= latitude %>&lon=<%= longitude %>&timestamp=<%= timestamp %>&"
}'''.split('\n').map((line) => line.trimLeft()).join();
}
2025-05-10 09:51:51 -07:00
static Future<void> _migrate() async {
final oldId = instance.getString('device_id_preference');
2025-05-05 22:43:43 -07:00
if (oldId != null) {
2025-05-10 09:51:51 -07:00
instance.setString(id, oldId);
instance.remove('device_id_preference');
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
final oldUrl = instance.getString('server_url_preference');
2025-05-05 22:43:43 -07:00
if (oldUrl != null) {
2025-05-10 09:51:51 -07:00
instance.setString(url, oldUrl);
instance.remove('server_url_preference');
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
final oldAccuracy = instance.getString('accuracy_preference');
2025-05-05 22:43:43 -07:00
if (oldAccuracy != null) {
2025-05-10 09:51:51 -07:00
instance.setString(accuracy, oldAccuracy);
instance.remove('accuracy_preference');
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
final oldIntervalString = instance.getString('frequency_preference');
2025-05-05 22:43:43 -07:00
final oldInterval = oldIntervalString != null ? int.tryParse(oldIntervalString) : null;
if (oldInterval != null) {
2025-05-10 09:51:51 -07:00
instance.setInt(interval, oldInterval);
instance.remove('frequency_preference');
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
final oldDistanceString = instance.getString('distance_preference');
2025-05-05 22:43:43 -07:00
final oldDistance = oldDistanceString != null ? int.tryParse(oldDistanceString) : null;
if (oldDistance != null) {
2025-06-10 07:37:09 -07:00
instance.setInt(distance, oldDistance > 0 ? oldDistance : 75);
2025-05-10 09:51:51 -07:00
instance.remove('distance_preference');
2025-05-05 22:43:43 -07:00
}
2025-05-10 09:51:51 -07:00
final oldBuffer = instance.getBool('buffer_preference');
2025-05-05 22:43:43 -07:00
if (oldBuffer != null) {
2025-05-10 09:51:51 -07:00
instance.setBool(buffer, oldBuffer);
instance.remove('buffer_preference');
2025-05-05 22:43:43 -07:00
}
}
}