Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the app to be configured with an MDM #81

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ([[email protected]](mailto:[email protected]))

### Secondary contributors

- Axel Rieben

## License

Apache License, Version 2.0
Expand Down
19 changes: 16 additions & 3 deletions TraccarClient/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate

migrateLegacyDefaults()

registerManagedConfiguration()

let modelUrl = Bundle.main.url(forResource: "TraccarClient", withExtension: "momd")
managedObjectModel = NSManagedObjectModel(contentsOf: modelUrl!)

Expand All @@ -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()
}
Expand All @@ -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: ""))
Expand Down Expand Up @@ -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)
}
}
}
}
}
12 changes: 11 additions & 1 deletion TraccarClient/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class MainViewController: IASKAppSettingsViewController {
title = NSLocalizedString("Traccar Client", comment: "")
showCreditsFooter = false
neverShowPrivacySettings = true
hideManagedSettings()
}

override func viewDidAppear(_ animated: Bool) {
Expand Down Expand Up @@ -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()
}
Expand All @@ -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)
}
}
}
23 changes: 23 additions & 0 deletions TraccarClient/StatusViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 - "
Expand Down Expand Up @@ -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!
}
Expand Down