Skip to content

Commit cd00d32

Browse files
AshishSynoriqAshishSynoriqpavel-kuznetsov-hypertrack
authored
Pull requests - null safety and android (#15)
* Added support for null safety and updated plugin structure. (cherry picked from commit f585460) * Updated channel info (cherry picked from commit 1764b1d) * Updted example app. (cherry picked from commit 7320990) * Resolved addGeoTag method * Updated methods * Resolved 'enableDebugging' method * Updated null safety * update example app * Change !! to ?. for registrar activity * Handled actitvity null case * Removed semi colon * Updated error message for failed registration and sdkInstance * Updated null error for null sdkInstance in methodCall * Updated error message for onMethodCall method * Added call.method in error message * Handling optional parameters using ?. * Reset example folder from hypertrack master * removed quick start submodule * Discarded changes to the example * Added type cast to arguments * Removed result.error in registrar and updated example app * Fix types * Updated MainActivity.kt and main.dart * Update for iOS Co-authored-by: AshishSynoriq <ashish.taduce@synoriq,in> Co-authored-by: pavel.kuznetsov <pavel@hypertrack.io>
1 parent 50726b4 commit cd00d32

File tree

11 files changed

+518
-293
lines changed

11 files changed

+518
-293
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ build/
88
pubspec.lock
99
.gradle/
1010
local.properties
11+
example/pubspec.lock

android/src/main/kotlin/com/hypertrack/sdk/flutter/HyperTrackPlugin.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ public class HyperTrackPlugin(): FlutterPlugin, MethodCallHandler, StreamHandler
6060
fun registerWith(registrar: Registrar) {
6161
Log.i(TAG, "registerWith")
6262

63-
val context = registrar.activity().applicationContext
64-
val messenger = registrar.messenger()
65-
HyperTrackPlugin().onAttachedToEngine(context, messenger)
63+
registrar.activity()?.applicationContext?.let { context ->
64+
val messenger = registrar.messenger()
65+
HyperTrackPlugin().onAttachedToEngine(context, messenger)
66+
} ?: run {
67+
Log.i(TAG, "failedRegister")
68+
}
6669
}
67-
}
68-
70+
}
6971
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
7072
if (call.method == "initialize") {
7173
initialize(call.arguments(), result)
@@ -77,7 +79,7 @@ public class HyperTrackPlugin(): FlutterPlugin, MethodCallHandler, StreamHandler
7779

7880
val sdk = sdkInstance
7981
if (sdk == null) {
80-
result.error("NOT_INITIALIZED", "Sdk wasn't initialized", null)
82+
result.error("NOT_INITIALIZED", "Internal Error: onMethodCall(${call.method}) - sdkInstance is null", null)
8183
return
8284
}
8385

@@ -86,15 +88,13 @@ public class HyperTrackPlugin(): FlutterPlugin, MethodCallHandler, StreamHandler
8688
"isRunning" -> result.success(sdk.isRunning)
8789
"start" -> start(result, sdk)
8890
"stop" -> stop(result, sdk)
89-
"addGeotag" -> addGeotag(call.arguments(), result, sdk)
91+
"addGeotag" -> call.arguments<Map<String, Any>>()?.let { arguments -> addGeotag(arguments, result, sdk) } ?: result.error("INVALID_ARGS", "Internal Error: onMethodCall(${call.method}) - arguments is null", null)
9092
"allowMockLocations" -> allowMockLocations(result, sdk)
91-
"setDeviceName" -> setDeviceName(call.arguments(), result, sdk)
92-
"setDeviceMetadata" -> setDeviceMetadata(call.arguments(), result, sdk)
93+
"setDeviceName" -> call.arguments<String>()?.let { arguments -> setDeviceName(arguments, result, sdk) } ?: result.error("INVALID_ARGS", "Internal Error: onMethodCall(${call.method}) - arguments is null", null)
94+
"setDeviceMetadata" -> call.arguments<Map<String, Any>?>()?.let { arguments -> setDeviceMetadata(arguments, result, sdk) } ?: result.error("INVALID_ARGS", "Internal Error: onMethodCall(${call.method}) - arguments is null", null)
9395
"syncDeviceSettings" -> syncDeviceSettings(result, sdk)
9496
else -> result.notImplemented()
95-
9697
}
97-
9898
}
9999

100100
private var sdkInstance : HyperTrack? = null
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.hypertrack.sdk.hypertrack_example
22

3-
import androidx.annotation.NonNull;
4-
import io.flutter.embedding.android.FlutterActivity
5-
import io.flutter.embedding.engine.FlutterEngine
3+
import android.os.Bundle
4+
import io.flutter.app.FlutterActivity
65
import io.flutter.plugins.GeneratedPluginRegistrant
76

8-
class MainActivity: FlutterActivity() {
9-
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10-
GeneratedPluginRegistrant.registerWith(flutterEngine);
7+
class MainActivity : FlutterActivity() {
8+
override fun onCreate(savedInstanceState: Bundle?) {
9+
super.onCreate(savedInstanceState)
10+
GeneratedPluginRegistrant.registerWith(this)
1111
}
12-
}
12+
}

example/lib/main.dart

Lines changed: 90 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,117 @@
11
import 'package:flutter/material.dart';
2-
import 'dart:async';
3-
2+
import 'package:hypertrack_plugin/const/constants.dart';
43
import 'package:hypertrack_plugin/hypertrack.dart';
54

6-
void main() => runApp(MyApp());
5+
void main() {
6+
runApp(const MyApp());
7+
}
78

89
class MyApp extends StatefulWidget {
10+
const MyApp({Key? key}) : super(key: key);
11+
912
@override
10-
_MyAppState createState() => _MyAppState();
13+
State<MyApp> createState() => _MyAppState();
1114
}
1215

1316
class _MyAppState extends State<MyApp> {
14-
static const key = 'paste_your_key_here';
17+
HyperTrack _hypertrackFlutterPlugin = HyperTrack();
18+
final String _publishableKey = "<-- Place public key here -->";
19+
final String _deviceName = 'Lightning';
1520
String _result = 'Not initialized';
16-
String _deviceId = '';
17-
HyperTrack sdk;
18-
19-
// Platform messages are asynchronous, so we initialize in an async method.
20-
Future<void> initializeSdk() async {
21-
HyperTrack.enableDebugLogging();
22-
// Initializer is just a helper class to get the actual sdk instance
23-
String result = 'failure';
24-
try {
25-
sdk = await HyperTrack.initialize(key);
26-
result = 'initialized';
27-
sdk.setDeviceName("Flutter Elvis");
28-
sdk.setDeviceMetadata({"source": "flutter sdk"});
29-
sdk.onTrackingStateChanged.listen((TrackingStateChange event) {
30-
if (mounted) {
31-
setState(() {
32-
_result = '$event';
33-
});
34-
}
35-
});
36-
} catch (e) {
37-
print(e);
38-
}
21+
bool isRunning = false;
3922

40-
final deviceId = (sdk == null) ? "unknown" : await sdk.getDeviceId();
41-
42-
// If the widget was removed from the tree while the asynchronous platform
43-
// message was in flight, we want to discard the reply rather than calling
44-
// setState to update our non-existent appearance.
45-
if (!mounted) return;
46-
47-
setState(() {
48-
_result = result;
49-
_deviceId = deviceId;
50-
});
23+
@override
24+
void initState() {
25+
super.initState();
26+
initHyperTrack();
5127
}
5228

53-
void start() => sdk.start();
54-
55-
void stop() => sdk.stop();
56-
57-
void syncDeviceSettings() => sdk.syncDeviceSettings();
58-
5929
@override
6030
Widget build(BuildContext context) {
6131
return MaterialApp(
32+
theme: ThemeData(
33+
colorScheme: const ColorScheme.light(primary: Colors.green),
34+
),
6235
home: Scaffold(
63-
appBar: AppBar(
64-
title: const Text('Plugin example app'),
65-
),
66-
body: Center(
67-
child: Column(
68-
mainAxisAlignment: MainAxisAlignment.center,
69-
children: <Widget>[
70-
Text(
71-
'Initialization result is $_result',
72-
),
73-
Text(
74-
'Device id is $_deviceId',
36+
appBar: AppBar(
37+
title: const Text('HyperTrack Quickstart'),
38+
centerTitle: true,
39+
),
40+
body: ListView(
41+
children: [
42+
SizedBox(height: 10),
43+
ListTile(
44+
leading: const Text("Device name"),
45+
trailing: Text(
46+
_deviceName,
47+
),
7548
),
7649
ButtonBar(
50+
alignment: MainAxisAlignment.center,
7751
children: [
78-
TextButton(onPressed: start, child: Text("Start")),
79-
TextButton(
80-
onPressed: initializeSdk, child: Text("Initialize")),
81-
TextButton(onPressed: stop, child: Text("Stop")),
82-
TextButton(
83-
onPressed: syncDeviceSettings, child: Text("Sync")),
52+
ElevatedButton(
53+
style: ElevatedButton.styleFrom(primary: isRunning ? Colors.red : Colors.green),
54+
onPressed: () {
55+
isRunning
56+
? _hypertrackFlutterPlugin.stop()
57+
: _hypertrackFlutterPlugin.start();
58+
setState(() {});
59+
},
60+
child:
61+
Text(isRunning ? "Stop Tracking" : "Start Tracking"),
62+
63+
64+
),
65+
ElevatedButton(
66+
onPressed: () async =>
67+
_hypertrackFlutterPlugin.syncDeviceSettings(),
68+
child: const Text("Sync Settings"),
69+
),
8470
],
85-
alignment: MainAxisAlignment.center,
86-
mainAxisSize: MainAxisSize.max,
8771
),
8872
],
8973
),
90-
),
91-
),
74+
bottomNavigationBar: ListTile(
75+
leading: Text("Status"),
76+
trailing: Text(_result),
77+
)),
9278
);
9379
}
80+
81+
void initHyperTrack() async {
82+
_hypertrackFlutterPlugin = await HyperTrack().initialize(_publishableKey);
83+
_hypertrackFlutterPlugin.setDeviceName(_deviceName);
84+
_hypertrackFlutterPlugin.setDeviceMetadata({"source": "flutter sdk"});
85+
_hypertrackFlutterPlugin.onTrackingStateChanged
86+
.listen((TrackingStateChange event) {
87+
if (mounted) {
88+
updateButtonState();
89+
_result = getTrackingStatus(event);
90+
setState(() {});
91+
}
92+
});
93+
}
94+
95+
void updateButtonState() async {
96+
final temp = await _hypertrackFlutterPlugin.isRunning();
97+
isRunning = temp;
98+
setState(() {});
99+
}
94100
}
101+
102+
String getTrackingStatus (TrackingStateChange event) {
103+
Map<TrackingStateChange, String> statusMap = {
104+
TrackingStateChange.start: "Tracking Started",
105+
TrackingStateChange.stop: "Tracking Stop",
106+
TrackingStateChange.unknownError: "Unknown Error",
107+
TrackingStateChange.authError: "Authentication Error",
108+
TrackingStateChange.networkError: "Network Error",
109+
TrackingStateChange.invalidToken: "Invalid Token",
110+
TrackingStateChange.locationDisabled: "Location Disabled",
111+
TrackingStateChange.permissionsDenied: "Permissions Denied",
112+
};
113+
if (statusMap[event] == null) {
114+
throw Exception("Unexpected null value in getTrackingStatus");
115+
}
116+
return statusMap[event]!;
117+
}

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Demonstrates how to use the hypertrack plugin.
33
publish_to: 'none'
44

55
environment:
6-
sdk: ">=2.1.0 <3.0.0"
6+
sdk: ">=2.12.0 <3.0.0"
77

88
dependencies:
99
flutter:
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'package:flutter/services.dart';
2+
import 'package:hypertrack_plugin/hypertrack.dart';
3+
import '../hypertrack_platform_interface.dart';
4+
5+
/// A subclass of [HypertrackPlatformInterface] for Android overriding.
6+
class AndroidChannelHypertrack extends HypertrackPlatformInterface {
7+
/// The method channel used to interact with the native platform.
8+
final MethodChannel _methodChannel;
9+
10+
/// The event channel used to interact with the native platform.
11+
final EventChannel _eventChannel;
12+
13+
AndroidChannelHypertrack(this._methodChannel, this._eventChannel) : super();
14+
15+
@override
16+
Future<HyperTrack> initialize(String publishableKey) async {
17+
String? result =
18+
await _methodChannel.invokeMethod<String>("initialize", publishableKey);
19+
if (result != null) {
20+
throw Exception(result);
21+
}
22+
return HyperTrack();
23+
}
24+
25+
@override
26+
Future<bool> isRunning() async {
27+
bool temp = await _methodChannel.invokeMethod<bool>("isRunning") ?? false;
28+
return temp;
29+
}
30+
31+
@override
32+
startTracking() async => await _methodChannel.invokeMethod("start");
33+
34+
@override
35+
stopTracking() async => await _methodChannel.invokeMethod("stop");
36+
37+
@override
38+
getDeviceId() async => await _methodChannel.invokeMethod("getDeviceId");
39+
40+
@override
41+
addGeotag(data, expectedLocation) async =>
42+
await _methodChannel.invokeMethod("addGeotag", data);
43+
44+
@override
45+
allowMockLocations(allow) async =>
46+
await _methodChannel.invokeMethod("allowMockLocations");
47+
48+
@override
49+
setDeviceMetadata(data) async =>
50+
await _methodChannel.invokeMethod("setDeviceMetadata", data);
51+
52+
@override
53+
setDeviceName(data) async =>
54+
await _methodChannel.invokeMethod('setDeviceName', data);
55+
56+
@override
57+
syncDeviceSettings() async =>
58+
await _methodChannel.invokeMethod("syncDeviceSettings");
59+
60+
@override
61+
void enableDebugLogging() async {
62+
await _methodChannel.invokeMethod("enableDebugLogging");
63+
}
64+
}

0 commit comments

Comments
 (0)