Skip to main content

Safe Driving Score Calculator using Vehicle SDK

Overview & Goals

This online tutorial is designed for developers who are new to vehicle app development but have experience in Android app (mobile or tablet) development and a basic understanding of Android. You will create a simple app using the Pleos Connect SDK. Through building a personalized safe driving score calculator app, you will learn step-by-step how to use the Vehicle SDK to integrate vehicle data.
This tutorial does not include design guidelines, UI implementation, or Android API integration details. Use this basic guide to create your own DIY vehicle app.

Development Level - Beginner
Basic knowledge of Android is recommended for smooth progress
Kotlin-based sample code guide provided

  • Prerequisite References:

    • Install Android Studio: Link
    • Android CarPropertyManager APIs: Link
    • Official Android Automotive App Development Guide: Link
    • Pleos Playground Vehicle SDK API Call Guide: Link
  • Learning Objectives:

    • Integrate vehicle data using the Pleos Vehicle SDK: API Details
  • Implementation Details: You will build a sample app that uses the Vehicle SDK to check car data and calculate a safe driving score. The app is designed for educational purposes.
    The score calculation includes three penalty factors:

  • Rapid acceleration: speed increases by 30km/h or more
  • Sudden braking: speed decreases by 30km/h or more
  • Poor steering: sharp changes of 50 degrees or more in either direction
    You can extend the app with additional use cases using other Vehicle APIs.

Sample App Overview (Use this flow to build your own score calculator)

  1. Scoring begins when the gear is shifted to Drive mode and the vehicle accelerates.
  2. The initial score starts at 100 points. If a penalty condition is detected through vehicle status integration, 5 points are deducted each time.
  3. See the following section for how to simulate driving behavior using adb commands.
  4. Scoring ends when the vehicle decelerates to 0 speed and the gear is shifted to Parking mode.
  5. Final report shows number of infractions and total score:
    • 100 P : Perfect Driver
    • 70 P or more : Best Driver
    • 50 P or more : Beginner Driver
    • Below 50 P : Novice Driver

Development Environment Setup

Pleos Connect provides a development and testing environment for building infotainment applications.

ItemVersion
Pleos Connect SDKv2.0.5
Minimum Android SDKAndroid API 26 or higher
Gradle Version8.0 or higher
LanguageJava, Kotlin
IDEAndroid Studio
AVDPleos Connect Emulator Setup Guide

SDK Integration Setup

To use the Vehicle SDK, configure SDK dependencies and required permissions.
See Vehicle SDK Integration Guide for details.

Source Code Implementation

Implement code and configuration (permissions) to connect with vehicle data.

[Driver Distraction Optimized 'true']

Since the sample app interacts with the driver during driving, you must declare Driver Distraction Optimized as true in AndroidManifest.
For details, refer to the official Android guidelines.

Step 1. Declare SDK Permissions

Declare permissions in AndroidManifest.xml to access vehicle speed and steering angle information.

[Android Automotive Integration Policy]

The Pleos Connect SDK aligns with Android Automotive OS if there are equivalent or similar APIs to minimize platform fragmentation. If features from the Pleos SDK are later absorbed into Android Automotive, the SDK guarantees backward compatibility for at least two major versions.

<?xml version="1.0" encoding="utf-8"?>
<manifest>
<!-- ... -->

<!-- TODO 2: Add dependencies and permissions (AndroidManifest.xml) -->
<uses-permission android:name="pleos.car.permission.CAR_DRIVE" />
<uses-permission android:name="android.car.permission.CAR_SPEED" />

<application />
<!-- ... -->
</manifest>

Step 2. Implement SDK Usage Code (Kotlin)

Using Vehicle SDK - Common (1/4)

Provide the Vehicle instance app-wide through a Hilt module using the @Provides method.

// package ai.pleos.playground.handson.vehicle.di.VehicleModules
@Module
@InstallIn(SingletonComponent::class)
object VehicleModules {
// TODO 3-1: Using Vehicle SDK - common
@Provides
@Singleton
fun provideVehicle(
@ApplicationContext context: Context
): Vehicle = Vehicle(context)
}

Using Vehicle SDK - Common (2/4)

Inject the Vehicle instance into MainActivity using @Inject.

// package ai.pleos.playground.handson.vehicle.MainActivity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
// TODO 3-2: Using Vehicle SDK - common
@Inject
lateinit var vehicle: Vehicle

override fun onCreate(savedInstanceState: Bundle?) { /* ... */ }
override fun onDestroy() { /* ... */ }
}

Using Vehicle SDK - Common (3/4)

Initialize the SDK in onCreate().

// package ai.pleos.playground.handson.vehicle.MainActivity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var vehicle: Vehicle


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// TODO 3-3: Using Vehicle SDK - common
vehicle.initialize()

enableEdgeToEdge()
setContent { /* ... */ }
}
override fun onDestroy() { /* ... */ }
}

Using Vehicle SDK - Common (4/4)

Release SDK resources in onDestroy().

// package ai.pleos.playground.handson.vehicle.MainActivity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var vehicle: Vehicle


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

vehicle.initialize()

enableEdgeToEdge()
setContent { /* ... */ }
}

override fun onDestroy() {
super.onDestroy()
// TODO 3-4: Using Vehicle SDK - common
vehicle.release()
}
}

Using Vehicle SDK - Get Steering Wheel Angle API

Call getSteeringWheelAngle() from the ViewModel to fetch the current steering angle.

// package ai.pleos.playground.handson.vehicle.vm.MainViewModel
@HiltViewModel
class MainViewModel @Inject constructor(
private val carPropertyRepository: CarPropertyRepository,
private val vehicleSdkRepository: VehicleSdkRepository,
) : ViewModel() {
/* ... */
// TODO 4: Using Vehicle SDK - Get Steering Wheel Angle API
fun getSteeringWheelAngle() {
vehicleSdkRepository.getSteeringWheelAngle(
onSuccess = { angle ->
Log.d(logTag, "SteeringWheel Angle is $angle")
},
onFailure = { e ->
e.printStackTrace()
}
)
}
// ... 생략
}

Using Vehicle SDK - Callback Steering Wheel Angle API (1/2)

Implement a listener interface to receive callback when the steering wheel angle changes.

// package ai.pleos.playground.handson.vehicle.vm.MainViewModel
@HiltViewModel
class MainViewModel @Inject constructor(
private val carPropertyRepository: CarPropertyRepository,
private val vehicleSdkRepository: VehicleSdkRepository,
) : ViewModel() {
/* ... */
// TODO 5-1: Using Vehicle SDK - Callback Steering Wheel Angle API
private val steeringWheelAngleListener = object : SteeringWheelAngleListener {
override fun onFailed(e: Exception) {
Log.w(logTag, "SteeringWheel Angle onFailed called.", e)
}

override fun onSteeringWheelAngleUpdated(angle: Float?) {
if (angle != null) {
observeSteeringWheelAngle(angle)
}
}
}
// ... 생략
}

Using Vehicle SDK - Callback Steering Wheel Angle API (2/2)

Use a lambda or anonymous object to register the listener.

// package ai.pleos.playground.handson.vehicle.vm.MainViewModel
@HiltViewModel
class MainViewModel @Inject constructor(
private val carPropertyRepository: CarPropertyRepository,
private val vehicleSdkRepository: VehicleSdkRepository,
) : ViewModel() {
private val steeringWheelAngleListener = /* ... */

fun startEvent() {
// ...
// TODO 5-2: Using Vehicle SDK - Callback Steering Wheel Angle API
vehicleSdkRepository.registerSteeringWheelAngle(listener = steeringWheelAngleListener)
}

fun stopEvent() {
// ...
// TODO 5-2: Using Vehicle SDK - Callback Steering Wheel Angle API
vehicleSdkRepository.unregisterSteeringWheelAngle(listener = steeringWheelAngleListener)
}
// ...
}

Step 3. Test the App

  1. Run the sample app from Android Studio.
  2. Use adb commands to simulate vehicle states and test the app behavior.
adb root

adb shell "echo 'propId: {property id} areaId: {area id} values: {value}' > /data/vendor/vsomeip/vhal_fifo"

// array type
adb shell "echo 'propId: {property id} areaId: {area id} values: [{value1},{value2}]' > /data/vendor/vsomeip/vhal_fifo"

// Gear shift (GEAR_SELECTION)
// P (Park)
adb shell "echo 'propId: 289408000 areaId: 0 values: 4' >
/data/vendor/vsomeip/vhal_fifo"

// D (Drive)
adb shell "echo 'propId: 289408000 areaId: 0 values: 8' > /data/vendor/vsomeip/vhal_fifo"
/**
* Note: Speed must be provided in m/s.
* Example: 60km/h = 16.67m/s
* Property: PERF_VEHICLE_SPEED
*/

// Sudden acceleration/deceleration (change of 30 km/h or more)
adb shell "echo 'propId: 291504647 areaId: 0 values: {m/s}' > /data/vendor/vsomeip/vhal_fifo"

/**
* Note: Set value between min and max.
* min_value : -470
* max_value : 500
* Property: PERF_STEERING_ANGLE
*/
// Steering wheel change (must differ 50 degrees or more)
adb shell "echo 'propId: 291504649 areaId: 0 values: {min ~ max}' > /data/vendor/vsomeip/vhal_fifo"

Reference: Google Vehicle Property IDs