From 8ba5641591b2c8f72884e9dea82e987b624058ec Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 30 Jun 2025 21:50:26 -0700 Subject: [PATCH] Implement push commands --- lib/main.dart | 2 ++ lib/push_service.dart | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 lib/push_service.dart diff --git a/lib/main.dart b/lib/main.dart index 3ed5290..b97a720 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/material.dart'; import 'package:rate_my_app/rate_my_app.dart'; import 'package:traccar_client/geolocation_service.dart'; +import 'package:traccar_client/push_service.dart'; import 'package:traccar_client/quick_actions.dart'; import 'l10n/app_localizations.dart'; @@ -16,6 +17,7 @@ void main() async { await Preferences.init(); await Preferences.migrate(); await GeolocationService.init(); + await PushService.init(); runApp(const MainApp()); } diff --git a/lib/push_service.dart b/lib/push_service.dart new file mode 100644 index 0000000..f27dfd6 --- /dev/null +++ b/lib/push_service.dart @@ -0,0 +1,53 @@ +import 'dart:developer' as developer; +import 'dart:io'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; + +import 'preferences.dart'; + +class PushService { + static Future init() async { + await FirebaseMessaging.instance.requestPermission(); + FirebaseMessaging.onBackgroundMessage(_backgroundHandler); + FirebaseMessaging.onMessage.listen(_onMessage); + FirebaseMessaging.instance.onTokenRefresh.listen(_uploadToken); + bg.BackgroundGeolocation.onEnabledChange((enabled) async { + if (enabled) { + _uploadToken(await FirebaseMessaging.instance.getToken()); + } + }); + } + + @pragma('vm:entry-point') + static Future _backgroundHandler(RemoteMessage message) async { + await Preferences.init(); + await _onMessage(message); + } + + static Future _onMessage(RemoteMessage message) async { + final command = message.data['command']; + if (command == 'positionSingle') { + try { + await bg.BackgroundGeolocation.getCurrentPosition(samples: 1, persist: true, extras: {'remote': true}); + } catch (error) { + developer.log('Failed to get position', error: error); + } + } + } + + static Future _uploadToken(String? token) async { + if (token == null) return; + final id = Preferences.instance.getString(Preferences.id); + final url = Preferences.instance.getString(Preferences.url); + if (id == null || url == null) return; + try { + final request = await HttpClient().postUrl(Uri.parse(url)); + request.headers.contentType = ContentType.parse('application/x-www-form-urlencoded'); + request.write('id=${Uri.encodeComponent(id)}¬ificationToken=${Uri.encodeComponent(token)}'); + await request.close(); + } catch (error) { + developer.log('Failed to upload token', error: error); + } + } +}