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: