WIP: Location tracking using foreground service
This commit is contained in:
parent
24d42c9597
commit
c844e21e76
@ -5,8 +5,13 @@
|
||||
android:required="false" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<!--
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
-->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
|
||||
|
||||
@ -53,6 +58,17 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name="rekab.app.background_locator.LocatorBroadcastReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true"/>
|
||||
<service android:name="rekab.app.background_locator.LocatorService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="true"/>
|
||||
<service android:name="rekab.app.background_locator.IsolateHolderService"
|
||||
android:permission="android.permission.FOREGROUND_SERVICE"
|
||||
android:exported="true"/>
|
||||
|
||||
<!--
|
||||
<service
|
||||
android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
@ -67,5 +83,6 @@
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
-->
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'dart:isolate';
|
||||
import 'dart:ui';
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
@ -23,8 +25,11 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:in_app_purchase/in_app_purchase.dart';
|
||||
import 'plugins/dynamic_multi_column_layout.dart';
|
||||
import 'plugins/spoiler_card.dart';
|
||||
import 'package:workmanager/workmanager.dart' as workManager;
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
//import 'package:workmanager/workmanager.dart' as workManager;
|
||||
//import 'package:geolocator/geolocator.dart';
|
||||
import 'package:background_locator/background_locator.dart';
|
||||
import 'package:background_locator/location_dto.dart';
|
||||
import 'package:background_locator/location_settings.dart';
|
||||
import 'package:battery/battery.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart' as standaloneWebview;
|
||||
@ -213,9 +218,12 @@ class _HAClientAppState extends State<HAClientApp> {
|
||||
StreamSubscription<List<PurchaseDetails>> _purchaseUpdateSubscription;
|
||||
StreamSubscription _themeChangeSubscription;
|
||||
AppTheme _currentTheme = AppTheme.defaultTheme;
|
||||
|
||||
ReceivePort port = ReceivePort();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
||||
InAppPurchaseConnection.enablePendingPurchases();
|
||||
final Stream purchaseUpdates =
|
||||
InAppPurchaseConnection.instance.purchaseUpdatedStream;
|
||||
@ -228,11 +236,18 @@ class _HAClientAppState extends State<HAClientApp> {
|
||||
_currentTheme = event.theme;
|
||||
});
|
||||
});
|
||||
/*
|
||||
workManager.Workmanager.initialize(
|
||||
updateDeviceLocationIsolate,
|
||||
isInDebugMode: false
|
||||
);
|
||||
*/
|
||||
super.initState();
|
||||
IsolateNameServer.registerPortWithName(port.sendPort, LocationManager.isolateName);
|
||||
port.listen((dynamic data) {
|
||||
// do something with data
|
||||
});
|
||||
initPlatformState();
|
||||
}
|
||||
|
||||
void _handlePurchaseUpdates(purchase) {
|
||||
@ -253,6 +268,10 @@ class _HAClientAppState extends State<HAClientApp> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initPlatformState() async {
|
||||
await BackgroundLocator.initialize();
|
||||
}
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -26,7 +26,7 @@ class LocationManager {
|
||||
defaultUpdateIntervalMinutes);
|
||||
_isRunning = prefs.getBool("location-enabled") ?? false;
|
||||
if (_isRunning) {
|
||||
await _startLocationService();
|
||||
//await _startLocationService();
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,20 @@ class LocationManager {
|
||||
}
|
||||
|
||||
_startLocationService() async {
|
||||
Logger.d('Starting location tracking');
|
||||
BackgroundLocator.registerLocationUpdate(
|
||||
locationCallback,
|
||||
//optional
|
||||
androidNotificationCallback: locationNotificationCallback,
|
||||
settings: LocationSettings(
|
||||
notificationTitle: "HA Client location tracking",
|
||||
notificationMsg: "HA Client is updating your device location",
|
||||
wakeLockTime: 20,
|
||||
autoStop: false,
|
||||
interval: 10
|
||||
),
|
||||
);
|
||||
/*
|
||||
String webhookId = ConnectionManager().webhookId;
|
||||
String httpWebHost = ConnectionManager().httpWebHost;
|
||||
if (webhookId != null && webhookId.isNotEmpty) {
|
||||
@ -100,14 +114,81 @@ class LocationManager {
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
_stopLocationService() async {
|
||||
Logger.d("Canceling previous schedule if any...");
|
||||
await workManager.Workmanager.cancelAll();
|
||||
Logger.d('Stopping location tracking');
|
||||
IsolateNameServer.removePortNameMapping(isolateName);
|
||||
BackgroundLocator.unRegisterLocationUpdate();
|
||||
/*Logger.d("Canceling previous schedule if any...");
|
||||
await workManager.Workmanager.cancelAll();*/
|
||||
}
|
||||
|
||||
static const String isolateName = "HAClientLocatorIsolate";
|
||||
|
||||
static void locationCallback(LocationDto locationDto) async {
|
||||
print('[Background location] Got location: $locationDto');
|
||||
sendLocationData(locationDto);
|
||||
final SendPort send = IsolateNameServer.lookupPortByName(isolateName);
|
||||
send?.send(locationDto);
|
||||
}
|
||||
|
||||
static Future<void> sendLocationData(LocationDto location) async {
|
||||
print('[Background location] Loading settings...');
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String domain = prefs.getString('hassio-domain');
|
||||
String port = prefs.getString('hassio-port');
|
||||
String webhookId = prefs.getString('app-webhook-id');
|
||||
String httpWebHost =
|
||||
"${prefs.getString('hassio-res-protocol')}://$domain:$port";
|
||||
if (webhookId != null && webhookId.isNotEmpty) {
|
||||
String url = "$httpWebHost/api/webhook/$webhookId";
|
||||
Map<String, String> headers = {};
|
||||
headers["Content-Type"] = "application/json";
|
||||
Map data = {
|
||||
"type": "update_location",
|
||||
"data": {
|
||||
"gps": [],
|
||||
"gps_accuracy": 0,
|
||||
"battery": 100
|
||||
}
|
||||
};
|
||||
try {
|
||||
if (location.longitude != null && location.latitude != null) {
|
||||
data["data"]["gps"] = [location.latitude, location.longitude];
|
||||
data["data"]["gps_accuracy"] = location.accuracy;
|
||||
print('[Background location] Sending...');
|
||||
try {
|
||||
http.Response response = await http.post(
|
||||
url,
|
||||
headers: headers,
|
||||
body: json.encode(data)
|
||||
);
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
print('[Background location] Success!');
|
||||
} else {
|
||||
print('[Background location] Error sending data: ${response.statusCode}');
|
||||
}
|
||||
} catch(e) {
|
||||
print('[Background location] Error sending data: $e');
|
||||
}
|
||||
} else {
|
||||
print('[Background location] Error. Location is null');
|
||||
}
|
||||
} catch (e) {
|
||||
print('[Background location] Error: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void locationNotificationCallback() {
|
||||
print('[Background location] User clicked on the notification');
|
||||
}
|
||||
|
||||
updateDeviceLocation() async {
|
||||
/*
|
||||
try {
|
||||
Logger.d("[Foreground location] Started");
|
||||
Geolocator geolocator = Geolocator();
|
||||
@ -150,10 +231,12 @@ class LocationManager {
|
||||
} catch (e, stack) {
|
||||
Logger.e('Foreground location error: ${e.toSTring()}', stacktrace: stack);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void updateDeviceLocationIsolate() {
|
||||
workManager.Workmanager.executeTask((backgroundTask, data) async {
|
||||
//print("[Background $backgroundTask] Started");
|
||||
@ -241,4 +324,5 @@ void updateDeviceLocationIsolate() {
|
||||
print("[Background $backgroundTask] Finished.");*/
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
*/
|
@ -53,9 +53,11 @@ class _IntegrationSettingsPageState extends State<IntegrationSettingsPage> {
|
||||
}
|
||||
|
||||
_switchLocationTrackingState(bool state) async {
|
||||
/*
|
||||
if (state) {
|
||||
await LocationManager().updateDeviceLocation();
|
||||
}
|
||||
*/
|
||||
await LocationManager().setSettings(_locationTrackingEnabled, _locationInterval);
|
||||
setState(() {
|
||||
_wait = false;
|
||||
|
@ -27,8 +27,9 @@ dependencies:
|
||||
flutter_secure_storage: ^3.3.3
|
||||
device_info: ^0.4.1+4
|
||||
flutter_local_notifications: ^1.1.6
|
||||
geolocator: ^5.3.1
|
||||
workmanager: ^0.2.2
|
||||
#geolocator: ^5.3.1
|
||||
background_locator: ^1.1.3+1
|
||||
#workmanager: ^0.2.2
|
||||
battery: ^1.0.0
|
||||
firebase_crashlytics: ^0.1.3+3
|
||||
syncfusion_flutter_core: ^18.1.48
|
||||
|
Reference in New Issue
Block a user