Get started

Prerequisite

Before starting DriveKit Trip Analysis integration, make sure that you have initialized DriveKit.

Get module from repository

To add Trip Analysis module to your app, add the following line to your dependencies in your application build.gradle file:

build.gradle
build.gradle
dependencies {
implementation 'com.drivequant.drivekit:drivekit-trip-analysis:1.11.2'
}

Make sure that you always have the same version for all DriveKit modules in your project.

Location Permission

For device running Android 6 and higher, it's required to ask the user for location permission. Find below an example of how to ask location permission:

Kotlin
Java
Kotlin
fun checkLocationPermission(requestCode: Int) {
val permissionFineLocationApproved = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (permissionFineLocationApproved) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val backgroundLocationPermissionApproved = ActivityCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
) == PackageManager.PERMISSION_GRANTED
if (!backgroundLocationPermissionApproved) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
requestCode)
}
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(this,
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION),
requestCode)
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
requestCode)
}
}
}
Java
private void checkLocationPermission(int requestCode) {
boolean permissionFineLocationApproved = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
if (permissionFineLocationApproved) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
boolean backgroundLocationPermissionApproved = ActivityCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
) == PackageManager.PERMISSION_GRANTED;
if (!backgroundLocationPermissionApproved) {
ActivityCompat.requestPermissions(this,
new String[] { Manifest.permission.ACCESS_BACKGROUND_LOCATION },
requestCode);
}
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(this,
new String[] {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION },
requestCode);
} else {
ActivityCompat.requestPermissions(this,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
requestCode);
}
}
}

If location permission is not granted by the user, Trip Analysis SDK will not work.

Activity Recognition Permission

For device running Android 10 and higher, it's required to ask the user for activity recognition permission. Find below an example of how to ask the permission:

Kotlin
Java
Kotlin
fun checkActivityRecognitionPermission(requestCode: Int) {
var isActivityRecognitionAuthorize = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
isActivityRecognitionAuthorize = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED
}
if (!isActivityRecognitionAuthorize && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACTIVITY_RECOGNITION)) {
// Display a message to explain why the permission is necessary
} else {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACTIVITY_RECOGNITION),
requestCode)
}
}
}
Java
private void checkActivityRecognitionPermission(int requestCode) {
boolean isActivityRecognitionAuthorize = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
isActivityRecognitionAuthorize = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED;
}
if (!isActivityRecognitionAuthorize && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACTIVITY_RECOGNITION)) {
// Display a message to explain why the permission is necessary
} else {
ActivityCompat.requestPermissions(this,
new String[] { Manifest.permission.ACTIVITY_RECOGNITION },
requestCode);
}
}
}

If activity recognition permission is not granted by the user, Trip Analysis component will not work.

Google Play Services

Trip Analysis SDK requires Google Play Location Services 16.0.0 or above.

You can check the Play services version with the following code:

Kotlin
Java
Kotlin
fun checkGooglePlayServices() {
val apiAvailability = GoogleApiAvailability.getInstance()
val resultCode = apiAvailability.isGooglePlayServicesAvailable(this)
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, 9000).show()
}
}
}
Java
void checkGooglePlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, 9000).show();
}
}
}

Battery optimization

For device running Android 6 and higher, it's required to ask the user to disable battery optimization for your app. Without battery optimization disabled, Trip Analysis SDK will not work properly.

The SDK usage is included into acceptable use cases for requesting or being on the Battery Optimizations exceptions whitelist. For more information you can read the Android developer documentation on this topic.

Firstly, define REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission in AndroidManifest.xml file of your application.

AndroidManifest.xml
AndroidManifest.xml
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

Then, call the following code after explaining to the user why battery optimization is required:

Kotlin
Java
Kotlin
fun checkBatteryOptimization(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val packageName = this.packageName
val pm = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
if (!pm.isIgnoringBatteryOptimizations(packageName)){
val intent = Intent()
intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
intent.data = Uri.parse("package:$packageName")
this.startActivity(intent)
}
}
}
Java
void checkBatteryOptimization(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)){
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
}

If battery optimization is enabled, trip recording will not work.

Some manufacturers add other battery optimizations. You can find tutorials on how to disable these battery optimizations for main Android device manufacturers here.

Initialization

An initialization phase is required to use the functions offered by the Trip Analysis component. To initialize Trip Analysis component in your app, you must call the initialization method in onCreate method of your application class.

The initialization method requires a TripNotification object as parameter, and an optional implementation of TripListener.

MyApplication.kt
MyApplication.java
MyApplication.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
DriveKit.initialize(this)
DriveKitTripAnalysis.initialize(createForegroundNotification(), object: TripListener {
override fun tripStarted(startMode : StartMode) {
}
override fun tripPoint(tripPoint : TripPoint) {
}
override fun tripSavedForRepost() {
}
override fun beaconDetected() {
}
override fun sdkStateChanged(state: State) {
}
})
}
private fun createForegroundNotification(): TripNotification{
val notification = TripNotification(
"DriveKit SDK",
"Start a trip with DriveKit SDK",
R.drawable.ic_trip_notification)
return notification
}
}
MyApplication.java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
DriveKit.INSTANCE.initialize(this);
DriveKitTripAnalysis.INSTANCE.initialize(createForegroundNotification(), new TripListener() {
@Override
public void tripStarted(@NotNull StartMode startMode) {
}
@Override
public void tripPoint(@NotNull TripPoint tripPoint) {
}
@Override
public void tripSavedForRepost() {
}
@Override
public void beaconDetected() {
}
@Override
public void sdkStateChanged(State state) {
}
});
}
public TripNotification createForegroundNotification(){
TripNotification tripNotification = new TripNotification(
"DriveKit SDK",
"Start a trip with DriveKit SDK",
R.drawable.ic_trip_notification);
return tripNotification;
}
}

TripListener interface includes 5 methods to implement:

  • tripStarted(startMode : StartMode): This method is called each time a trip's started. StartMode indicates which event starts the trip. Possible values are described here.

  • tripPoint(tripPoint: TripPoint): This method is called when a trip's started and confirmed, for each GPS point recorded by the SDK. Data available in TripPoint object are described here.

  • tripSavedForRepost(): This method is called if at the end of the trip, the trip can be sent to DriveQuant's server for the analysis. The trip is saved locally on the SDK and will sent later.

  • beaconDetected(): This method is called when a beacon sets in the SDK is detected.

  • sdkStateChanged(state: State): This method is called every time the state of the SDK changed with the new state as parameter. States are described here.

End of trip notification: Depending on the trip Analysis service's response, we recommend that you specify the notification content if you decide to display a user feedback:

  • For a vehicle trip, you can display a message such as: Your trip has been analyzed.

  • For a trip by rail it is better to display the following message: Your journey was made by train.

Check your configuration

You can check if Trip Analysis component is well configured with the following method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.isConfigured()
Java
DriveKitTripAnalysis.INSTANCE.isConfigured();

This method returns true if it is well configured.

Vehicle

To obtain a more precise analysis on driving behavior, it's recommended to configure the vehicle used by the driver. You can do this by calling the following method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.setVehicle(vehicle: Vehicle)
Java
DriveKitTripAnalysis.INSTANCE.setVehicle(vehicle);

A detailed description of vehicle parameter is available here.

If no vehicle is configured, a default vehicle will be configured with the following parameters:

  • carTypeIndex = 1

  • carEngineIndex = 1

  • carPower = 150

  • carMass = 1

  • carGearboxIndex = 2

  • carConsumption = 4.5

Retrieve trip data

When a trip has been recorded and analyzed on DriveQuant's server, data can be retrieved by creating a class that extends TripAnalysedReceiver and implements the 2 methods onTripReceived and onTripCancelled.

Kotlin
Java
Kotlin
class TripReceiver : TripAnalysedReceiver() {
override fun onTripReceived(context: Context,
post: PostGeneric,
response: PostGenericResponse) {
}
override fun onTripCancelled(context: Context, status: CancelTrip) {
}
}
Java
public class TripReceiver extends TripAnalysedReceiver {
@Override
public void onTripReceived(
final Context context,
final PostGeneric post,
final PostGenericResponse response) {
}
@Override
public void onTripCancelled(
@NotNull Context context,
@NotNull CancelTrip cancelTrip) {
}
}
  • onTripReceived(context: Context, post: PostGeneric, response: PostGenericResponse): This method is called when a trip has been recorded by the SDK and sent to DriveQuant's server to be analyzed. PostGeneric object contains raw data sent to the server, PostGenericResponse object contains the trip analysis made on the server. Detailed description of these data are available here.

  • onTripCancelled(context: Context, status: CancelTrip): This method is called when a trip is cancelled. CancelTrip indicates which event cancels the trip. Possible values are described here.

Then in onCreate method of your application class, you have to register your class as a broadcast receiver to action com.drivequant.sdk.TRIP_ANALYSED.

MyApplication.kt
MyApplication.java
MyApplication.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
DriveKit.initialize(this)
DriveKitTripAnalysis.initialize(createForegroundNotification(), object: TripListener {
override fun tripStarted(startMode : StartMode) {
}
override fun tripPoint(tripPoint : TripPoint) {
}
override fun tripSavedForRepost() {
}
override fun beaconDetected() {
}
override fun sdkStateChanged(state: State) {
}
})
registerReceiver()
}
private fun registerReceiver(){
val receiver = TripReceiver()
val filter = IntentFilter("com.drivequant.sdk.TRIP_ANALYSED")
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter)
}
...
}
MyApplication.java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
DriveKit.INSTANCE.initialize(this);
DriveKitTripAnalysis.INSTANCE.initialize(createForegroundNotification(), new TripListener() {
@Override
public void tripStarted(@NotNull StartMode startMode) {
}
@Override
public void tripPoint(@NotNull TripPoint tripPoint) {
}
@Override
public void tripSavedForRepost() {
}
@Override
public void beaconDetected() {
}
@Override
public void sdkStateChanged(State state) {
}
});
registerReceiver()
}
private void registerReceiver(){
TripReceiver receiver = new TripReceiver();
IntentFilter filter = new IntentFilter("com.drivequant.sdk.TRIP_ANALYSED");
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
}
...
}

Trip

Start a trip

You can start a trip by calling the following method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.startTrip()
Java
DriveKitTripAnalysis.INSTANCE.startTrip();

If a trip's already started, calling this method will have no effect.

Stop a trip

You can stop a trip by calling the following method. The trip will be stopped instantly:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.stopTrip()
Java
DriveKitTripAnalysis.INSTANCE.stopTrip();

If a vehicle stops longer than the timeout configured, the trip will be stopped automatically.

If no trip is running, calling this method will have no effect.

Cancel a trip

If you want to cancel a trip, you can call this method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.cancelTrip()
Java
DriveKitTripAnalysis.INSTANCE.cancelTrip();

If no trip is running or if the trip has been sent to the server and is currently being analyzed, calling this method will have no effect.

SDK recorder state

Two methods are available to determinate SDK state.

Kotlin
Java
Kotlin
DriveKitTripAnalysis.isTripRunning()
Java
DriveKitTripAnalysis.INSTANCE.isTripRunning();

This method returns false if the SDK is in INACTIVE state, and no trip is currently running.

If you want a more detailed state of the SDK, you can call the following method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.getRecorderState()
Java
DriveKitTripAnalysis.INSTANCE.getRecorderState();

This method returns the state of the SDK.

  • INACTIVE: No trip is running.

  • STARTING: The auto start mode detects a movement of the user and checks if it's a trip in vehicle.

  • RUNNING: The trip has been confirmed by the speed of the movement.

  • STOPPING: The SDK is in this state when a potential trip end is detected. If the trip continues, the SDK goes back to RUNNING state. The duration of the stopping state can be configured.

  • SENDING: The trip is completed and sent to DriveQuant's server. When the SDK receives the response from the server, it switches to INACTIVE state, waiting for the next trip.

Repost

Trip Analysis SDK have a repost mechanism. In most cases, when a trip is finished, it is sent to DriveQuant's server for analysis. Once it's done, the result of the analysis is sent back to the SDK.

In some case, the trip can't be sent to DriveQuant's server (no network for example). In this case, the SDK will save the trip data locally to send it later. A retry will be attempted later when you are connected to network.

Kotlin
Java
Kotlin
DriveKitTripAnalysis.checkTripToRepost()
Java
DriveKitTripAnalysis.INSTANCE.checkTripToRepost();

Reset

If you need to reset Trip analysis configuration (user logout for example), you can call the following method:

Kotlin
Java
Kotlin
DriveKitTripAnalysis.reset()
Java
DriveKitTripAnalysis.INSTANCE.reset();

All data saved locally by Trip Analysis component will be erased and default configuration will be restored.