Initialize in main

This commit is contained in:
Anton Tananaev 2025-05-10 09:51:51 -07:00
parent c6375d0a7c
commit dd164e95ea
4 changed files with 56 additions and 73 deletions

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
import 'main_screen.dart'; import 'main_screen.dart';
import 'preferences.dart'; import 'preferences.dart';
@ -7,6 +8,7 @@ import 'preferences.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Preferences.init(); await Preferences.init();
await bg.BackgroundGeolocation.ready(Preferences.geolocationConfig());
runApp(const MainApp()); runApp(const MainApp());
} }

View file

@ -2,7 +2,6 @@ import 'dart:developer' as developer;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:traccar_client/preferences.dart'; import 'package:traccar_client/preferences.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
@ -17,8 +16,6 @@ class MainScreen extends StatefulWidget {
} }
class _MainScreenState extends State<MainScreen> { class _MainScreenState extends State<MainScreen> {
bool loading = true;
late SharedPreferences preferences;
bool trackingEnabled = false; bool trackingEnabled = false;
@override @override
@ -28,12 +25,8 @@ class _MainScreenState extends State<MainScreen> {
} }
void _initState() async { void _initState() async {
preferences = await SharedPreferences.getInstance(); final state = await bg.BackgroundGeolocation.state;
final state = await bg.BackgroundGeolocation.ready(
Preferences.geolocationConfig(preferences),
);
setState(() { setState(() {
loading = false;
trackingEnabled = state.enabled; trackingEnabled = state.enabled;
}); });
bg.BackgroundGeolocation.onEnabledChange((bool enabled) { bg.BackgroundGeolocation.onEnabledChange((bool enabled) {
@ -58,7 +51,7 @@ class _MainScreenState extends State<MainScreen> {
ListTile( ListTile(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
title: Text(AppLocalizations.of(context)!.idLabel), title: Text(AppLocalizations.of(context)!.idLabel),
trailing: Text(preferences.getString(Preferences.id) ?? ''), trailing: Text(Preferences.instance.getString(Preferences.id) ?? ''),
leadingAndTrailingTextStyle: Theme.of(context).textTheme.bodyLarge, leadingAndTrailingTextStyle: Theme.of(context).textTheme.bodyLarge,
), ),
SwitchListTile( SwitchListTile(
@ -117,7 +110,7 @@ class _MainScreenState extends State<MainScreen> {
ListTile( ListTile(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
title: Text(AppLocalizations.of(context)!.urlLabel), title: Text(AppLocalizations.of(context)!.urlLabel),
trailing: Text(preferences.getString(Preferences.url) ?? ''), trailing: Text(Preferences.instance.getString(Preferences.url) ?? ''),
leadingAndTrailingTextStyle: Theme.of(context).textTheme.bodyLarge, leadingAndTrailingTextStyle: Theme.of(context).textTheme.bodyLarge,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@ -140,10 +133,6 @@ class _MainScreenState extends State<MainScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (loading) {
return const Center(child: CircularProgressIndicator());
}
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(AppLocalizations.of(context)!.mainTitle), title: Text(AppLocalizations.of(context)!.mainTitle),

View file

@ -6,6 +6,7 @@ import 'package:flutter_background_geolocation/flutter_background_geolocation.da
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class Preferences { class Preferences {
static late SharedPreferences instance;
static const String id = 'id'; static const String id = 'id';
static const String url = 'url'; static const String url = 'url';
static const String accuracy = 'accuracy'; static const String accuracy = 'accuracy';
@ -14,80 +15,80 @@ class Preferences {
static const String buffer = 'buffer'; static const String buffer = 'buffer';
static Future<void> init() async { static Future<void> init() async {
SharedPreferences preferences = await SharedPreferences.getInstance(); instance = await SharedPreferences.getInstance();
if (Platform.isIOS) { if (Platform.isIOS) {
await _migrate(preferences); await _migrate();
} }
await preferences.setString(id, preferences.getString(id) ?? (Random().nextInt(90000000) + 10000000).toString()); await instance.setString(id, instance.getString(id) ?? (Random().nextInt(90000000) + 10000000).toString());
await preferences.setString(url, preferences.getString(url) ?? 'http://demo.traccar.org:5055'); await instance.setString(url, instance.getString(url) ?? 'http://demo.traccar.org:5055');
await preferences.setString(accuracy, preferences.getString(accuracy) ?? 'medium'); await instance.setString(accuracy, instance.getString(accuracy) ?? 'medium');
await preferences.setInt(interval, preferences.getInt(interval) ?? 300); await instance.setInt(interval, instance.getInt(interval) ?? 300);
final distanceValue = preferences.getInt(distance); final distanceValue = instance.getInt(distance);
if (distanceValue == null || distanceValue <= 0) { if (distanceValue == null || distanceValue <= 0) {
await preferences.setInt(distance, 75); await instance.setInt(distance, 75);
} }
await preferences.setBool(buffer, preferences.getBool(buffer) ?? true); await instance.setBool(buffer, instance.getBool(buffer) ?? true);
} }
static bg.Config geolocationConfig(SharedPreferences preferences) { static bg.Config geolocationConfig() {
return bg.Config( return bg.Config(
stopOnTerminate: false, stopOnTerminate: false,
startOnBoot: true, startOnBoot: true,
desiredAccuracy: switch (preferences.getString(accuracy)) { desiredAccuracy: switch (instance.getString(accuracy)) {
'high' => bg.Config.DESIRED_ACCURACY_HIGH, 'high' => bg.Config.DESIRED_ACCURACY_HIGH,
'low' => bg.Config.DESIRED_ACCURACY_LOW, 'low' => bg.Config.DESIRED_ACCURACY_LOW,
_ => bg.Config.DESIRED_ACCURACY_MEDIUM, _ => bg.Config.DESIRED_ACCURACY_MEDIUM,
}, },
url: preferences.getString(url), url: instance.getString(url),
params: { params: {
"device_id": preferences.getString(id), "device_id": instance.getString(id),
}, },
distanceFilter: preferences.getInt(distance)?.toDouble(), distanceFilter: instance.getInt(distance)?.toDouble(),
locationUpdateInterval: (preferences.getInt(interval) ?? 0) * 1000, locationUpdateInterval: (instance.getInt(interval) ?? 0) * 1000,
maxRecordsToPersist: preferences.getBool(buffer) != false ? -1 : 0, maxRecordsToPersist: instance.getBool(buffer) != false ? -1 : 0,
logLevel: bg.Config.LOG_LEVEL_INFO, logLevel: bg.Config.LOG_LEVEL_INFO,
logMaxDays: 1, logMaxDays: 1,
); );
} }
static Future<void> _migrate(SharedPreferences preferences) async { static Future<void> _migrate() async {
final oldId = preferences.getString('device_id_preference'); final oldId = instance.getString('device_id_preference');
if (oldId != null) { if (oldId != null) {
preferences.setString(id, oldId); instance.setString(id, oldId);
preferences.remove('device_id_preference'); instance.remove('device_id_preference');
} }
final oldUrl = preferences.getString('server_url_preference'); final oldUrl = instance.getString('server_url_preference');
if (oldUrl != null) { if (oldUrl != null) {
preferences.setString(url, oldUrl); instance.setString(url, oldUrl);
preferences.remove('server_url_preference'); instance.remove('server_url_preference');
} }
final oldAccuracy = preferences.getString('accuracy_preference'); final oldAccuracy = instance.getString('accuracy_preference');
if (oldAccuracy != null) { if (oldAccuracy != null) {
preferences.setString(accuracy, oldAccuracy); instance.setString(accuracy, oldAccuracy);
preferences.remove('accuracy_preference'); instance.remove('accuracy_preference');
} }
final oldIntervalString = preferences.getString('frequency_preference'); final oldIntervalString = instance.getString('frequency_preference');
final oldInterval = oldIntervalString != null ? int.tryParse(oldIntervalString) : null; final oldInterval = oldIntervalString != null ? int.tryParse(oldIntervalString) : null;
if (oldInterval != null) { if (oldInterval != null) {
preferences.setInt(interval, oldInterval); instance.setInt(interval, oldInterval);
preferences.remove('frequency_preference'); instance.remove('frequency_preference');
} }
final oldDistanceString = preferences.getString('distance_preference'); final oldDistanceString = instance.getString('distance_preference');
final oldDistance = oldDistanceString != null ? int.tryParse(oldDistanceString) : null; final oldDistance = oldDistanceString != null ? int.tryParse(oldDistanceString) : null;
if (oldDistance != null) { if (oldDistance != null) {
preferences.setInt(distance, oldDistance); instance.setInt(distance, oldDistance);
preferences.remove('distance_preference'); instance.remove('distance_preference');
} }
final oldAngleString = preferences.getString('angle_preference'); final oldAngleString = instance.getString('angle_preference');
final oldAngle = oldAngleString != null ? int.tryParse(oldAngleString) : null; final oldAngle = oldAngleString != null ? int.tryParse(oldAngleString) : null;
if (oldAngle != null) { if (oldAngle != null) {
preferences.setInt('angle', oldAngle); instance.setInt('angle', oldAngle);
preferences.remove('angle_preference'); instance.remove('angle_preference');
} }
final oldBuffer = preferences.getBool('buffer_preference'); final oldBuffer = instance.getBool('buffer_preference');
if (oldBuffer != null) { if (oldBuffer != null) {
preferences.setBool(buffer, oldBuffer); instance.setBool(buffer, oldBuffer);
preferences.remove('buffer_preference'); instance.remove('buffer_preference');
} }
} }
} }

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
@ -14,8 +13,6 @@ class SettingsScreen extends StatefulWidget {
} }
class _SettingsScreenState extends State<SettingsScreen> { class _SettingsScreenState extends State<SettingsScreen> {
bool loading = true;
late SharedPreferences preferences;
bool buffering = true; bool buffering = true;
@override @override
@ -25,10 +22,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
} }
void _initState() async { void _initState() async {
preferences = await SharedPreferences.getInstance();
setState(() { setState(() {
loading = false; buffering = Preferences.instance.getBool(Preferences.buffer) ?? true;
buffering = preferences.getBool(Preferences.buffer) ?? true;
}); });
} }
@ -42,8 +37,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
Future<void> _editSetting(String title, String key, bool isInt) async { Future<void> _editSetting(String title, String key, bool isInt) async {
final initialValue = isInt final initialValue = isInt
? preferences.getInt(key)?.toString() ?? '0' ? Preferences.instance.getInt(key)?.toString() ?? '0'
: preferences.getString(key) ?? ''; : Preferences.instance.getString(key) ?? '';
final controller = TextEditingController(text: initialValue); final controller = TextEditingController(text: initialValue);
@ -73,18 +68,18 @@ class _SettingsScreenState extends State<SettingsScreen> {
if (isInt) { if (isInt) {
final intValue = int.tryParse(result); final intValue = int.tryParse(result);
if (intValue != null) { if (intValue != null) {
await preferences.setInt(key, intValue); await Preferences.instance.setInt(key, intValue);
} }
} else { } else {
await preferences.setString(key, result); await Preferences.instance.setString(key, result);
} }
await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig(preferences)); await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig());
setState(() {}); setState(() {});
} }
} }
Widget _buildListTile(String title, String key, bool isInt) { Widget _buildListTile(String title, String key, bool isInt) {
final value = isInt ? preferences.getInt(key)?.toString() : preferences.getString(key); final value = isInt ? Preferences.instance.getInt(key)?.toString() : Preferences.instance.getString(key);
return ListTile( return ListTile(
title: Text(title), title: Text(title),
subtitle: Text(value ?? ''), subtitle: Text(value ?? ''),
@ -96,7 +91,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
final accuracyOptions = ['high', 'medium', 'low']; final accuracyOptions = ['high', 'medium', 'low'];
return ListTile( return ListTile(
title: Text(AppLocalizations.of(context)!.accuracyLabel), title: Text(AppLocalizations.of(context)!.accuracyLabel),
subtitle: Text(_getAccuracyLabel(preferences.getString(Preferences.accuracy))), subtitle: Text(_getAccuracyLabel(Preferences.instance.getString(Preferences.accuracy))),
onTap: () async { onTap: () async {
final selectedAccuracy = await showDialog<String>( final selectedAccuracy = await showDialog<String>(
context: context, context: context,
@ -109,8 +104,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
), ),
); );
if (selectedAccuracy != null) { if (selectedAccuracy != null) {
await preferences.setString(Preferences.accuracy, selectedAccuracy); await Preferences.instance.setString(Preferences.accuracy, selectedAccuracy);
await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig(preferences)); await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig());
setState(() {}); setState(() {});
} }
}, },
@ -119,10 +114,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (loading) {
return const Center(child: CircularProgressIndicator());
}
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(AppLocalizations.of(context)!.settingsTitle)), appBar: AppBar(title: Text(AppLocalizations.of(context)!.settingsTitle)),
body: ListView( body: ListView(
@ -136,8 +127,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
title: Text(AppLocalizations.of(context)!.bufferLabel), title: Text(AppLocalizations.of(context)!.bufferLabel),
value: buffering, value: buffering,
onChanged: (value) async { onChanged: (value) async {
await preferences.setBool(Preferences.buffer, value); await Preferences.instance.setBool(Preferences.buffer, value);
await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig(preferences)); await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig());
setState(() => buffering = value); setState(() => buffering = value);
}, },
), ),