From b70e564b2dee2ec281cd06ccecc131c77e3e7e36 Mon Sep 17 00:00:00 2001 From: Axel Rieben <26045532+AxelRieben@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:10:05 +0100 Subject: [PATCH 1/2] Allow app to be configured with an iOS MDM solution --- TraccarClient/AppDelegate.swift | 19 ++++++++++++++++--- TraccarClient/MainViewController.swift | 12 +++++++++++- TraccarClient/StatusViewController.swift | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/TraccarClient/AppDelegate.swift b/TraccarClient/AppDelegate.swift index 732da69..c090d3b 100644 --- a/TraccarClient/AppDelegate.swift +++ b/TraccarClient/AppDelegate.swift @@ -51,6 +51,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate migrateLegacyDefaults() + registerManagedConfiguration() + let modelUrl = Bundle.main.url(forResource: "TraccarClient", withExtension: "momd") managedObjectModel = NSManagedObjectModel(contentsOf: modelUrl!) @@ -63,7 +65,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate managedObjectContext?.persistentStoreCoordinator = persistentStoreCoordinator if userDefaults.bool(forKey: "service_status_preference") { - StatusViewController.addMessage(NSLocalizedString("Service created", comment: "")) + StatusViewController.addStartMessage() trackingController = TrackingController() trackingController?.start() } @@ -79,7 +81,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate case "org.traccar.client.start": if !userDefaults.bool(forKey: "service_status_preference") { userDefaults.setValue(true, forKey: "service_status_preference") - StatusViewController.addMessage(NSLocalizedString("Service created", comment: "")) + StatusViewController.addStartMessage() trackingController = TrackingController() trackingController?.start() showToast(message: NSLocalizedString("Service created", comment: "")) @@ -172,5 +174,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate userDefaults.removeObject(forKey: "secure_preference") } } - + + // Override user preferences with configuration provided by an iOS MDM (Mobile Device Management) solution + func registerManagedConfiguration() { + if let managedConfiguration = UserDefaults.standard.object(forKey: "com.apple.configuration.managed") as? [String: Any?] { + for (key, value) in managedConfiguration { + // Status cannot be set via managed configuration + if value != nil && key != "service_status_preference" { + UserDefaults.standard.setValue(value, forKey: key) + } + } + } + } } diff --git a/TraccarClient/MainViewController.swift b/TraccarClient/MainViewController.swift index 19b59b4..9251e5f 100644 --- a/TraccarClient/MainViewController.swift +++ b/TraccarClient/MainViewController.swift @@ -26,6 +26,7 @@ class MainViewController: IASKAppSettingsViewController { title = NSLocalizedString("Traccar Client", comment: "") showCreditsFooter = false neverShowPrivacySettings = true + hideManagedSettings() } override func viewDidAppear(_ animated: Bool) { @@ -65,7 +66,7 @@ class MainViewController: IASKAppSettingsViewController { } else if frequency <= 0 { self.showError("Invalid frequency value") } else { - StatusViewController.addMessage(NSLocalizedString("Service created", comment: "")) + StatusViewController.addStartMessage() AppDelegate.instance.trackingController = TrackingController() AppDelegate.instance.trackingController?.start() } @@ -77,4 +78,13 @@ class MainViewController: IASKAppSettingsViewController { } } + // Settings that are configured through a MDM are hidden and cannot be changed by the user + func hideManagedSettings() { + if let managedConfiguration = UserDefaults.standard.object(forKey: "com.apple.configuration.managed") as? [String: Any?] { + let configWithoutNil = managedConfiguration.compactMapValues{ $0 } + // Status cannot be set via managed configuration and is always set by user + let keysWithoutStatus = configWithoutNil.keys.filter { $0 != "service_status_preference" } + setHiddenKeys(Set(keysWithoutStatus), animated: false) + } + } } diff --git a/TraccarClient/StatusViewController.swift b/TraccarClient/StatusViewController.swift index 95cdd89..d52fdc0 100644 --- a/TraccarClient/StatusViewController.swift +++ b/TraccarClient/StatusViewController.swift @@ -23,6 +23,26 @@ class StatusViewController: UITableViewController { static var messages = [String]() + class func addStartMessage() { + var message = NSLocalizedString("Service created", comment: "") + message += "\n\nDevice identifier: " + message += UserDefaults.standard.string(forKey: "device_id_preference") ?? "" + message += "\nServer URL: " + message += UserDefaults.standard.string(forKey: "server_url_preference") ?? "" + message += "\nLocation accuracy: " + message += UserDefaults.standard.string(forKey: "accuracy_preference") ?? "" + message += "\nFrequency: " + message += String(UserDefaults.standard.double(forKey: "frequency_preference")) + message += "\nDistance: " + message += String(UserDefaults.standard.double(forKey: "distance_preference")) + message += "\nAngle: " + message += String(UserDefaults.standard.double(forKey: "angle_preference")) + message += "\nOffline buffering: " + message += UserDefaults.standard.bool(forKey: "buffer_preference") ? "On" : "Off" + + addMessage(message) + } + class func addMessage(_ message: String) { let formatter = DateFormatter() formatter.dateFormat = "HH:mm - " @@ -74,6 +94,9 @@ class StatusViewController: UITableViewController { if cell == nil { cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier) } + tableView.rowHeight = UITableView.automaticDimension + tableView.estimatedRowHeight = 24 + cell?.textLabel?.numberOfLines = 0 cell?.textLabel?.text = StatusViewController.messages[indexPath.row] return cell! } From 6f9a82d2ad32ebed29e12a3719a57a1aef5b14a0 Mon Sep 17 00:00:00 2001 From: Axel Rieben <26045532+AxelRieben@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:12:05 +0100 Subject: [PATCH 2/2] Add doc for MDM configuration --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 0c30be4..956a021 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,32 @@ Project uses CocoaPods for dependencies management. To build the project you nee pod install ``` +## Configure app with an MDM (Mobile Device Management) + +When deploying the application with an MDM solution, the parameters can be overloaded with a managed configuration pushed to the phone. The following table shows the keys associated with the parameters. + +|Parameter name|Key|Type| +|---|---|---| +|Device identifier|device_id_preference|string| +|Server URL|server_url_preference|string| +|Location accuracy|accuracy_preference|string| +|Frequency|frequency_preference|integer| +|Distance|distance_preference|integer| +|Angle|angle_preference|integer| +|Offline buffering|buffer_preference|string| + +When a parameter is configured through MDM, it is hidden in UI and cannot be changed by the user. + ## Team +### Main contributors + - Anton Tananaev ([anton@traccar.org](mailto:anton@traccar.org)) +### Secondary contributors + +- Axel Rieben + ## License Apache License, Version 2.0