3
import 'package:flutter/material.dart';
4
import 'package:fluttertoast/fluttertoast.dart';
5
import 'package:nb_asset_tracking_flutter/nb_asset_tracking_flutter.dart';
6
import 'package:nb_asset_tracking_flutter_example/util/permiss_checker.dart';
7
import 'package:nb_asset_tracking_flutter_example/util/toast_mixin.dart';
8
import 'package:shared_preferences/shared_preferences.dart';
10
import '../util/consts.dart';
11
import 'create_asset.dart';
13
class HomeScreen extends StatefulWidget {
14
const HomeScreen({super.key});
17
State<HomeScreen> createState() => _MyAppState();
20
class _MyAppState extends State<HomeScreen> with ToastMixin implements OnTrackingDataCallBack {
21
bool _isRunning = false;
22
bool isAllowMockLocation = false;
23
bool enableTrackingStartedNotification = true;
24
bool enableTrackingStopNotification = true;
25
final assetTracking = AssetTracking();
26
TrackingMode selectedOption = TrackingMode.active;
27
CustomIntervalMode selectedIntervalMode = CustomIntervalMode.distanceBased;
28
String trackingStatus = 'Tracking Status: ';
29
String locationInfo = '';
30
late SharedPreferences sharedPreferences;
31
final TextEditingController textEditingController = TextEditingController();
36
assetTracking.initialize(apiKey: accessKey);
37
Stream<AssetResult> statusStream = assetTracking.isTracking().asStream();
38
statusStream.listen((value) {
39
_isRunning = value.data;
40
updateTrackingStatus(_isRunning);
43
assetTracking.addDataListener(this);
44
initSharedPreferences();
48
Future initSharedPreferences() async {
49
sharedPreferences = await SharedPreferences.getInstance();
51
AssetResult result = await assetTracking.getFakeGpsConfig();
53
bool allow = sharedPreferences.getBool(keyOfFakeGpsFlag) ?? result.data;
54
assetTracking.setFakeGpsConfig(allow: allow);
56
String trackingMode = sharedPreferences.getString(keyOfTrackingMode) ?? TrackingMode.active.name;
57
TrackingMode mode = TrackingMode.fromString(trackingMode);
58
assetTracking.setLocationConfig(config: LocationConfig.config(mode));
60
var envConfig = sharedPreferences.getString(keyOfEnvConfig);
61
if (envConfig?.isNotEmpty == true) {
62
assetTracking.setDataTrackingConfig(
63
config: DataTrackingConfig(baseUrl: EnvConfig.fromString(envConfig!) == EnvConfig.prod ? baseUrlProd : baseUrlStaging));
67
isAllowMockLocation = allow;
68
selectedOption = mode;
72
void bindExistAssetId() async {
73
SharedPreferences prefs = await SharedPreferences.getInstance();
74
String? boundId = prefs.getString(keyOfBoundId);
76
if (boundId == null) {
80
AssetResult result = await assetTracking.bindAsset(customId: boundId);
81
if (!result.success) {
82
showToast("bind asset failed: ${result.msg}");
85
showToast("Bind asset successfully with id: ${result.data}");
91
assetTracking.removeDataListener(this);
95
void updateTrackingStatus(bool isRunning) {
97
_isRunning = isRunning;
98
final status = isRunning ? "ON" : "OFF";
99
trackingStatus = 'Tracking Status: $status';
106
void startTracking() async {
107
if (Platform.isAndroid) {
108
var granted = await checkAndRequestLocationPermission();
110
showToast("Please granted location access for this app");
114
SharedPreferences prefs = await SharedPreferences.getInstance();
115
String? boundId = prefs.getString(keyOfBoundId);
117
if (boundId == null) {
118
showToast("You mast bind a asset Id first");
122
configNotificationConfig();
123
if (locationConfigAvailable()) {
124
assetTracking.startTracking();
129
void configNotificationConfig() {
130
if (Platform.isIOS) {
131
var iosNotificationConfig = IOSNotificationConfig();
132
iosNotificationConfig.showAssetEnableNotification = enableTrackingStartedNotification;
133
iosNotificationConfig.showAssetDisableNotification = enableTrackingStopNotification;
134
assetTracking.setIOSNotificationConfig(config: iosNotificationConfig);
138
bool locationConfigAvailable() {
139
if (selectedOption == TrackingMode.custom) {
140
num? customValue = num.tryParse(textEditingController.text);
141
if (customValue == null) {
142
Fluttertoast.showToast(
144
"Please enter ${selectedIntervalMode == CustomIntervalMode.distanceBased ? "distance interval" : "time interval"}",
145
gravity: ToastGravity.CENTER);
148
var locationConfig = LocationConfig();
149
switch (selectedIntervalMode) {
150
case CustomIntervalMode.distanceBased:
151
locationConfig = LocationConfig(smallestDisplacement: customValue.toDouble());
153
case CustomIntervalMode.timeBased:
154
locationConfig = LocationConfig(intervalForAndroid: customValue.toInt() * 1000);
157
assetTracking.setLocationConfig(config: locationConfig);
162
void stopTracking() {
163
configNotificationConfig();
164
assetTracking.stopTracking();
168
Widget build(BuildContext context) {
171
title: const Text('Asset Tracking Flutter'),
173
body: SingleChildScrollView(
175
padding: const EdgeInsets.symmetric(horizontal: 16.0),
177
crossAxisAlignment: CrossAxisAlignment.start,
179
_notificationConfig(),
183
'Allow mock location',
184
style: TextStyle(fontSize: 16),
189
value: isAllowMockLocation,
192
isAllowMockLocation = value;
194
assetTracking.setFakeGpsConfig(allow: value);
195
sharedPreferences.setBool(keyOfFakeGpsFlag, value);
197
activeTrackColor: Colors.lightGreenAccent,
198
activeColor: Colors.green,
205
child: RadioListTile<TrackingMode>(
207
'TRACKING_MODE_ACTIVE',
208
style: TextStyle(fontSize: 15),
210
value: TrackingMode.active,
211
groupValue: selectedOption,
212
onChanged: _isRunning
215
assetTracking.updateLocationConfig(config: LocationConfig.activeConfig());
217
selectedOption = value!;
219
sharedPreferences.setString(keyOfTrackingMode, selectedOption.name);
221
contentPadding: EdgeInsets.zero,
226
child: RadioListTile<TrackingMode>(
228
'TRACKING_MODE_BALANCED',
229
style: TextStyle(fontSize: 15),
231
value: TrackingMode.balanced,
232
groupValue: selectedOption,
233
onChanged: _isRunning
236
assetTracking.updateLocationConfig(config: LocationConfig.balancedConfig());
238
selectedOption = value!;
240
sharedPreferences.setString(keyOfTrackingMode, selectedOption.name);
242
contentPadding: EdgeInsets.zero,
247
child: RadioListTile<TrackingMode>(
249
'TRACKING_MODE_PASSIVE',
250
style: TextStyle(fontSize: 15),
252
value: TrackingMode.passive,
253
groupValue: selectedOption,
254
onChanged: _isRunning
257
assetTracking.updateLocationConfig(config: LocationConfig.passiveConfig());
259
selectedOption = value!;
261
sharedPreferences.setString(keyOfTrackingMode, selectedOption.name);
263
contentPadding: EdgeInsets.zero,
268
child: RadioListTile<TrackingMode>(
270
'TRACKING_MODE_CUSTOM',
271
style: TextStyle(fontSize: 15),
273
value: TrackingMode.custom,
274
groupValue: selectedOption,
275
onChanged: _isRunning
278
assetTracking.updateLocationConfig(config: LocationConfig());
280
selectedOption = value!;
282
sharedPreferences.setString(keyOfTrackingMode, selectedOption.name);
284
contentPadding: EdgeInsets.zero,
288
padding: const EdgeInsets.only(left: 48.0, top: 15),
292
? DropdownButton<CustomIntervalMode>(
293
value: selectedIntervalMode,
294
underline: Container(
300
value: CustomIntervalMode.distanceBased,
303
style: TextStyle(fontSize: 15),
307
value: CustomIntervalMode.timeBased,
310
style: TextStyle(fontSize: 15),
314
alignment: AlignmentDirectional.topCenter,
315
onChanged: customOptionAvailable()
318
selectedIntervalMode = value!;
326
margin: EdgeInsets.only(left: 8, right: 8),
329
enabled: customOptionAvailable(),
330
controller: textEditingController,
332
keyboardType: TextInputType.number,
334
color: customOptionAvailable() ? Colors.black : Colors.grey.shade400, fontSize: 16.0),
335
decoration: InputDecoration(
336
contentPadding: const EdgeInsets.only(left: 6, right: 6, top: 0, bottom: 0),
337
border: const OutlineInputBorder(),
338
hintText: selectedIntervalMode == CustomIntervalMode.distanceBased
341
hintStyle: const TextStyle(color: Colors.grey, fontSize: 15.0))),
349
padding: const EdgeInsets.only(top: 20),
351
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
355
padding: const EdgeInsets.symmetric(horizontal: 2.0),
356
child: ElevatedButton(
357
onPressed: _isRunning
362
child: const Text('START TRACKING', style: TextStyle(fontSize: 13)),
368
padding: const EdgeInsets.symmetric(horizontal: 2.0),
369
child: ElevatedButton(
370
onPressed: _isRunning
375
child: const Text('STOP TRACKING', style: TextStyle(fontSize: 13)),
383
padding: const EdgeInsets.only(top: 18.0),
384
child: Text(trackingStatus),
394
width: double.infinity,
396
padding: const EdgeInsets.symmetric(horizontal: 5.0),
397
child: ElevatedButton(
398
onPressed: () async {
399
AssetResult assetResult = await assetTracking.isTracking();
400
if(assetResult.data) {
401
Fluttertoast.showToast(msg: "please stop tracking before editing asset profile");
406
child: const Text('Create new Asset'),
414
// width: double.infinity,
415
// child: ElevatedButton(
419
// child: const Text('View data uploaded logs'),
429
bool customOptionAvailable() {
430
return !_isRunning && selectedOption == TrackingMode.custom;
433
void pushToCreateAsset() {
436
MaterialPageRoute(builder: (context) => const CreateAssteScreen()),
441
void onLocationFailure(String message) {
443
locationInfo = "------- Location Info ------- \n"
449
void onLocationSuccess(NBLocation location) {
452
locationInfo = "------- Location Info ------- \n"
453
"Provider: ${location.provider} \n"
454
"Latitude: ${location.latitude}\n"
455
"Longitude: ${location.longitude}\n"
456
"Altitude: ${location.altitude}\n"
457
"Accuracy: ${location.accuracy}\n"
458
"Speed: ${location.speed}\n"
459
"Bearing: ${location.heading}\n"
460
"Time: ${location.timestamp}\n";
466
void onTrackingStart(String message) {
467
updateTrackingStatus(true);
471
void onTrackingStop(String message) {
472
updateTrackingStatus(false);
475
Widget _notificationConfig() {
476
if (Platform.isAndroid) {
484
'Enable Tracking Started Notification',
485
style: TextStyle(fontSize: 16),
490
value: enableTrackingStartedNotification,
493
enableTrackingStartedNotification = value;
495
sharedPreferences.setBool(keyOfEnableTrackingStartedNotification, value);
497
activeTrackColor: Colors.lightGreenAccent,
498
activeColor: Colors.green,
506
'Enable Tracking Stopped Notification',
507
style: TextStyle(fontSize: 16),
512
value: enableTrackingStopNotification,
515
enableTrackingStopNotification = value;
517
sharedPreferences.setBool(keyOfEnableTrackingStopNotification, value);
519
activeTrackColor: Colors.lightGreenAccent,
520
activeColor: Colors.green,