Asset profile Operations
This detailed example walks you through the following steps:
-
Creating a New Asset Based on User Input: Learn how to generate a new asset within your application, leveraging user input to create assets dynamically.
-
Binding User-Created Asset IDs to the Current Device: Discover the process of associating user-generated asset IDs with the device you're currently using, facilitating tracking and management of these assets.
-
Starting and Stopping Tracking Based on User Operations: Gain insights into how to initiate and halt tracking operations, giving users control over the tracking process.
-
Switching Between Tracking Modes Based on User Operations: Learn how to transition between different tracking modes, providing flexibility and adaptability to user preferences.
-
Receiving AssetTrackingCallbacks and Displaying Results in the User Interface: Explore how to handle AssetTrackingCallbacks and effectively communicate tracking results to the user interface, ensuring a seamless and informative user experience.
For all code examples, refer to iOS Tracking Android Code Examples
SetProfileViewController view source
1
2class SetProfileViewController: UIViewController, UIGestureRecognizerDelegate {
3 @IBOutlet weak var editCustomId: UITextField!
4 @IBOutlet weak var editAssetName: UITextField!
5 @IBOutlet weak var editAssetDescription: UITextField!
6 @IBOutlet weak var editAssetAttributes: UITextField!
7 @IBOutlet weak var lastAssetId: UITextField!
8 @IBOutlet weak var createAsset: UIButton!
9
10 @IBOutlet weak var editAssetId: UITextField!
11 @IBOutlet weak var bindAsset: UIButton!
12
13 var customId: String = ""
14 var assetName: String = ""
15 var assetDescription: String = ""
16 var assetAttributes: String = ""
17 var assetId: String = ""
18
19 let userDefaults: UserDefaults = UserDefaults.standard
20
21 override func viewDidLoad() {
22 super.viewDidLoad()
23 self.navigationController?.interactivePopGestureRecognizer?.delegate = self
24 self.hideKeyboardWhenTappedAround()
25 initData()
26 setUpInitialView()
27 addGestureEvents()
28 }
29
30 override func viewWillAppear(_ animated: Bool) {
31 self.navigationController?.setNavigationBarHidden(true, animated: true)
32 }
33
34 private func initData() {
35 customId = userDefaults.string(forKey: Constants.CUSTOM_ID_KEY) ?? UUID().uuidString.lowercased()
36 assetName = userDefaults.string(forKey: Constants.ASSET_NAME_KEY) ?? "my car"
37 assetDescription = userDefaults.string(forKey: Constants.ASSET_DESCRIPTION_KEY) ?? "a luxury BMW"
38 assetAttributes = userDefaults.string(forKey: Constants.ASSET_ATTRIBUTES_KEY) ?? "a test attribute"
39
40 assetId = userDefaults.string(forKey: Constants.ASSET_ID_KEY) ?? ""
41 }
42
43 private func setUpInitialView(){
44 editCustomId.delegate = self
45 editAssetName.delegate = self
46 editAssetDescription.delegate = self
47 editAssetAttributes.delegate = self
48 editAssetId.delegate = self
49
50 editCustomId.text = customId
51 editAssetName.text = assetName
52 editAssetDescription.text = assetDescription
53 editAssetAttributes.text = assetAttributes
54 editAssetId.text = assetId
55 lastAssetId.text = userDefaults.string(forKey: Constants.LAST_BIND_ASSET_ID_KEY) ?? ""
56
57 createAsset.setTitleColor(.white, for: .normal)
58 createAsset.layer.cornerRadius = 10
59 createAsset.layer.backgroundColor = UIColor.systemBlue.cgColor
60
61 bindAsset.setTitleColor(.systemBlue, for: .normal)
62 bindAsset.layer.cornerRadius = 10
63 bindAsset.layer.borderWidth = 1.0
64 bindAsset.layer.borderColor = UIColor.systemBlue.cgColor
65 }
66
67 private func addGestureEvents() {
68 createAsset.addTarget(self, action: #selector(onCreateAssetTapped), for: .touchUpInside)
69 bindAsset.addTarget(self, action: #selector(onBindAssetTapped), for: .touchUpInside)
70 }
71
72 func isLauncherScreen() -> Bool {
73 return self.navigationController?.viewControllers.count == 1
74 }
75
76 func lanchToHomeView() {
77 let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController")
78 self.view.window?.rootViewController = UINavigationController(rootViewController: viewController)
79 }
80
81 private func saveAssetProfile(assetId: String){
82 userDefaults.set(customId, forKey: Constants.CUSTOM_ID_KEY)
83 userDefaults.set(assetName, forKey: Constants.ASSET_NAME_KEY)
84 userDefaults.set(assetDescription, forKey: Constants.ASSET_DESCRIPTION_KEY)
85 userDefaults.set(assetAttributes, forKey: Constants.ASSET_ATTRIBUTES_KEY)
86 userDefaults.set(assetId, forKey: Constants.ASSET_ID_KEY)
87 }
88
89 @objc private func onCreateAssetTapped() {
90 if (assetName.isEmpty) {
91 let toastView = ToastView(message: "Please enter asset name")
92 toastView.show()
93 return
94 }
95
96 if(AssetTracking.shared.isRunning()){
97 let toastView = ToastView(message: "Asset tracking is ON, please turn off tracking before creating new asset!")
98 toastView.show()
99 return
100 }
101
102 let assetProfile: AssetProfile = AssetProfile.init(customId: customId, assetDescription: assetDescription, name: assetName, attributes: ["test": assetAttributes])
103
104 AssetTracking.shared.createAsset(assetProfile: assetProfile) { assetCreationResponse in
105 let assetId = assetCreationResponse.data.id
106 self.editAssetId.text = assetId
107 self.saveAssetProfile(assetId: assetId)
108 } errorHandler: { error in
109 let errorMessage = error.localizedDescription
110 let toastView = ToastView(message: "Create asset failed: " + errorMessage)
111 toastView.show()
112 }
113 }
114
115 private func showForceBindDialog(assetId: String, warningMessage: String) {
116 // Create an alert controller
117 let alertController = UIAlertController(title: "", message: warningMessage + ", do you want to clear local data and force bind to new asset id?", preferredStyle: .alert)
118
119 let okAction = UIAlertAction(title: "Proceed", style: .default) { (_) in
120 self.dismiss(animated: true, completion: nil)
121 AssetTracking.shared.forceBindAsset(assetId: assetId) { responseCode in
122 let toastView = ToastView(message: "Force bind new asset successfully with assetId: " + assetId)
123 toastView.show()
124
125 self.userDefaults.set(true, forKey: Constants.IS_NOT_FIRST_INSTALLATION_KEY)
126 self.userDefaults.set(assetId, forKey: Constants.LAST_BIND_ASSET_ID_KEY)
127
128 if self.isLauncherScreen() {
129 self.lanchToHomeView()
130 } else {
131 self.navigationController?.popViewController(animated: true)
132 }
133 } errorHandler: { error in
134 let errorMessage = error.localizedDescription
135 let toastView = ToastView(message: "Bind asset failed: " + errorMessage)
136 toastView.show()
137 }
138 }
139 alertController.addAction(okAction)
140
141 // Add "Cancel" button
142 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in
143 self.dismiss(animated: true, completion: nil)
144 }
145 alertController.addAction(cancelAction)
146
147 // Show the alert
148 present(alertController, animated: true, completion: nil)
149 }
150
151 @objc private func onBindAssetTapped() {
152 guard let assetId = editAssetId.text else {
153 let toastView = ToastView(message: "Please enter asset id")
154 toastView.show()
155 return
156 }
157
158 AssetTracking.shared.bindAsset(assetId: assetId) { responseCode in
159 let toastView = ToastView(message: "Bind asset successfully with id: " + assetId)
160 toastView.show()
161
162 self.userDefaults.set(true, forKey: Constants.IS_NOT_FIRST_INSTALLATION_KEY)
163 self.userDefaults.set(assetId, forKey: Constants.LAST_BIND_ASSET_ID_KEY)
164
165 if self.isLauncherScreen() {
166 self.lanchToHomeView()
167 } else {
168 self.navigationController?.popViewController(animated: true)
169 }
170 } errorHandler: { error in
171 let errorMessage = error.localizedDescription
172
173 if (errorMessage.contains(AssetTrackingApiExceptionType.UN_UPLOADED_LOCATION_DATA.rawValue)) {
174 self.showForceBindDialog(assetId: assetId, warningMessage: errorMessage)
175 } else {
176 let toastView = ToastView(message: "Bind asset failed: " + errorMessage)
177 toastView.show()
178 }
179 }
180
181 }
182
183}
184extension SetProfileViewController{
185 func hideKeyboardWhenTappedAround() {
186 let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
187 tap.cancelsTouchesInView = false
188 view.addGestureRecognizer(tap)
189 }
190
191 @objc private func dismissKeyboard() {
192 view.endEditing(true)
193 }
194
195}
196extension SetProfileViewController: UITextFieldDelegate {
197 public func textFieldDidChangeSelection(_ textField: UITextField) {
198 let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) ?? ""
199 if textField == self.editCustomId {
200 customId = text
201 } else if textField == self.editAssetName {
202 assetName = text
203 } else if textField == self.editAssetDescription {
204 assetDescription = text
205 } else if textField == self.editAssetAttributes {
206 assetAttributes = text
207 } else if textField == self.editAssetId {
208 assetId = text
209 }
210 }
211
212 func textFieldShouldReturn(_ textField: UITextField) -> Bool {
213 textField.resignFirstResponder()
214 return true
215 }
216}
ExtendedTrackingViewController view source
1class ExtendedTrackingViewController: UIViewController, AssetTrackingCallback {
2 @IBOutlet weak var locationInfo: UILabel!
3 @IBOutlet weak var trackingStatus: UILabel!
4 @IBOutlet weak var trackingModeSelector: UISegmentedControl!
5 @IBOutlet weak var startTracking: UIButton!
6 @IBOutlet weak var stopTracking: UIButton!
7 @IBOutlet weak var createAsset: UIButton!
8 @IBOutlet weak var viewDataLogs: UIButton!
9 var assetTracking: AssetTracking = AssetTracking.shared
10
11 override func viewDidLoad() {
12 super.viewDidLoad()
13 assetTracking.initialize(apiKey: "YOUR_API_KEY")
14
15 assetTracking.delegate = self
16
17 startTracking.setTitle("Start Tracking", for: .normal)
18 startTracking.setTitleColor(.white, for: .normal)
19 startTracking.layer.cornerRadius = 10
20 startTracking.layer.backgroundColor = UIColor.systemBlue.cgColor
21
22 stopTracking.setTitle("Stop Tracking", for: .normal)
23 stopTracking.setTitleColor(.white, for: .normal)
24 stopTracking.layer.cornerRadius = 10
25 stopTracking.layer.backgroundColor = UIColor.systemBlue.cgColor
26
27 bindExistingAssetId()
28 setUpButtons()
29 updateTrackingStatus()
30 }
31
32 override func viewWillAppear(_ animated: Bool) {
33 self.navigationController?.setNavigationBarHidden(true, animated: true)
34 }
35
36 private func bindExistingAssetId(){
37 let assetId = UserDefaults.standard.string(forKey: Constants.LAST_BIND_ASSET_ID_KEY) ?? ""
38
39 if(!assetId.isEmpty) {
40 AssetTracking.shared.bindAsset(assetId: assetId) { responseCode in
41 let toastView = ToastView(message: "Bind asset successfully with id: " + assetId)
42 toastView.show()
43 } errorHandler: { error in
44 let errorMessage = error.localizedDescription
45 let toastView = ToastView(message: "Bind asset failed: " + errorMessage)
46 toastView.show()
47 }
48 }
49 }
50
51 private func setUpButtons(){
52 createAsset.setTitleColor(.white, for: .normal)
53 createAsset.layer.cornerRadius = 10
54 createAsset.layer.backgroundColor = UIColor.systemBlue.cgColor
55
56 viewDataLogs.setTitleColor(.systemBlue, for: .normal)
57 viewDataLogs.layer.cornerRadius = 10
58 viewDataLogs.layer.borderWidth = 1.0
59 viewDataLogs.layer.borderColor = UIColor.systemBlue.cgColor
60
61 createAsset.addTarget(self, action: #selector(onCreateAssetTapped), for: .touchUpInside)
62
63 viewDataLogs.addTarget(self, action: #selector(onViewDataLogsTapped), for: .touchUpInside)
64 }
65
66 @objc private func onCreateAssetTapped() {
67 if assetTracking.isRunning() {
68 let toastView = ToastView(message: "please stop tracking before editing asset profile")
69 toastView.show()
70 return
71 }
72
73 let setProfileViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SetProfileViewController") as! SetProfileViewController
74 self.navigationController?.pushViewController(setProfileViewController, animated: true)
75 }
76
77 @objc private func onViewDataLogsTapped() {
78 let dataUploadLogVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DataUploadLogViewController") as! DataUploadLogViewController
79 self.navigationController?.pushViewController(dataUploadLogVC, animated: true)
80 }
81
82
83 @IBAction func startTracking(_ sender: Any) {
84 let assetId = assetTracking.getAssetId()
85
86 if (assetId.isEmpty){
87 let toastView = ToastView(message: "Please bind asset first before start tracking!")
88 toastView.show()
89 return
90 }
91
92 assetTracking.startTracking()
93 }
94
95 @IBAction func stopTracking(_ sender: Any) {
96 locationInfo.text = ""
97 assetTracking.stopTracking()
98 }
99
100
101 @IBAction func onTrackingModeChanged(_ sender: Any) {
102 var trackingMode: TrackingMode = TrackingMode.ACTIVE
103 switch trackingModeSelector.selectedSegmentIndex {
104 case 0:
105 trackingMode = .ACTIVE
106 case 1:
107 trackingMode = .BALANCED
108 case 2:
109 trackingMode = .PASSIVE
110 default:
111 break
112 }
113
114 let locationConfig = LocationConfig(trackingMode: trackingMode)
115 assetTracking.updateLocationConfig(config: locationConfig)
116 }
117
118 func onTrackingStart(assetId: String) {
119 updateTrackingStatus()
120 }
121
122 func onTrackingStop(assetId: String, trackingDisableType: TrackingDisableType) {
123 updateTrackingStatus()
124 }
125
126 func onLocationSuccess(location: CLLocation) {
127 locationInfo.text = """
128 --------- Location Info ---------
129 Latitude: \(location.coordinate.latitude)
130 Longitude: \(location.coordinate.longitude)
131 Altitude: \(location.altitude)
132 Accuracy: \(location.horizontalAccuracy)
133 Speed: \(location.speed)
134 Bearing: \(location.course)
135 Time: \(location.timestamp)
136 """
137 }
138
139 func showLocationAlert() {
140 let alert = UIAlertController(title: "Location Services Disabled", message: "To enable location services, please go to Settings > Privacy > Location Services.", preferredStyle: .alert)
141 alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
142
143 present(alert, animated: true, completion: nil)
144 }
145
146 func onLocationFailure(error: Error) {
147 }
148
149 func onLocationServiceOff() {
150 showLocationAlert()
151 }
152
153
154 func updateTrackingStatus() {
155 trackingStatus.text = "Tracking Status: \(assetTracking.isRunning() ? "ON" : "OFF")"
156 if !assetTracking.isRunning() {
157 locationInfo.text = ""
158 }
159 }
160
161}
Upon executing the code example provided above, your app's appearance will resemble the following snippet:
![]() | ![]() |
Asset Profile Page | Asset Tracking Page |
Code Highlights
The SetProfileViewController class inherits from the UIViewController class, which is the base class for all view controllers in iOS.
-
The class has several outlet properties: editCustomId, editAssetName, editAssetDescription, editAssetAttributes, lastAssetId, createAsset, and bindAsset. These properties are linked to the corresponding UI elements in the view controller's storyboard.
-
createAsset(): This method creates a new asset with the specified custom ID, asset name, description, and attributes. The method calls the AssetTracking.shared.createAsset() method to make the API request.
-
bindAsset(): This method binds the current view controller to the specified asset ID. The method calls the AssetTracking.shared.bindAsset() method to make the API request.
-
saveAssetProfile(): This method saves the asset profile to the user's device. The method updates the values of the customId, assetName, assetDescription, assetAttributes, and assetId properties, and then calls the userDefaults.set() method to save the values to the user's device.
-
onCreateAssetTapped(): This method is called when the user taps on the create asset button. The method checks if the asset name is empty, and if it is, it displays a toast message. Otherwise, it creates a new asset and saves the asset profile.
-
onBindAssetTapped(): This method is called when the user taps on the bind asset button. The method checks if the asset ID is empty, and if it is, it displays a toast message. Otherwise, it binds the current view controller to the asset and saves the asset profile.
-
dismissKeyboard(): This method dismisses the keyboard. The method calls the view.endEditing(true) method to dismiss the keyboard.
Here is a more detailed explanation of some of the key concepts in the code:
-
UITextFieldDelegate: This protocol is adopted by classes that want to receive notifications when a text field changes.
-
UIGestureRecognizerDelegate: This protocol is adopted by classes that want to receive notifications when a gesture recognizer is triggered.
-
AssetTrackingApiExceptionType: This enum defines the possible types of errors that can occur when calling the Asset Tracking API.
The ViewController class inherits from the UIViewController class, which is the base class for all view controllers in iOS.
-
The class has several outlet properties: locationInfo, trackingStatus, trackingModeSelector, startTracking, stopTracking, createAsset, and vie**wDataLogs. These properties are linked to the corresponding UI elements in the view controller's storyboard.
-
startTracking(): This method starts tracking the asset. The method calls the assetTracking.startTracking() method.
-
stopTracking(): This method stops tracking the asset. The method calls the assetTracking.stopTracking() method.
-
onTrackingStart(): This method is called when tracking starts. The method updates the trackingStatus label.
-
onTrackingStop(): This method is called when tracking stops. The method updates the trackingStatus label.
-
onLocationSuccess(): This method is called when a new location is received. The method updates the locationInfo label.
-
onLocationFailure(): This method is called when an error occurs while getting the location. The method does nothing in this case.
-
onLocationServiceOff(): This method is called when location services are turned off. The method displays an alert to the user.
Here is a more detailed explanation of some of the key concepts in the code:
-
AssetTracking: This class is responsible for tracking assets.
-
TrackingMode: This enum defines the three possible tracking modes: ACTIVE, BALANCED, and PASSIVE.
-
TrackingDisableType: This enum defines the possible reasons why tracking was stopped.
-
CLLocation: This class represents a location on Earth.
-
UIAlertController: This class is used to display alerts.