diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b581645..4c7c617 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -29,6 +29,12 @@ + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 5ab925d..b380c2d 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -28,6 +28,15 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + CFBundleURLTypes + + + CFBundleURLSchemes + + org.traccar.client + + + LSRequiresIPhoneOS NSAppTransportSecurity diff --git a/lib/configuration_service.dart b/lib/configuration_service.dart new file mode 100644 index 0000000..a3c34ea --- /dev/null +++ b/lib/configuration_service.dart @@ -0,0 +1,63 @@ +import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; + +import 'preferences.dart'; + +class ConfigurationService { + static Future applyUri(Uri uri) async { + if (uri.scheme == 'http' || uri.scheme == 'https') { + await Preferences.instance.setString(Preferences.url, '${uri.origin}${uri.path}'); + } else { + final url = uri.queryParameters['url']; + if (url != null) { + await Preferences.instance.setString(Preferences.url, url); + } + } + final parameters = uri.queryParameters; + await _applyStringParameter(parameters, Preferences.id); + await _applyStringParameter(parameters, Preferences.accuracy); + await _applyIntParameter(parameters, Preferences.distance); + await _applyIntParameter(parameters, Preferences.interval); + await _applyIntParameter(parameters, Preferences.angle); + await _applyIntParameter(parameters, Preferences.heartbeat); + await _applyIntParameter(parameters, Preferences.fastestInterval); + await _applyBoolParameter(parameters, Preferences.buffer); + await _applyBoolParameter(parameters, Preferences.wakelock); + await _applyBoolParameter(parameters, Preferences.stopDetection); + await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig()); + } + + static Future _applyStringParameter( + Map parameters, String key) async { + final value = parameters[key]; + if (value != null) { + await Preferences.instance.setString(key, value); + } + } + + static Future _applyIntParameter( + Map parameters, String key) async { + final stringValue = parameters[key]; + if (stringValue != null) { + final value = int.tryParse(stringValue); + if (value != null) { + await Preferences.instance.setInt(key, value); + } + } + } + + static Future _applyBoolParameter( + Map parameters, String key) async { + final value = parameters[key]; + if (value != null) { + switch (value) { + case 'false': + await Preferences.instance.setBool(key, false); + break; + case 'true': + await Preferences.instance.setBool(key, true); + break; + } + } + } +} + diff --git a/lib/main.dart b/lib/main.dart index 9984ed2..80d8c50 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,10 @@ +import 'dart:async'; import 'dart:developer' as developer; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/material.dart'; +import 'package:app_links/app_links.dart'; import 'package:rate_my_app/rate_my_app.dart'; import 'package:traccar_client/geolocation_service.dart'; import 'package:traccar_client/push_service.dart'; @@ -11,6 +13,7 @@ import 'package:traccar_client/quick_actions.dart'; import 'l10n/app_localizations.dart'; import 'main_screen.dart'; import 'preferences.dart'; +import 'configuration_service.dart'; final messengerKey = GlobalKey(); @@ -38,6 +41,7 @@ class _MainAppState extends State { @override void initState() { super.initState(); + _initLinks(); WidgetsBinding.instance.addPostFrameCallback((_) async { await rateMyApp.init(); if (mounted && rateMyApp.shouldOpenDialog) { @@ -50,6 +54,17 @@ class _MainAppState extends State { }); } + Future _initLinks() async { + final appLinks = AppLinks(); + final uri = await appLinks.getInitialLink(); + if (uri != null) { + await ConfigurationService.applyUri(uri); + } + appLinks.uriLinkStream.listen((uri) async { + await ConfigurationService.applyUri(uri); + }); + } + @override Widget build(BuildContext context) { return MaterialApp( diff --git a/lib/qr_code_screen.dart b/lib/qr_code_screen.dart index 9ddf2ee..e78131d 100644 --- a/lib/qr_code_screen.dart +++ b/lib/qr_code_screen.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; -import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; -import 'preferences.dart'; +import 'configuration_service.dart'; import 'l10n/app_localizations.dart'; class QrCodeScreen extends StatefulWidget { @@ -15,53 +14,6 @@ class QrCodeScreen extends StatefulWidget { class _QrCodeScreenState extends State { bool _scanned = false; - Future _applySettings(Uri uri) async { - await Preferences.instance.setString(Preferences.url, '${uri.origin}${uri.path}'); - final parameters = uri.queryParameters; - await _applyStringParameter(parameters, Preferences.id); - await _applyStringParameter(parameters, Preferences.accuracy); - await _applyIntParameter(parameters, Preferences.distance); - await _applyIntParameter(parameters, Preferences.interval); - await _applyIntParameter(parameters, Preferences.angle); - await _applyIntParameter(parameters, Preferences.heartbeat); - await _applyIntParameter(parameters, Preferences.fastestInterval); - await _applyBoolParameter(parameters, Preferences.buffer); - await _applyBoolParameter(parameters, Preferences.wakelock); - await _applyBoolParameter(parameters, Preferences.stopDetection); - await bg.BackgroundGeolocation.setConfig(Preferences.geolocationConfig()); - } - - Future _applyStringParameter(Map parameters, String key) async { - final value = parameters[key]; - if (value != null) { - await Preferences.instance.setString(key, value); - } - } - - Future _applyIntParameter(Map parameters, String key) async { - final stringValue = parameters[key]; - if (stringValue != null) { - final value = int.tryParse(stringValue); - if (value != null) { - await Preferences.instance.setInt(key, value); - } - } - } - - Future _applyBoolParameter(Map parameters, String key) async { - final value = parameters[key]; - if (value != null) { - switch (value) { - case 'false': - await Preferences.instance.setBool(key, false); - break; - case 'true': - await Preferences.instance.setBool(key, true); - break; - } - } - } - void _onDetect(BarcodeCapture capture) async { if (_scanned) return; final barcode = capture.barcodes.first; @@ -70,7 +22,7 @@ class _QrCodeScreenState extends State { final uri = Uri.tryParse(rawValue); if (uri == null || uri.scheme.isEmpty) return; _scanned = true; - await _applySettings(uri); + await ConfigurationService.applyUri(uri); if (mounted) Navigator.pop(context); } diff --git a/pubspec.lock b/pubspec.lock index 511e01e..29e6aa7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.60" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8" + url: "https://pub.dev" + source: hosted + version: "6.4.1" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" async: dependency: transitive description: @@ -261,6 +293,14 @@ packages: description: flutter source: sdk version: "0.0.0" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" intl: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index a856354..74ebca7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,6 +24,7 @@ dependencies: wakelock_partial_android: ^1.0.1 mobile_scanner: ^7.0.1 flutter_secure_storage: ^9.2.4 + app_links: ^6.4.1 dev_dependencies: flutter_test: