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
1
dependencies {
2
implementation 'com.drivequant.drivekit:drivekit-trip-analysis:$drivekit_version'
3
}
Copied!
Replace $drivekit_version with the DriveKit version you are using in your app

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
1
fun checkLocationPermission(requestCode: Int) {
2
val permissionFineLocationApproved = ActivityCompat.checkSelfPermission(this,
3
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
4
5
if (permissionFineLocationApproved) {
6
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
7
val backgroundLocationPermissionApproved = ActivityCompat.checkSelfPermission(
8
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
9
) == PackageManager.PERMISSION_GRANTED
10
if (!backgroundLocationPermissionApproved) {
11
ActivityCompat.requestPermissions(this,
12
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
13
requestCode)
14
}
15
}
16
} else {
17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
18
ActivityCompat.requestPermissions(this,
19
arrayOf(
20
Manifest.permission.ACCESS_FINE_LOCATION,
21
Manifest.permission.ACCESS_BACKGROUND_LOCATION),
22
requestCode)
23
} else {
24
ActivityCompat.requestPermissions(this,
25
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
26
requestCode)
27
}
28
}
29
}
Copied!
1
private void checkLocationPermission(int requestCode) {
2
boolean permissionFineLocationApproved = ActivityCompat.checkSelfPermission(this,
3
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
4
5
if (permissionFineLocationApproved) {
6
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
7
boolean backgroundLocationPermissionApproved = ActivityCompat.checkSelfPermission(
8
this, Manifest.permission.ACCESS_BACKGROUND_LOCATION
9
) == PackageManager.PERMISSION_GRANTED;
10
if (!backgroundLocationPermissionApproved) {
11
ActivityCompat.requestPermissions(this,
12
new String[] { Manifest.permission.ACCESS_BACKGROUND_LOCATION },
13
requestCode);
14
}
15
}
16
} else {
17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
18
ActivityCompat.requestPermissions(this,
19
new String[] {
20
Manifest.permission.ACCESS_FINE_LOCATION,
21
Manifest.permission.ACCESS_BACKGROUND_LOCATION },
22
requestCode);
23
} else {
24
ActivityCompat.requestPermissions(this,
25
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
26
requestCode);
27
}
28
}
29
}
30
Copied!
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
1
fun checkActivityRecognitionPermission(requestCode: Int) {
2
var isActivityRecognitionAuthorize = true
3
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
4
isActivityRecognitionAuthorize = ContextCompat.checkSelfPermission(this,
5
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED
6
}
7
if (!isActivityRecognitionAuthorize && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
8
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
9
Manifest.permission.ACTIVITY_RECOGNITION)) {
10
// Display a message to explain why the permission is necessary
11
} else {
12
ActivityCompat.requestPermissions(this,
13
arrayOf(Manifest.permission.ACTIVITY_RECOGNITION),
14
requestCode)
15
}
16
}
17
}
Copied!
1
private void checkActivityRecognitionPermission(int requestCode) {
2
boolean isActivityRecognitionAuthorize = true;
3
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
4
isActivityRecognitionAuthorize = ActivityCompat.checkSelfPermission(this,
5
Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED;
6
}
7
if (!isActivityRecognitionAuthorize && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
8
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
9
Manifest.permission.ACTIVITY_RECOGNITION)) {
10
// Display a message to explain why the permission is necessary
11
} else {
12
ActivityCompat.requestPermissions(this,
13
new String[] { Manifest.permission.ACTIVITY_RECOGNITION },
14
requestCode);
15
}
16
}
17
}
Copied!
If activity recognition permission is not granted by the user, Trip Analysis component will not work.

Nearby Devices Permission

For device running Android 12 and higher, it's required to ask the user for Nearby Devices permission. Find below an example of how to ask Nearby Devices permission:
Kotlin
Java
1
fun checkNearbyDevicesPermission(activity: Activity, requestCode : Int) {
2
val isNearbyDevicesPermissionAuthorized = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
3
ContextCompat.checkSelfPermission(
4
activity, Manifest.permission.BLUETOOTH_SCAN
5
) == PackageManager.PERMISSION_GRANTED
6
&& ContextCompat.checkSelfPermission(
7
activity, Manifest.permission.BLUETOOTH_CONNECT
8
) == PackageManager.PERMISSION_GRANTED
9
} else {
10
true
11
}
12
13
if (!isNearbyDevicesPermissionAuthorized && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
14
val shouldShowRationaleScan = shouldShowRequestPermissionRationale(activity, Manifest.permission.BLUETOOTH_SCAN)
15
val shouldShowRationaleConnect = shouldShowRequestPermissionRationale(activity, Manifest.permission.BLUETOOTH_CONNECT)
16
if (!shouldShowRationaleScan || !shouldShowRationaleConnect) {
17
// Display a message to explain why the permission is necessary
18
} else {
19
requestPermissions(activity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), requestCode)
20
}
21
}
22
}
Copied!
1
public void checkNearbyDevicesPermission(Activity activity, int requestCode) {
2
boolean isNearbyDevicesPermissionAuthorized;
3
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
4
isNearbyDevicesPermissionAuthorized = ContextCompat.checkSelfPermission(
5
activity, Manifest.permission.BLUETOOTH_SCAN
6
) == PackageManager.PERMISSION_GRANTED
7
&& ContextCompat.checkSelfPermission(
8
activity, Manifest.permission.BLUETOOTH_CONNECT
9
) == PackageManager.PERMISSION_GRANTED;
10
} else {
11
isNearbyDevicesPermissionAuthorized = true;
12
}
13
14
if (!isNearbyDevicesPermissionAuthorized && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
15
final boolean shouldShowRationaleScan = shouldShowRequestPermissionRationale(activity, Manifest.permission.BLUETOOTH_SCAN);
16
final boolean shouldShowRationaleConnect = shouldShowRequestPermissionRationale(activity, Manifest.permission.BLUETOOTH_CONNECT);
17
if (!shouldShowRationaleScan || !shouldShowRationaleConnect) {
18
// Display a message to explain why the permission is necessary
19
} else {
20
requestPermissions(activity, new String[] { Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT }, requestCode);
21
}
22
}
23
}
Copied!
If Nearby Devices permission is not granted by the user, Trip Analysis component won't work correctly.

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
1
fun checkGooglePlayServices() {
2
val apiAvailability = GoogleApiAvailability.getInstance()
3
val resultCode = apiAvailability.isGooglePlayServicesAvailable(this)
4
if (resultCode != ConnectionResult.SUCCESS) {
5
if (apiAvailability.isUserResolvableError(resultCode)) {
6
apiAvailability.getErrorDialog(this, resultCode, 9000).show()
7
}
8
}
9
}
Copied!
1
void checkGooglePlayServices() {
2
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
3
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
4
if (resultCode != ConnectionResult.SUCCESS) {
5
if (apiAvailability.isUserResolvableError(resultCode)) {
6
apiAvailability.getErrorDialog(this, resultCode, 9000).show();
7
}
8
}
9
}
Copied!

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
1
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Copied!
Then, call the following code after explaining to the user why battery optimization is required:
Kotlin
Java
1
fun checkBatteryOptimization(){
2
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
3
val packageName = this.packageName
4
val pm = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
5
if (!pm.isIgnoringBatteryOptimizations(packageName)){
6
val intent = Intent()
7
intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
8
intent.data = Uri.parse("package:$packageName")
9
this.startActivity(intent)
10
}
11
}
12
}
Copied!
1
void checkBatteryOptimization(){
2
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
3
Intent intent = new Intent();
4
String packageName = getPackageName();
5
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
6
if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)){
7
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
8
intent.setData(Uri.parse("package:" + packageName));
9
startActivity(intent);
10
}
11
}
12
}
Copied!
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
1
class MyApplication: Application() {
2
3
override fun onCreate() {
4
super.onCreate()
5
DriveKit.initialize(this)
6
DriveKitTripAnalysis.initialize(createForegroundNotification(), object: TripListener {
7
override fun tripStarted(startMode : StartMode) {
8
}
9
override fun tripPoint(tripPoint : TripPoint) {
10
}
11
override fun tripSavedForRepost() {
12
}
13
override fun beaconDetected() {
14
}
15
override fun sdkStateChanged(state: State) {
16
}
17
})
18
}
19
20
private fun createForegroundNotification(): TripNotification{
21
val notification = TripNotification(
22
"DriveKit SDK",
23
"Start a trip with DriveKit SDK",
24
R.drawable.ic_trip_notification)
25
return notification
26
}
27
}
Copied!
1
public class MyApplication extends Application {
2
3
@Override
4
public void onCreate() {
5
super.onCreate();
6
DriveKit.INSTANCE.initialize(this);
7
DriveKitTripAnalysis.INSTANCE.initialize(createForegroundNotification(), new TripListener() {
8
@Override
9
public void tripStarted(@NotNull StartMode startMode) {
10
}
11
@Override
12
public void tripPoint(@NotNull TripPoint tripPoint) {
13
}
14
@Override
15
public void tripSavedForRepost() {
16
}
17
@Override
18
public void beaconDetected() {
19
}
20
@Override
21
public void sdkStateChanged(State state) {
22
}
23
});
24
}
25
26
public TripNotification createForegroundNotification(){
27
TripNotification tripNotification = new TripNotification(
28
"DriveKit SDK",
29
"Start a trip with DriveKit SDK",
30
R.drawable.ic_trip_notification);
31
return tripNotification;
32
}
33
}
Copied!
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
1
DriveKitTripAnalysis.isConfigured()
Copied!
1
DriveKitTripAnalysis.INSTANCE.isConfigured();
Copied!
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
1
DriveKitTripAnalysis.setVehicle(vehicle: Vehicle)
Copied!
1
DriveKitTripAnalysis.INSTANCE.setVehicle(vehicle);
Copied!
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
1
class TripReceiver : TripAnalysedReceiver() {
2
3
override fun onTripReceived(context: Context,
4
post: PostGeneric,
5
response: PostGenericResponse) {
6
}
7
8
override fun onTripCancelled(context: Context, status: CancelTrip) {
9
}
10
}
Copied!
1
public class TripReceiver extends TripAnalysedReceiver {
2
@Override
3
public void onTripReceived(
4
final Context context,
5
final PostGeneric post,
6
final PostGenericResponse response) {
7
}
8
@Override
9
public void onTripCancelled(
10
@NotNull Context context,
11
@NotNull CancelTrip cancelTrip) {
12
}
13
}
Copied!
  • 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
1
class MyApplication: Application() {
2
3
override fun onCreate() {
4
super.onCreate()
5
DriveKit.initialize(this)
6
DriveKitTripAnalysis.initialize(createForegroundNotification(), object: TripListener {
7
override fun tripStarted(startMode : StartMode) {
8
}
9
override fun tripPoint(tripPoint : TripPoint) {
10
}
11
override fun tripSavedForRepost() {
12
}
13
override fun beaconDetected() {
14
}
15
override fun sdkStateChanged(state: State) {
16
}
17
})
18
registerReceiver()
19
}
20
21
private fun registerReceiver(){
22
val receiver = TripReceiver()
23
val filter = IntentFilter("com.drivequant.sdk.TRIP_ANALYSED")
24
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter)
25
}
26
...
27
}
Copied!
1
public class MyApplication extends Application {
2
3
@Override
4
public void onCreate() {
5
super.onCreate();
6
DriveKit.INSTANCE.initialize(this);
7
DriveKitTripAnalysis.INSTANCE.initialize(createForegroundNotification(), new TripListener() {
8
@Override
9
public void tripStarted(@NotNull StartMode startMode) {
10
}
11
@Override
12
public void tripPoint(@NotNull TripPoint tripPoint) {
13
}
14
@Override
15
public void tripSavedForRepost() {
16
}
17
@Override
18
public void beaconDetected() {
19
}
20
@Override
21
public void sdkStateChanged(State state) {
22
}
23
});
24
registerReceiver()
25
}
26
private void registerReceiver(){
27
TripReceiver receiver = new TripReceiver();
28
IntentFilter filter = new IntentFilter("com.drivequant.sdk.TRIP_ANALYSED");
29
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
30
}
31
...
32
}
Copied!

Trip

Start a trip

You can start a trip by calling the following method:
Kotlin
Java
1
DriveKitTripAnalysis.startTrip()
Copied!
1
DriveKitTripAnalysis.INSTANCE.startTrip();
Copied!
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
1
DriveKitTripAnalysis.stopTrip()
Copied!
1
DriveKitTripAnalysis.INSTANCE.stopTrip();
Copied!
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
1
DriveKitTripAnalysis.cancelTrip()
Copied!
1
DriveKitTripAnalysis.INSTANCE.cancelTrip();
Copied!
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
1
DriveKitTripAnalysis.isTripRunning()
Copied!
1
DriveKitTripAnalysis.INSTANCE.isTripRunning();
Copied!
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
1
DriveKitTripAnalysis.getRecorderState()
Copied!
1
DriveKitTripAnalysis.INSTANCE.getRecorderState();
Copied!
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
1
DriveKitTripAnalysis.checkTripToRepost()
Copied!
1
DriveKitTripAnalysis.INSTANCE.checkTripToRepost();
Copied!

Reset

If you need to reset Trip analysis configuration (user logout for example), you can call the following method:
Kotlin
Java
1
DriveKitTripAnalysis.reset()
Copied!
1
DriveKitTripAnalysis.INSTANCE.reset();
Copied!
All data saved locally by Trip Analysis component will be erased and default configuration will be restored.
Last modified 30d ago