Compare commits

...
This repository has been archived on 2025-04-22. You can view files and clone it, but cannot push or open issues or pull requests.

1 Commits

Author SHA1 Message Date
Yegor Vialov
c844e21e76 WIP: Location tracking using foreground service 2020-05-12 22:18:41 +00:00
5 changed files with 132 additions and 9 deletions

View File

@ -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>

View File

@ -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) {

View File

@ -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;
});
}
}
*/

View File

@ -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;

View File

@ -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