Flutter

Migrating from v0.0.22 to v6.9.x of the Sentiance Flutter SDKs

Changes regarding library imports

In version 0.0.22, the imports you needed to specify to interact with the Sentiance SDKs were a little too much. That's why we're now offering the entirety of a package's functionality under 1 library file, ready for import.

For the example, in order to create a new Sentiance user, you needed to do something like this:

// import #1, brings in CreateUserResult and CreateUserOptions types among other types
import 'package:sentiance_core/api.g.dart'; 
// import #2, brings in SentianceCore and more
import 'package:sentiance_core/sentiance_core.dart';

void createNewSentianceUser() async {
    final sentianceCore = SentianceCore();
    CreateUserResult result = await sentianceCore.createUser(
        CreateUserOptions(...)
    );
}

Change your code to import everything it needs from the sentiance_core package's single public library instead:

// This brings in everything you previously needed in addition to all other public declarations of the package
import 'package:sentiance_core/sentiance_core.dart';
                                                     
void createNewSentianceUser() async {
    final sentianceCore = SentianceCore();
    CreateUserResult result = await sentianceCore.createUser(
        CreateUserOptions(...)
    );
}

If you don't want to pollute the global namespace, you can be specific about what you want to import:

import 'package:sentiance_core/sentiance_core.dart' 
    show SentianceCore, CreateUserResult, CreateUserOptions; // Import only these 3 types

void createNewSentianceUser() async {
    final sentianceCore = SentianceCore();
    CreateUserResult result = await sentianceCore.createUser(
        CreateUserOptions(...)
    );
}

This applies for every single Sentiance package out there. At the time of writing this, the following are the only public imports for all of our SDKs:

import 'package:sentiance_core/sentiance_core.dart';
import 'package:sentiance_crash_detection/sentiance_crash_detection.dart';
import 'package:sentiance_driving_insights/sentiance_driving_insights.dart';
import 'package:sentiance_event_timeline/sentiance_event_timeline.dart';
import 'package:sentiance_smart_geofences/sentiance_smart_geofences.dart';
import 'package:sentiance_user_context/sentiance_user_context.dart';

For more information on what types and functionality our packages provide, check out the API reference on pub.dev.

Changes regarding duplicate type definitions across packages

In v0.0.22, several packages were re-defining the same type. For the example, sentiance_crash_detection was defining its own Location type, as well as sentiance_smart_geofences. These types shared the same fields as well, so it only made sense to get rid of the duplication here and to centralize the definition of commonly used types in one package and one package alone.

For more information on where to find what, check out the documentation on pub.dev.

Changes regarding the public signature of certain APIs

The signatures of several Sentiance APIs have changed. Make sure to update your code accordingly:

  • reset() now returns void instead of bool. If the operation succeeds, execution terminates normally. If an error occurs, a ResetError will be thrown.

  • submitDetections() now returns void instead of bool. If the operation succeeds, execution terminates normally. If an error occurs, a SubmitDetectionsError will be thrown.

  • enableDetections() now returns void instead of bool. If the operation succeeds, execution terminates normally. If an error occurs, an EnableDetectionsError will be thrown.

  • enableDetectionsWithExpiryDate() now returns void instead of bool. If the operation succeeds, execution terminates normally. If an error occurs, an EnableDetectionsError will be thrown.

  • disableDetections() now returns void instead of bool. If the operation succeeds, execution terminates normally. If an error occurs, a DisableDetectionsError will be thrown.

  • createUser() now throws a UserCreationError if the operation fails.

  • requestAccessToken() now throws a UserAccessTokenError if the operation fails.

  • refreshGeofences() now throws a SmartGeofencesRefreshError if the operation fails.

  • requestUserContext() now throws a RequestUserContextError if the operation fails.

  • invokeDummyVehicleCrash() now returns void instead of bool.

  • The getPhoneUsageEvents, getHarshDrivingEvents, getCallWhileMovingEvents, getSpeedingEvents, getTimelineUpdates and getTimelineEvents APIs now return a list of non-nullable events instead of nullable ones. This change could be breaking for you if you're using a linter as part of your build process. If not, you may want to do something about those "unnecessary null-aware operator use" warnings that will pop.

APIs that were removed

  • getLanguageName() has been removed and is no longer supported.

Changes concerning overall usage of background listeners

Setting a background listener

In order to set a listener to get notified of SDK events in the background - for the example, smart geofence events - you had to create a top level Dart handler function like this:

import 'package:sentiance_smart_geofences/api.g.dart';

@pragma('vm:entry-point')
void handleSmartGeofenceEvents() async {
  // Initialize required Flutter bindings
  WidgetsFlutterBinding.ensureInitialized();
  
  SentianceSmartGeofencesListenerApi.setUp(SmartGeofenceEventHandler());
}

class SmartGeofenceEventHandler extends SentianceSmartGeofencesListenerApi {
  @override
  void onSmartGeofenceEvent(SmartGeofenceEvent event) {
    // Do something with the event
  }
}

The SentianceSmartGeofencesListenerApi class is no longer directly accessible. Change your code to use the static SentianceSmartGeofences.registerSmartGeofenceEventListener function instead:

import 'package:sentiance_smart_geofences/sentiance_smart_geofences.dart';

@pragma('vm:entry-point')
void handleSmartGeofenceEvents() async {
  // Initialize required Flutter bindings
  WidgetsFlutterBinding.ensureInitialized();

  SentianceSmartGeofences.registerSmartGeofenceEventListener((smartGeofenceEvent) {
    // Do something with the event
  });
}

On that same note, here is a summary with all the changes that you need to make for any background listeners that you may be setting:

Before migrating
After migrating

SentianceUserContextListenerApi.setUp(...)

SentianceUserContext.registerUserContextUpdateListener()

SentianceEventTimelineListenerApi.setUp(...)

SentianceEventTimeline.registerEventTimelineUpdateListener()

SentianceSmartGeofencesListenerApi.setUp(...)

SentianceSmartGeofences.registerSmartGeofenceEventListener()

SentianceCrashDetectionListenerApi.setUp(...)

SentianceCrashDetection.registerCrashListener() SentianceCrashDetection.registerCrashDiagnosticListener()

SentianceDrivingInsightsListenerApi.setUp(...)

SentianceDrivingInsights.registerDrivingInsightsListener()

Setting crash detection background listeners

As you may have noticed in the table above, you now have the option to set a listener to vehicle crash events independently of setting another listener for crash diagnostic updates; make sure to update your code accordingly based on your needs and requirements.

Setting a user context updates' background listener

In version 0.0.22, you set a background listener to get the most recent user context updates as follows:

import 'package:sentiance_user_context/api.g.dart';

@pragma('vm:entry-point')
void handleUserContextUpdates() async {
  // Initialize required Flutter bindings
  WidgetsFlutterBinding.ensureInitialized();

  SentianceUserContextListenerApi.setUp(UserContextUpdatesHandler());
}

class UserContextUpdatesHandler extends SentianceUserContextListenerApi {
  @override
  void didUpdate(UserContext userContext) {
    // Do something with the user context
  }
}

Change your code to take into account an additional list of user context update criteria that now gets delivered as well:

import 'package:sentiance_user_context/sentiance_user_context.dart' show SentianceUserContext;

@pragma('vm:entry-point')
void handleUserContextUpdates() async {
  // Initialize required Flutter bindings
  WidgetsFlutterBinding.ensureInitialized();

  SentianceUserContext.registerUserContextUpdateListener((criteria, userContext) {
    // Do something with the user context
    // Do something with the update criteria
  });
}

Changes impacting users of event timeline features

All the event timeline APIs return objects of type TimelineEvent that had multiple nullable fields that only carry a value if the event is of a certain type.

The type field has been removed and the TimelineEvent class is now abstract. To process the timeline events based on their type, use inheritance checks as follows:

import 'package:sentiance_event_timeline/sentiance_event_timeline.dart';

final eventTimeline = SentianceEventTimeline();

/// A function that processes all events that occurred since the dawn of times.
void processTimelineEvents() async {
  final startEpochTimeMs = 0;
  final endEpochTimeMs = DateTime.now().millisecondsSinceEpoch;
  final events = await eventTimeline.getTimelineEvents(startEpochTimeMs, endEpochTimeMs);

  for (final timelineEvent in events) {
    if (timelineEvent is StationaryEvent) {
      // Process stationary
    } else if (timelineEvent is TransportEvent) {
      // Process transport
    } else if (timelineEvent is OffTheGridEvent) {
      // Process off the grid
    } else if (timelineEvent is UnknownEvent) {
      // Process unknown event
    }
  }
}

Changes impacting users of user context features

Segment attributes

As of v6.9.0, segment attribute values are double instead of int. Please update your code accordingly.

Changes impacting users of driving insights features

Call-while-moving events

  • The minTravelledSpeedInMps and maxTravelledSpeedInMps fields have been renamed to minTraveledSpeedInMps and maxTraveledSpeedInMps respectively.

Transport events associated with a driving insights payload

Transport events previously had a String type field, which is no longer the case.

final sentianceDrivingInsights = SentianceDrivingInsights();
final drivingInsights = await sentianceDrivingInsights.getDrivingInsights("transport_id_here");

String type = drivingInsights.transportEvent.type; // no longer compiles

Moreover, with v6.9.0, the transport event associated with driving insights is now a type that is provided by the sentiance_event_timeline package:

import 'package:sentiance_driving_insights/sentiance_driving_insights.dart' show SentianceDrivingInsights;
import 'package:sentiance_event_timeline/sentiance_event_timeline.dart' show TransportEvent;

final sentianceDrivingInsights = SentianceDrivingInsights();
final drivingInsights = await sentianceDrivingInsights.getDrivingInsights("transport_id_here");

TransportEvent transportEvent = drivingInsights.transportEvent;

Make sure to change your code accordingly.

Last updated