Asset Tracking Extended

SDK, users can do asset creation and binding, switch between different tracking modes, and receive callbacks for the data tracking.

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 initiating and halting 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 Asset Tracking Android Code Examples

activity_set_profile.xml view source

1<?xml version="1.0" encoding="utf-8"?>
2<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 tools:context=".SetProfileActivity">
7
8 <ScrollView
9 android:layout_width="match_parent"
10 android:layout_height="wrap_content">
11
12 <LinearLayout
13 android:layout_width="match_parent"
14 android:layout_height="wrap_content"
15 android:orientation="vertical"
16 android:paddingStart="20dp"
17 android:paddingEnd="20dp"
18 android:paddingBottom="20dp">
19
20 <TextView
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_marginTop="50dp"
24 android:text="@string/custom_id"
25 android:textColor="@color/text_color_primary"
26 android:textSize="15sp"
27 android:textStyle="bold" />
28
29 <EditText
30 android:id="@+id/edit_custom_id"
31 android:layout_width="match_parent"
32 android:layout_height="40dp"
33 android:layout_marginTop="6dp"
34 android:height="40dp"
35 android:background="@drawable/selector_edit_text_bg"
36 android:hint="@string/enter_custom_id"
37 android:inputType="text"
38 android:lines="1"
39 android:paddingStart="10dp"
40 android:paddingEnd="10dp"
41 android:textAlignment="viewStart"
42 android:textColor="@color/text_color_primary"
43 android:textColorHint="@color/md_grey_400"
44 android:textCursorDrawable="@drawable/shape_cursor_color"
45 android:textSize="15sp"
46 tools:ignore="Autofill" />
47
48
49 <TextView
50 android:layout_width="wrap_content"
51 android:layout_height="wrap_content"
52 android:layout_marginTop="40dp"
53 android:text="@string/asset_name"
54 android:textColor="@color/text_color_primary"
55 android:textSize="15sp"
56 android:textStyle="bold" />
57
58 <EditText
59 android:id="@+id/edit_asset_name"
60 android:layout_width="match_parent"
61 android:layout_height="40dp"
62 android:layout_marginTop="6dp"
63 android:background="@drawable/selector_edit_text_bg"
64 android:hint="@string/enter_asset_name"
65 android:inputType="text"
66 android:lines="1"
67 android:paddingStart="10dp"
68 android:paddingEnd="10dp"
69 android:textAlignment="viewStart"
70 android:textColor="@color/text_color_primary"
71 android:textColorHint="@color/md_grey_400"
72 android:textCursorDrawable="@drawable/shape_cursor_color"
73 android:textSize="15sp"
74 tools:ignore="Autofill,TextFields" />
75
76 <TextView
77 android:layout_width="wrap_content"
78 android:layout_height="wrap_content"
79 android:layout_marginTop="40dp"
80 android:text="@string/asset_description"
81 android:textColor="@color/text_color_primary"
82 android:textSize="15sp"
83 android:textStyle="bold" />
84
85 <EditText
86 android:id="@+id/edit_asset_description"
87 android:layout_width="match_parent"
88 android:layout_height="40dp"
89 android:layout_marginTop="6dp"
90 android:background="@drawable/selector_edit_text_bg"
91 android:hint="@string/enter_asset_description"
92 android:inputType="text"
93 android:lines="1"
94 android:paddingStart="10dp"
95 android:paddingEnd="10dp"
96 android:textAlignment="viewStart"
97 android:textColor="@color/text_color_primary"
98 android:textColorHint="@color/md_grey_400"
99 android:textCursorDrawable="@drawable/shape_cursor_color"
100 android:textSize="15sp"
101 tools:ignore="Autofill,TextFields" />
102
103 <TextView
104 android:layout_width="wrap_content"
105 android:layout_height="wrap_content"
106 android:layout_marginTop="40dp"
107 android:text="@string/asset_attributes"
108 android:textColor="@color/text_color_primary"
109 android:textSize="15sp"
110 android:textStyle="bold" />
111
112 <EditText
113 android:id="@+id/edit_asset_attributes"
114 android:layout_width="match_parent"
115 android:layout_height="40dp"
116 android:layout_marginTop="6dp"
117 android:background="@drawable/selector_edit_text_bg"
118 android:hint="@string/enter_asset_attributes"
119 android:inputType="text"
120 android:lines="1"
121 android:paddingStart="10dp"
122 android:paddingEnd="10dp"
123 android:textAlignment="viewStart"
124 android:textColor="@color/text_color_primary"
125 android:textColorHint="@color/md_grey_400"
126 android:textCursorDrawable="@drawable/shape_cursor_color"
127 android:textSize="15sp"
128 tools:ignore="Autofill,TextFields" />
129
130 <TextView
131 android:id="@+id/create_new_asset"
132 android:layout_width="match_parent"
133 android:layout_height="wrap_content"
134 android:layout_gravity="bottom|center_horizontal"
135 android:layout_marginTop="50dp"
136 android:background="@drawable/route_nav_bg"
137 android:gravity="center"
138 android:paddingTop="15dp"
139 android:paddingBottom="15dp"
140 android:text="@string/create_asset"
141 android:textColor="@color/white"
142 android:textSize="15sp"
143 android:textStyle="bold" />
144
145 <TextView
146 android:layout_width="wrap_content"
147 android:layout_height="wrap_content"
148 android:layout_marginTop="40dp"
149 android:text="@string/asset_id"
150 android:textColor="@color/text_color_primary"
151 android:textSize="15sp"
152 android:textStyle="bold" />
153
154 <EditText
155 android:id="@+id/edit_asset_id"
156 android:layout_width="match_parent"
157 android:layout_height="40dp"
158 android:layout_marginTop="6dp"
159 android:background="@drawable/selector_edit_text_bg"
160 android:hint="@string/enter_asset_id"
161 android:inputType="text"
162 android:lines="1"
163 android:paddingStart="10dp"
164 android:paddingEnd="10dp"
165 android:textAlignment="viewStart"
166 android:textColor="@color/text_color_primary"
167 android:textColorHint="@color/md_grey_400"
168 android:textCursorDrawable="@drawable/shape_cursor_color"
169 android:textSize="15sp"
170 tools:ignore="Autofill,TextFields" />
171
172 <TextView
173 android:id="@+id/bind_asset"
174 android:layout_width="match_parent"
175 android:layout_height="wrap_content"
176 android:layout_gravity="bottom|center_horizontal"
177 android:layout_marginTop="20dp"
178 android:background="@drawable/dialog_radius_5_415e_bg"
179 android:gravity="center"
180 android:paddingTop="15dp"
181 android:paddingBottom="15dp"
182 android:text="@string/bind_asset"
183 android:textColor="@color/colorPrimary"
184 android:textSize="15sp"
185 android:textStyle="bold" />
186
187 <TextView
188 android:layout_width="wrap_content"
189 android:layout_height="wrap_content"
190 android:layout_marginTop="40dp"
191 android:text="@string/your_asset_id"
192 android:textColor="@color/text_color_primary"
193 android:textSize="15sp"
194 android:textStyle="bold" />
195
196 <EditText
197 android:id="@+id/last_used_asset_id"
198 android:layout_width="match_parent"
199 android:layout_height="40dp"
200 android:layout_marginTop="6dp"
201 android:layout_marginBottom="50dp"
202 android:height="40dp"
203 android:background="@drawable/selector_edit_text_bg"
204 android:hint="@string/display_asset_id"
205 android:inputType="none"
206 android:lines="1"
207 android:paddingStart="10dp"
208 android:paddingEnd="10dp"
209 android:textAlignment="viewStart"
210 android:textColor="@color/text_color_primary"
211 android:textColorHint="@color/md_grey_400"
212 android:textCursorDrawable="@drawable/shape_cursor_color"
213 android:textIsSelectable="true"
214 android:textSize="15sp"
215 tools:ignore="Autofill" />
216
217 </LinearLayout>
218 </ScrollView>
219
220 <ProgressBar
221 android:id="@+id/saving_progress"
222 android:layout_width="80dp"
223 android:layout_height="80dp"
224 android:layout_gravity="center"
225 android:visibility="gone" />
226
227</FrameLayout>

activity_extended_tracking.xml view source

1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:orientation="vertical"
8 android:padding="10dp"
9 tools:context=".MainActivity">
10
11 <LinearLayout
12 android:layout_width="wrap_content"
13 android:layout_height="wrap_content">
14 <Button
15 android:id="@+id/start_tracking"
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:text="@string/start_tracking"
19 />
20
21 <Button
22 android:id="@+id/stop_tracking"
23 android:layout_width="wrap_content"
24 android:layout_height="wrap_content"
25 android:layout_marginLeft="10dp"
26 android:text="@string/stop_tracking"
27 />
28
29 </LinearLayout>
30
31 <RadioGroup
32 android:id="@+id/radioGroup"
33 android:layout_width="wrap_content"
34 android:layout_height="wrap_content"
35 >
36
37 <RadioButton
38 android:id="@+id/radioButtonActive"
39 android:layout_width="wrap_content"
40 android:layout_height="wrap_content"
41 android:text="TRACKING_MODE_ACTIVE" />
42
43 <RadioButton
44 android:id="@+id/radioButtonBalanced"
45 android:layout_width="wrap_content"
46 android:layout_height="wrap_content"
47 android:text="TRACKING_MODE_BALANCED" />
48
49 <RadioButton
50 android:id="@+id/radioButtonPassive"
51 android:layout_width="wrap_content"
52 android:layout_height="wrap_content"
53 android:text="TRACKING_MODE_PASSIVE" />
54
55 </RadioGroup>
56
57 <TextView
58 android:id="@+id/isStopTracking"
59 android:layout_marginTop="10dp"
60 android:layout_width="wrap_content"
61 android:layout_height="wrap_content"/>
62
63
64 <TextView
65 android:id="@+id/locationEngineInfo"
66 android:layout_marginTop="20dp"
67 android:layout_width="wrap_content"
68 android:layout_height="wrap_content"/>
69
70 <TextView
71 android:id="@+id/locationInfo"
72 android:layout_marginTop="20dp"
73 android:layout_width="wrap_content"
74 android:layout_height="wrap_content"/>
75
76
77 <TextView
78 android:id="@+id/edit_asset_profile"
79 android:layout_width="match_parent"
80 android:layout_height="wrap_content"
81 android:layout_gravity="bottom|center_horizontal"
82 android:layout_marginTop="50dp"
83 android:background="@drawable/route_nav_bg"
84 android:gravity="center"
85 android:paddingTop="15dp"
86 android:paddingBottom="15dp"
87 android:text="@string/create_asset"
88 android:textColor="@color/white"
89 android:textSize="15sp"
90 android:textStyle="bold" />
91
92</LinearLayout>

SetProfileActivity view source

1class SetProfileActivity : AppCompatActivity() {
2 private lateinit var sharedPreferences: SharedPreferences
3 private lateinit var editIdView: EditText
4 private lateinit var editAssetNameView: EditText
5 private lateinit var editDescriptionView: EditText
6 private lateinit var editAttributesView: EditText
7 private lateinit var editAssetIdView: EditText
8 private lateinit var lastAssetIdView: EditText
9
10 private lateinit var createNewAssetView: TextView
11 private lateinit var bindAssetView: TextView
12 private lateinit var progressBar: View
13
14 private lateinit var customId: String
15 private lateinit var assetName: String
16 private lateinit var assetDescription: String
17 private lateinit var assetAttributes: String
18 private lateinit var assetId: String
19
20 private var isSplash = true
21
22 override fun onCreate(savedInstanceState: Bundle?) {
23 super.onCreate(savedInstanceState)
24 setContentView(R.layout.activity_set_profile)
25 sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
26 isSplash = intent.getBooleanExtra(Constants.IS_SPLASH_PAGE_KEY, true)
27 setActivityView()
28 initViewText()
29 setListeners()
30 checkAssetId()
31 }
32
33 private fun setActivityView() {
34 editIdView = findViewById(R.id.edit_custom_id)
35 editAssetNameView = findViewById(R.id.edit_asset_name)
36 editDescriptionView = findViewById(R.id.edit_asset_description)
37 editAttributesView = findViewById(R.id.edit_asset_attributes)
38 editAssetIdView = findViewById(R.id.edit_asset_id)
39 lastAssetIdView = findViewById(R.id.last_used_asset_id)
40
41 createNewAssetView = findViewById(R.id.create_new_asset)
42 bindAssetView = findViewById(R.id.bind_asset)
43
44 progressBar = findViewById(R.id.saving_progress)
45 }
46
47 private fun initViewText() {
48 customId =
49 sharedPreferences.getString(Constants.CUSTOM_ID_KEY, UUID.randomUUID().toString())
50 .toString()
51
52 assetName = sharedPreferences.getString(
53 Constants.ASSET_NAME_KEY,
54 getString(R.string.asset_name_example_value)
55 ) as String
56
57 assetDescription = sharedPreferences.getString(
58 Constants.ASSET_DESCRIPTION_KEY,
59 getString(R.string.asset_description_example_value)
60 ) as String
61
62 assetAttributes = sharedPreferences.getString(
63 Constants.ASSET_ATTRIBUTES_KEY,
64 getString(R.string.asset_attribute_example_value)
65 ) as String
66
67 assetId = sharedPreferences.getString(Constants.ASSET_ID_KEY, "") as String
68
69 val lastAssetId = sharedPreferences.getString(Constants.LAST_ASSET_ID_KEY, "") as String
70
71 editIdView.setText(customId)
72 editAssetNameView.setText(assetName)
73 editDescriptionView.setText(assetDescription)
74 editAttributesView.setText(assetAttributes)
75 lastAssetIdView.setText(lastAssetId)
76 lastAssetIdView.inputType = InputType.TYPE_NULL
77
78 if (!assetId.isNullOrEmpty()) {
79 editAssetIdView.setText(assetId)
80 }
81 }
82
83 private fun hideKeyboard() {
84 this.currentFocus?.let { view ->
85 val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
86 imm?.hideSoftInputFromWindow(view.windowToken, 0)
87 }
88 }
89
90 private fun setListeners() {
91 createNewAssetView.setOnClickListener {
92 readAssetInfoFromView()
93 if (!checkUserInput()) {
94 return@setOnClickListener
95 }
96
97 if (assetTrackingIsRunning) {
98 Toast.makeText(
99 this@SetProfileActivity,
100 "Asset tracking is ON, please turn off tracking before creating new asset!",
101 Toast.LENGTH_LONG
102 ).show()
103 return@setOnClickListener
104 }
105
106 hideKeyboard()
107 progressBar.visibility = View.VISIBLE
108
109 AssetTracking.instance.createNewAsset(
110 AssetProfile.Builder().setCustomId(customId).setName(assetName)
111 .setDescription(assetDescription).setAttributes(
112 mapOf("test attribute" to assetAttributes)
113 ).build(), object : AssetApiCallback<AssetCreationResponse> {
114 override fun onSuccess(result: AssetCreationResponse) {
115 progressBar.visibility = View.GONE
116 assetId = result.data.id
117 editAssetIdView.setText(assetId)
118 saveToSharedPreference()
119 }
120
121 override fun onFailure(exception: Exception) {
122 progressBar.visibility = View.GONE
123 Toast.makeText(
124 this@SetProfileActivity,
125 "create asset failed: " + exception.message,
126 Toast.LENGTH_LONG
127 ).show()
128 }
129 }
130 )
131
132 }
133
134 bindAssetView.setOnClickListener {
135 assetId = editAssetIdView.text.toString().trim()
136
137 if (assetId.isEmpty()) {
138 return@setOnClickListener
139 }
140 hideKeyboard()
141 progressBar.visibility = View.VISIBLE
142
143 AssetTracking.instance.bindAsset(
144 this@SetProfileActivity,
145 assetId,
146 object : AssetApiCallback<Unit> {
147 override fun onSuccess(result: Unit) {
148 progressBar.visibility = View.GONE
149
150 Toast.makeText(
151 this@SetProfileActivity,
152 String.format(
153 "bind asset successfully with assetId: %s",
154 assetId
155 ),
156 Toast.LENGTH_LONG
157 ).show()
158
159 sharedPreferences.edit().putString(Constants.LAST_ASSET_ID_KEY, assetId).apply()
160
161 if (isSplash) {
162 launchMainActivity()
163 } else {
164 finish()
165 }
166 }
167
168 override fun onFailure(exception: Exception) {
169 progressBar.visibility = View.GONE
170
171 val exceptionMessage = exception.message ?: ""
172
173 if (exceptionMessage.contains(AssetTrackingApiExceptionType.UN_UPLOADED_LOCATION_DATA.exceptionString)) {
174 showForceBindDialog(assetId, exceptionMessage)
175 } else {
176 Toast.makeText(
177 this@SetProfileActivity,
178 "bind asset failed: $exceptionMessage",
179 Toast.LENGTH_LONG
180 ).show()
181 }
182 }
183 })
184 }
185 }
186
187 private fun showForceBindDialog(assetId: String, warningMessage: String) {
188 val alertDialogBuilder = AlertDialog.Builder(this)
189
190 alertDialogBuilder.setMessage("$warningMessage, do you want to clear local data and force bind to new asset id?")
191
192 alertDialogBuilder.setPositiveButton("Proceed") { dialogInterface: DialogInterface, _: Int ->
193 dialogInterface.dismiss() // Close the dialog
194 progressBar.visibility = View.VISIBLE
195
196 AssetTracking.instance.forceBindAsset(this, assetId, object : AssetApiCallback<Unit> {
197 override fun onSuccess(result: Unit) {
198 progressBar.visibility = View.GONE
199
200 Toast.makeText(
201 this@SetProfileActivity,
202 String.format(
203 "Force bind new asset successfully with assetId: %s",
204 assetId
205 ),
206 Toast.LENGTH_LONG
207 ).show()
208
209 sharedPreferences.edit().putString(Constants.LAST_ASSET_ID_KEY, assetId).apply()
210
211 if (isSplash) {
212 launchMainActivity()
213 } else {
214 finish()
215 }
216 }
217
218 override fun onFailure(exception: Exception) {
219 progressBar.visibility = View.GONE
220
221 Toast.makeText(
222 this@SetProfileActivity,
223 "bind asset failed: " + exception.message,
224 Toast.LENGTH_LONG
225 ).show()
226 }
227 })
228 }
229
230 alertDialogBuilder.setNegativeButton("Cancel") { dialogInterface: DialogInterface, _: Int ->
231 dialogInterface.dismiss() // Close the dialog
232 }
233
234 val alertDialog = alertDialogBuilder.create()
235 alertDialog.show()
236 }
237
238 private fun readAssetInfoFromView() {
239 customId = editIdView.text.toString().trim()
240 assetName = editAssetNameView.text.toString().trim()
241 assetDescription = editDescriptionView.text.toString().trim()
242 assetAttributes = editAttributesView.text.toString().trim()
243 }
244
245 private fun saveToSharedPreference() {
246 sharedPreferences.edit().putString(Constants.CUSTOM_ID_KEY, customId).apply()
247 sharedPreferences.edit().putString(Constants.ASSET_NAME_KEY, assetName).apply()
248 sharedPreferences.edit().putString(Constants.ASSET_DESCRIPTION_KEY, assetDescription)
249 .apply()
250 sharedPreferences.edit().putString(Constants.ASSET_ATTRIBUTES_KEY, assetAttributes).apply()
251 sharedPreferences.edit()
252 .putString(Constants.ASSET_ID_KEY, assetId)
253 .apply()
254 }
255
256 private fun checkAssetId() {
257 if (isSplash && !TextUtils.isEmpty(assetId)) {
258 launchMainActivity()
259 }
260 }
261
262 private fun launchMainActivity() {
263 startActivity(Intent(this, ExtendedTrackingActivity::class.java))
264 finish()
265 }
266
267 private fun checkUserInput(): Boolean {
268 if (assetName.isEmpty()) {
269 Toast.makeText(this, R.string.please_enter_name, Toast.LENGTH_SHORT).show()
270 return false
271 }
272 return true
273 }
274}

ExtendedTrackingActivity view source

1class ExtendedTrackingActivity : AppCompatActivity(), View.OnClickListener,
2 AssetTrackingCallBack {
3 private lateinit var startTrackingButton: Button
4 private lateinit var stopTrackingButton: Button
5 private lateinit var radioGroup: RadioGroup
6 private lateinit var activeRadioButton: RadioButton
7 private lateinit var trackingStatusView: TextView
8 private lateinit var locationEngineInfoView: TextView
9 private lateinit var locationInfoView: TextView
10 private lateinit var editAssetProfileView: TextView
11
12
13 var permissionsManager: LocationPermissionsManager? = null
14 var currentSelectedTrackingMode = TrackingMode.ACTIVE
15
16 private val mainHandler by lazy {
17 Handler(Looper.getMainLooper())
18 }
19
20 override fun onCreate(savedInstanceState: Bundle?) {
21 super.onCreate(savedInstanceState)
22 setContentView(R.layout.activity_extended_tracking)
23 // custom location engine
24// TrackingSDK.setLocationEngine(CustomLocationEngine());
25 initialize("PUT YOUR API KEY HERE")
26
27 initView()
28
29 assetTrackingAddCallback(this)
30 bindExistingAsset()
31 }
32
33 private fun bindExistingAsset() {
34 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
35 val assetId = sharedPreferences.getString(Constants.LAST_ASSET_ID_KEY, "") as String
36 if (assetId.isNotEmpty()) {
37 AssetTracking.instance.bindAsset(
38 this@ExtendedTrackingActivity,
39 assetId,
40 object : AssetApiCallback<Unit> {
41 override fun onSuccess(result: Unit) {
42 Toast.makeText(
43 this@ExtendedTrackingActivity,
44 String.format(
45 "bind asset successfully with assetId: %s",
46 assetId
47 ),
48 Toast.LENGTH_LONG
49 ).show()
50 }
51
52 override fun onFailure(exception: Exception) {
53 Toast.makeText(
54 this@ExtendedTrackingActivity,
55 "bind asset failed: " + exception.message,
56 Toast.LENGTH_LONG
57 ).show()
58 }
59
60 }
61 )
62 }
63 }
64
65 override fun onDestroy() {
66 super.onDestroy()
67
68 assetTrackingRemoveCallback(this)
69 }
70
71 private fun initView() {
72 startTrackingButton = findViewById(R.id.start_tracking)
73 stopTrackingButton = findViewById(R.id.stop_tracking)
74 startTrackingButton.setOnClickListener(this)
75 stopTrackingButton.setOnClickListener(this)
76
77 activeRadioButton = findViewById(R.id.radioButtonActive)
78 activeRadioButton.isChecked = true
79
80 radioGroup = findViewById(R.id.radioGroup)
81 radioGroup.setOnCheckedChangeListener { group, checkedId ->
82 currentSelectedTrackingMode = enumValues<TrackingMode>().find {
83 it.value == group.indexOfChild(group.findViewById(checkedId))
84 }!!
85 AssetTracking.instance.updateLocationConfig(this, LocationConfig(currentSelectedTrackingMode))
86 }
87
88 editAssetProfileView = findViewById(R.id.edit_asset_profile)
89 editAssetProfileView.setOnClickListener {
90 if (AssetTracking.instance.isRunning(this)) {
91 Toast.makeText(this, "please stop tracking before editing asset profile", Toast.LENGTH_LONG).show()
92 return@setOnClickListener
93 }
94
95 val intent = Intent(this@ExtendedTrackingActivity, SetProfileActivity::class.java)
96 intent.putExtra(Constants.IS_SPLASH_PAGE_KEY, false)
97 startActivity(intent)
98 }
99
100 trackingStatusView = findViewById(R.id.isStopTracking)
101 locationEngineInfoView = findViewById(R.id.locationEngineInfo)
102 locationInfoView = findViewById(R.id.locationInfo)
103 }
104
105 @SuppressLint("SetTextI18n")
106 override fun onClick(view: View) {
107 if (view.id == R.id.start_tracking) {
108 checkPermissionsAndStartTracking()
109 } else if (view.id == R.id.stop_tracking) {
110// TrackingSDK.stopTracking()
111 assetTrackingStop()
112 updateTrackingStatus()
113 }
114 }
115
116 @SuppressLint("SetTextI18n")
117 private fun updateTrackingStatus() {
118 Log.d("asset", "updateTrackingStatus")
119 mainHandler.postDelayed({
120 val isTrackingOn = AssetTracking.instance.isRunning(this)
121 trackingStatusView.text = "Tracking Status: " + if (isTrackingOn) "ON" else "OFF"
122 if (!isTrackingOn) {
123 locationInfoView.text = ""
124 locationEngineInfoView.text = ""
125 }
126 }, 1000)
127
128 }
129
130 @SuppressLint(*["SetTextI18n", "MissingPermission"])
131 fun startTracking() {
132 assetTrackingStart()
133 updateTrackingStatus()
134 }
135
136
137 private fun showLocationServiceOffDialog() {
138 val alertDialogBuilder = AlertDialog.Builder(this)
139
140 alertDialogBuilder.setTitle("Location Services Disabled")
141 alertDialogBuilder.setMessage("To enable location services, please go to Settings > Privacy > Location Services.")
142
143 alertDialogBuilder.setPositiveButton("OK") { dialogInterface: DialogInterface, _: Int ->
144 dialogInterface.dismiss() // Close the dialog
145 }
146
147 val alertDialog = alertDialogBuilder.create()
148 alertDialog.show()
149 }
150
151 private fun checkPermissionsAndStartTracking() {
152 if (areAllLocationPermissionGranted(this@ExtendedTrackingActivity)) {
153 startTracking()
154 } else if (!isLocationServiceEnabled(this@ExtendedTrackingActivity)) {
155 showLocationServiceOffDialog()
156 } else {
157 permissionsManager = LocationPermissionsManager(object : LocationPermissionsListener {
158 override fun onExplanationNeeded(permissionsToExplain: List<String>?) {
159 Toast.makeText(
160 this@ExtendedTrackingActivity, "You need to accept location permissions.",
161 Toast.LENGTH_SHORT
162 ).show()
163 }
164
165 override fun onPermissionResult(granted: Boolean) {
166 if (granted) {
167 if (isBackgroundLocationPermissionGranted(this@ExtendedTrackingActivity)) {
168 startTracking()
169 } else {
170 permissionsManager?.requestBackgroundLocationPermissions(this@ExtendedTrackingActivity)
171 }
172 } else {
173 Toast.makeText(
174 this@ExtendedTrackingActivity, "You need to accept location permissions.$granted",
175 Toast.LENGTH_SHORT
176 ).show()
177 }
178 }
179 })
180 permissionsManager?.requestLocationPermissions(this)
181 }
182 }
183
184 override fun onRequestPermissionsResult(
185 requestCode: Int,
186 permissions: Array<String>,
187 grantResults: IntArray
188 ) {
189 super.onRequestPermissionsResult(requestCode, permissions, grantResults)
190 permissionsManager?.onRequestPermissionsResult(requestCode, permissions, grantResults)
191 }
192
193 private fun getTrackingModeString(trackingMode: TrackingMode): String {
194 return when (trackingMode.value) {
195 0 -> "TRACKING_MODE_ACTIVE"
196 1 -> "TRACKING_MODE_BALANCED"
197 2 -> "TRACKING_MODE_PASSIVE"
198 else -> "Unknown tracking mode"
199 }
200 }
201
202 @SuppressLint("SetTextI18n")
203 override fun onLocationSuccess(result: Location) {
204 locationInfoView.text = """
205 --------- Location Info ---------
206 Provider: ${result.provider}
207 Latitude: ${result.latitude}
208 Longitude: ${result.longitude}
209 Altitude: ${result.altitude}
210 Accuracy: ${result.accuracy}
211 speed:${result.speed}
212 Bearing: ${result.bearing}
213 Time: ${result.time}
214 """.trimIndent()
215 }
216
217 override fun onLocationFailure(exception: Exception) {
218 locationInfoView.text = exception.message
219 }
220
221 override fun onTrackingStart(assetId: String) {
222 updateTrackingStatus()
223 }
224
225 override fun onTrackingStop(assetId: String, trackingDisableType: TrackingDisableType) {
226 Log.d("asset", "onTrackingStop")
227 updateTrackingStatus()
228 }
229}

Upon executing the code example provided above, your app's appearance will resemble the following snippet:

docs-imagedocs-image
Asset Profile PageAsset Tracking Page

Code Highlights

The SetProfileActivity is for an Android activity that allows users to create and bind assets. The activity has the following main steps:

  1. Initialize the shared preferences.

  2. Initialize the view objects.

  3. Read the asset information from the view.

  4. Validate the user input.

  5. Check whether the asset ID is already set in shared preferences.

  6. Create a new asset or bind an existing asset.

  7. Save the asset information to shared preferences.

  8. Launch the MainActivity if the asset ID is already set in shared preferences and the activity was launched from the splash screen.

The following is a description of each step:

  1. To initialize the shared preferences, the activity calls the PreferenceManager.getDefaultSharedPreferences() method. This method returns a SharedPreferences object that contains the default shared preferences for the application.

  2. To initialize the view objects, the activity finds the view objects by their ID. The view objects include the following:

    1. editIdView: An EditText object that allows users to enter the asset's custom ID.

    2. editAssetNameView: An EditText object that allows users to enter the asset's name.

    3. editDescriptionView: An EditText object that allows users to enter the asset's description.

    4. editAttributesView: An EditText object that allows users to enter the asset's attributes.

    5. editAssetIdView: An EditText object that allows users to enter the asset's ID.

    6. lastAssetIdView: An EditText object that displays the last used asset ID.

  3. To read the asset information from the view, the activity gets the text from each of the EditText objects.

  4. To validate the user input, the activity checks the following:

    1. The asset's custom ID must be a valid UUID.

    2. The asset's name must not be empty.

    3. The asset's description must not be empty.

    4. The asset's attributes must be a valid JSON string.

  5. To check whether the asset ID is already set in shared preferences, the activity calls the checkAssetId() function.

  6. To create a new asset, the activity calls the AssetTracking.instance.createNewAsset() method. This method creates a new asset with the information that was entered by the user.

  7. To bind an existing asset, the activity calls the AssetTracking.instance.bindAsset() method. This method binds the asset that is specified by the assetId parameter to the device.

  8. To save the asset information to shared preferences, the activity calls the SharedPreferences.Editor.putString() method for each of the asset information keys.

  9. To launch the MainActivity, if the asset ID is already set in shared preferences and the activity was launched from the splash screen, the activity calls the launchMainActivity() function.

The ExtendedTrackingActivity is for an Android activity that allows users to start and stop tracking an asset. The activity has the following main steps:

  1. Initialize the location permissions manager.

  2. Bind an existing asset, if there is one.

  3. Initialize the view.

  4. Set up the click listeners for the buttons.

  5. Implement the onRequestPermissionsResult() method to handle the results of the location permission requests.

  6. Implement the onLocationSuccess() and onLocationFailure() methods to handle location updates.

  7. Implement the onTrackingStart() and onTrackingStop() methods to handle tracking events.

The following is a description of each step:

  1. To initialize the location permissions manager, the activity creates a new LocationPermissionsManager object and sets a listener for the onPermissionResult() event.

  2. To bind an existing asset, the activity gets the asset ID from shared preferences and calls the AssetTracking.instance.bindAsset() method.

  3. To initialize the view, the activity finds the view objects by their ID. The view objects include the following:

    1. start_tracking: A button that starts tracking the asset.

    2. stop_tracking: A button that stops tracking the asset.

    3. dit_asset_profile: A button that opens the asset profile activity.

    4. isStopTracking: A text view that displays the tracking status.

    5. locationInfo: A text view that displays location information.

    6. locationEngineInfo: A text view that displays the location engine information.

  4. To set up the click listeners for the buttons, the activity sets a click listener for the start_tracking button that calls the checkPermissionsAndStartTracking() method. The activity also sets a click listener for the stop_tracking button that calls the assetTrackingStop() method.

  5. To implement the onRequestPermissionsResult() method, the activity checks the results of the location permission requests and calls the startTracking() method if the permissions are granted.

  6. To implement the onLocationSuccess() and onLocationFailure() methods, the activity updates the locationInfo text view with the location information or the error message, respectively.

  7. To implement the onTrackingStart() and onTrackingStop() methods, the activity updates the isStopTracking text view to reflect the tracking status.