Skip to content

Instantly share code, notes, and snippets.

@lukepighetti
Last active June 28, 2023 00:49
Show Gist options
  • Save lukepighetti/dfd9ebe73a3860c90d14d44020f3e58c to your computer and use it in GitHub Desktop.
Save lukepighetti/dfd9ebe73a3860c90d14d44020f3e58c to your computer and use it in GitHub Desktop.
All the basic data you need to roll your own analytics payloads
import 'dart:convert';
import 'dart:io';
import 'package:app/extensions.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:get_it/get_it.dart';
import 'package:package_info_plus/package_info_plus.dart';
Future<void> setupDeviceService() async {
final x = DeviceService();
await x.init();
GetIt.instance.registerSingleton(x);
}
class DeviceService {
static final _dip = DeviceInfoPlugin();
Future<void> init() async {
// Platform
platform = defaultTargetPlatform.name;
localeName = Platform.localeName;
timezone = await FlutterTimezone.getLocalTimezone();
// Device info
if (Platform.isIOS) {
final d = await _dip.iosInfo;
platform = 'ios';
deviceId = d.identifierForVendor;
isPhysicalDevice = d.isPhysicalDevice;
_deviceData = d.data.toSerializableMap();
} else if (Platform.isAndroid) {
final d = await _dip.androidInfo;
deviceId = d.fingerprint;
isPhysicalDevice = d.isPhysicalDevice;
_deviceData = d.data.toSerializableMap();
} else {
final d = await _dip.deviceInfo;
_deviceData = d.data.toSerializableMap();
}
// Package info
final pi = await PackageInfo.fromPlatform();
version = pi.version;
buildNumber = pi.buildNumber;
_packageData = {
'app_name': pi.appName,
'build_number': pi.buildNumber,
'build_signature': pi.buildSignature,
'installer_store': pi.installerStore,
'package_name': pi.packageName,
'version': pi.version,
};
}
// Platform
String? platform;
String? localeName;
String? timezone;
// Device info
String? deviceId;
bool? isPhysicalDevice;
Map<String, dynamic> _deviceData = {};
// Package info
String? version;
String? buildNumber;
Map<String, dynamic> _packageData = {};
Map<String, dynamic>? get analyticsData => {
...{
"platform": platform,
"localeName": localeName,
"timezone": timezone,
}.prefixedWith('platform.'),
..._deviceData.prefixedWith("device."),
..._packageData.prefixedWith("package."),
};
}
extension on Map<String, dynamic> {
Map<String, dynamic> toSerializableMap() {
return jsonDecode(
jsonEncode(this, toEncodable: (foo) => foo.toString()),
);
}
}
ApiResponse<void> userEvent(UserEvent payload) async {
try {
await _dio.post<void>(
"/events/user",
data: [
{
"type": payload.toJson()['type'],
"payload": payload.toJson(),
}
],
);
debugPrint('EVENT: ${payload.toString()}');
return Result.success(null);
} on Object {
return Result.failure(ApiError.serverUnreachable);
}
}
extension StringMapExtensions<V> on Map<String, V> {
Map<String, dynamic> prefixedWith(String prefix) {
return {for (final MapEntry(:key, :value) in entries) '$prefix$key': value};
}
}
@Freezed(unionKey: "type", unionValueCase: FreezedUnionCase.snake)
class UserEvent with _$UserEvent {
const factory UserEvent.launchApp() = _UserEventLaunchApp;
const factory UserEvent.interest(String name, bool interested) =
_UserEventInterest;
const factory UserEvent.requestTopic({
required String topic,
required String category,
required String reason,
}) = _UserEventRequestTopic;
const factory UserEvent.invalidTopic({
required String topicId,
}) = _UserEventInvalidTopic;
const factory UserEvent.giveFeedback({
required String feedback,
}) = _UserEventGiveFeedback;
const factory UserEvent.appLaunched({
required String? platform,
required String? localeName,
required String? timezone,
required Environment? environment,
required bool? kDebugMode,
required String? deviceId,
required bool? isPhysicalDevice,
required String? buildNumber,
required String? version,
required Map<String, dynamic>? extra,
}) = _UserEventAppLaunched;
factory UserEvent.fromJson(Map<String, Object?> json) =>
_$UserEventFromJson(json);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment