How to read Car Speed using Car Property in AOSP?

GS Nayma
4 min readNov 23, 2022

--

Android Car APIs allows developers to read the Car Property using Car Property Service. There are many car properties we can read using CarPropertyService.

In this example we will read Car Speed.

Steps to follow:

  1. Create a module/project in AOSP (you can use your own path to create module. In this case I am using vendor/gs/CarSpeedDemo)
creating a module/project CarSpeedDemo in AOSP

2. Create a new file Android.bp file in CarSpeedDemo module and add below content to this file.

Note: you can create new file by using command touch Android.bp

android_app {

name: "CarSpeedDemo",

srcs: [
"src/**/*.java",
],

resource_dirs: ["res"],

manifest: "AndroidManifest.xml",
libs: [
"android.car", // this lib will provide Car APIs
],
static_libs: [
"androidx-constraintlayout_constraintlayout-solver",
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"com.google.android.material_material",
],

platform_apis: true,
privileged: true,
certificate: "platform",

optimize: {
enabled: false,
},

}

3. Create folder src and res in CarSpeedDemo

creating src and res directory

4. Create an AndroidManifest.xml file in CarSpeedDemo

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.CarSpeedDemo"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

4. Create sub directory mipmap and values in res directory

add you app logo (image) into mipmap directory and rename the image file to “ic_launcher” (ic_launcher.png)

5. Create a strings.xml file in values directory

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CarSpeedDemo</string>
</resources>

6. Create a colors.xml file in values directory

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

7. Create a themes.xml file in values directory

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.CarSpeedDemo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

8. Create package in src directory (com/gs/carspeeddemo)

9. Create a sub directory layout in res and add file activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/tv_speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="40sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

10. Create an Activity class e.g MainActivity.java

package com.gs.carspeeddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.car.Car;
import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();
private TextView mTvSpeed;
private Car mCar;
String[] perms = {"android.car.permission.CAR_SPEED"};
int permsRequestCode = 200;
CarPropertyManager mCarPropertyManager;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mTvSpeed = findViewById(R.id.tv_speed);
requestPermissions(perms, permsRequestCode);

}

CarPropertyManager.CarPropertyEventCallback mCallBack = new CarPropertyManager.CarPropertyEventCallback() {
@Override
public void onChangeEvent(CarPropertyValue carPropertyValue) {
Log.d(TAG, "onChangeEvent: " + carPropertyValue.toString());
if (carPropertyValue.getPropertyId() == VehiclePropertyIds.PERF_VEHICLE_SPEED) {
float value = (Float) carPropertyValue.getValue();
mTvSpeed.setText("Speed: " + Math.round(value));
}
}

@Override
public void onErrorEvent(int i, int i1) {
Log.e(TAG, "onErrorEvent: " + i);
}
};

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
Log.d(TAG, "onRequestPermissionsResult: called");

super.onRequestPermissionsResult(permsRequestCode, permissions, grantResults);
switch (permsRequestCode) {
case 200:
Log.d(TAG, "onRequestPermissionsResult: " + permsRequestCode);
boolean carPermission = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (carPermission) {
mCar = Car.createCar(this);
mCarPropertyManager = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
mCarPropertyManager.registerCallback(mCallBack, VehiclePropertyIds.PERF_VEHICLE_SPEED, CarPropertyManager.SENSOR_RATE_NORMAL);

Log.d(TAG, "onRequestPermissionsResult: isConnected " + mCar.isConnected());
} else {
requestPermissions(perms, permsRequestCode);
}
break;
default:
Log.d(TAG, "onRequestPermissionsResult: default " + permsRequestCode);
break;
}
}

@Override
protected void onStop() {
super.onStop();
mCar.disconnect();
}
}

11. Add Car Speed permission in AndroidManifest.xml

<uses-permission android:name="android.car.permission.CAR_SPEED"/>

12. Add your module into car.mk file in device/generic/car/common/car.mk file. (for different vendor path might be different)

car.mk file

13. run the mm command in the module CarSpeedDemo

Build success
App Demo

--

--

GS Nayma

A passionate Android App & Framework Developer with 7+ years of experience in Android and AOSP. I have exposure to System Apps, System Service etc.