Add wake lock and optimization
This commit is contained in:
parent
e0f2bde919
commit
4ac4f1f892
8 changed files with 108 additions and 18 deletions
56
lib/geolocation_service.dart
Normal file
56
lib/geolocation_service.dart
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
|
||||
import 'package:traccar_client/preferences.dart';
|
||||
import 'package:wakelock_partial_android/wakelock_partial_android.dart';
|
||||
|
||||
class GeolocationService {
|
||||
static Future<void> init() async {
|
||||
await bg.BackgroundGeolocation.ready(Preferences.geolocationConfig());
|
||||
if (Platform.isAndroid) {
|
||||
await bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
|
||||
}
|
||||
bg.BackgroundGeolocation.onEnabledChange(onEnabledChange);
|
||||
bg.BackgroundGeolocation.onMotionChange(onMotionChange);
|
||||
bg.BackgroundGeolocation.onHeartbeat(onHeartbeat);
|
||||
}
|
||||
|
||||
static Future<void> onEnabledChange(bool enabled) async {
|
||||
if (Preferences.instance.getBool(Preferences.wakelock) ?? false) {
|
||||
if (!enabled) {
|
||||
await WakelockPartialAndroid.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> onMotionChange(bg.Location location) async {
|
||||
if (Preferences.instance.getBool(Preferences.wakelock) ?? false) {
|
||||
if (location.isMoving) {
|
||||
await WakelockPartialAndroid.acquire();
|
||||
} else {
|
||||
await WakelockPartialAndroid.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> onHeartbeat(bg.HeartbeatEvent event) async {
|
||||
await bg.BackgroundGeolocation.getCurrentPosition(samples: 1, persist: true);
|
||||
}
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void headlessTask(bg.HeadlessEvent headlessEvent) async {
|
||||
await Preferences.init();
|
||||
switch (headlessEvent.name) {
|
||||
case bg.Event.ENABLEDCHANGE:
|
||||
await GeolocationService.onEnabledChange(headlessEvent.event);
|
||||
break;
|
||||
case bg.Event.MOTIONCHANGE:
|
||||
await GeolocationService.onMotionChange(headlessEvent.event);
|
||||
break;
|
||||
case bg.Event.HEARTBEAT:
|
||||
await GeolocationService.onHeartbeat(headlessEvent.event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
"statusTitle": "Logs",
|
||||
"saveButton": "Save",
|
||||
"cancelButton": "Cancel",
|
||||
"okButton": "OK",
|
||||
"locationButton": "Send location",
|
||||
"statusButton": "Show status",
|
||||
"settingsButton": "Change settings",
|
||||
|
|
@ -25,6 +26,7 @@
|
|||
"trackingLabel": "Continuous tracking",
|
||||
"motionLabel": "Active movement",
|
||||
"advancedLabel": "Advanced settings",
|
||||
"optimizationMessage": "To ensure reliable tracking, please disable battery optimization for this app.",
|
||||
"startAction": "Start service",
|
||||
"stopAction": "Stop service",
|
||||
"sosAction": "Send SOS"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
|
||||
import 'package:rate_my_app/rate_my_app.dart';
|
||||
import 'package:traccar_client/geolocation_service.dart';
|
||||
import 'package:traccar_client/quick_actions.dart';
|
||||
|
||||
import 'l10n/app_localizations.dart';
|
||||
|
|
@ -16,23 +14,11 @@ void main() async {
|
|||
await Firebase.initializeApp();
|
||||
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
|
||||
await Preferences.init();
|
||||
await bg.BackgroundGeolocation.ready(Preferences.geolocationConfig());
|
||||
if (Platform.isAndroid) {
|
||||
await bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
|
||||
}
|
||||
bg.BackgroundGeolocation.onHeartbeat((bg.HeartbeatEvent event) async {
|
||||
await bg.BackgroundGeolocation.getCurrentPosition(samples: 1, persist: true);
|
||||
});
|
||||
await Preferences.migrate();
|
||||
await GeolocationService.init();
|
||||
runApp(const MainApp());
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void headlessTask(bg.HeadlessEvent headlessEvent) async {
|
||||
if (headlessEvent.name == bg.Event.HEARTBEAT) {
|
||||
await bg.BackgroundGeolocation.getCurrentPosition(samples: 1, persist: true);
|
||||
}
|
||||
}
|
||||
|
||||
class MainApp extends StatefulWidget {
|
||||
const MainApp({super.key});
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,30 @@ class _MainScreenState extends State<MainScreen> {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> _checkBatteryOptimizations(BuildContext context) async {
|
||||
try {
|
||||
if (!await bg.DeviceSettings.isIgnoringBatteryOptimizations) {
|
||||
final request = await bg.DeviceSettings.showIgnoreBatteryOptimizations();
|
||||
if (!request.seen && context.mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
content: Text(AppLocalizations.of(context)!.optimizationMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => bg.DeviceSettings.show(request),
|
||||
child: Text(AppLocalizations.of(context)!.okButton),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint(error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTrackingCard() {
|
||||
return Card(
|
||||
child: Padding(
|
||||
|
|
@ -69,6 +93,7 @@ class _MainScreenState extends State<MainScreen> {
|
|||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
bg.BackgroundGeolocation.start();
|
||||
_checkBatteryOptimizations(context);
|
||||
} else {
|
||||
bg.BackgroundGeolocation.stop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ class Preferences {
|
|||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> migrate() async {
|
||||
if (Platform.isAndroid) {
|
||||
if (instance.get(interval) is String) {
|
||||
final stringValue = instance.getString(interval);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
|
||||
import 'package:wakelock_partial_android/wakelock_partial_android.dart';
|
||||
|
||||
import 'l10n/app_localizations.dart';
|
||||
import 'preferences.dart';
|
||||
|
|
@ -179,6 +180,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
value: wakelock,
|
||||
onChanged: (value) async {
|
||||
await Preferences.instance.setBool(Preferences.wakelock, value);
|
||||
if (value) {
|
||||
final state = await bg.BackgroundGeolocation.state;
|
||||
if (state.isMoving == true) {
|
||||
WakelockPartialAndroid.acquire();
|
||||
}
|
||||
} else {
|
||||
WakelockPartialAndroid.release();
|
||||
}
|
||||
setState(() => wakelock = value);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue