This is an unofficial SDK for Android Auto.
With great power comes great responsibility. Do not write apps that distract drivers. Distraction is dangerous.
Have a look at these example apps:
Add this to your main build.gradle:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
and this to your app's build.gradle:
dependencies {
compile 'com.github.martoreto:aauto-sdk:v4.0'
}
and this to your AndroidManifest.xml inside <application>
:
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
and save this as res/xml/automotive_app_desc.xml:
<?xml version="1.0" encoding="utf-8"?>
<automotiveApp xmlns:tools="http://schemas.android.com/tools">
<uses name="service" tools:ignore="InvalidUsesTagAttribute" />
<uses name="projection" tools:ignore="InvalidUsesTagAttribute" />
<uses name="notification" />
</automotiveApp>
There are no docs, but you can explore the API in Android Studio after switching to the Package view:
Then have a look in the following places under Libraries:
com.google.android.apps.auto.sdk
android.support.car
values/color.xml
values/dimens.xml
values/styles.xml
Actually, some version of android.support.car
is open source and has docs in code.
A new OEM activity looks like this in AndroidMainfest.xml:
<service
android:name=".CarService"
android:label="@string/car_service_name"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.google.android.gms.car.category.CATEGORY_PROJECTION" />
<category android:name="com.google.android.gms.car.category.CATEGORY_PROJECTION_OEM" />
</intent-filter>
</service>
Testing OEM apps with the Android SDK and a virtual headunit on a computer is straight-forward, follow Testing Apps for Auto. Summary:
- Install Android Auto Desktop Head Unit (DHU) from Android SDK manager
- Connect phone to computer
- Run /sdk/platform-tools/adb forward tcp:5277 tcp:5277
- Run /sdk/extras/google/auto/desktop-head-unit.exe
For running apps on your phone in an actual vehicle, it is required to adjust the settings of Android Auto to allow apps from unknown sources. To do so, follow these steps:
- Disconnect phone from car
- Start Android Auto on your phone
- Go to Hamburger Menu -> About
- Tap the title "About Android Auto" 10 times to activate developer options
- Go to three dots menu (top right) and go to "Developer settings"
- Scroll down and activate "Unkown sources"
Here's some example code for reading sensor data provided by car.
This can be used in an Android Auto activity, or a background service.
Some documentation: CarSensorManager.java
import android.support.car.Car;
import android.support.car.CarConnectionCallback;
import android.support.car.hardware.CarSensorEvent;
import android.support.car.hardware.CarSensorManager;
@Override
public void onStart() {
mCar = Car.createCar(this, mCarConnectionCallback);
mCar.connect();
}
@Override
public void onStop() {
try {
mCar.disconnect();
} catch (Exception e) {
Log.w(TAG, "Error disconnecting from car", e);
}
}
private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
@Override
public void onConnected(Car car) {
try {
Log.d(TAG, "Connected to car");
CarSensorManager sensorManager = (CarSensorManager) car.getCarManager(Car.SENSOR_SERVICE);
//Get supported sensor types:
int[] supportedSensors = sensorManager.getSupportedSensors();
for(int sensorId : supportedSensors){
Log.d(TAG, "Supported sensor id: "+sensorId);
sensorManager.addListener(mSensorsListener, sensorId, CarSensorManager.SENSOR_RATE_NORMAL);
}
} catch (Exception e) {
Log.w(TAG, "Error setting up car connection", e);
}
}
@Override
public void onDisconnected(Car car) {
Log.d(TAG, "Disconnected from car");
}
};
private final CarSensorManager.OnSensorChangedListener mSensorsListener = new CarSensorManager.OnSensorChangedListener() {
@Override
public void onSensorChanged(CarSensorManager sensorManager, CarSensorEvent ev) {
switch (ev.sensorType){
case CarSensorManager.SENSOR_TYPE_NIGHT:
Log.d(TAG, "isNightMode " + ev.getNightData().isNightMode);
break;
case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS:
CarSensorEvent.DrivingStatusData ds = ev.getDrivingStatusData();
Log.d(TAG, "videoRestricted: " + ds.isVideoRestricted() + ", fullyRestricted:" + ds.isFullyRestricted());
break;
default:
Log.d(TAG, "Unhandled " + ev.sensorType);
//Include it in the switch-case statement
break;
}
}
};
Android Auto protocol defines another communication method between the car and an app running on the phone, called vendor channel. It's basically a byte channel.
The protocol inside is vendor-specific:
- Volkswagen Group uses Exlap
- Ford Performance vehicles use an unknown protocol
Example use:
CarVendorExtensionManagerLoader vexLoader =
(CarVendorExtensionManagerLoader)mCar.getCarManager(
CarVendorExtensionManagerLoader.VENDOR_EXTENSION_LOADER_SERVICE);
mVexManager = vexLoader.getManager(getVendorChannelName());
if (mVexManager == null) {
throw new RuntimeException("Vendor channel not available");
}
mVexManager.registerListener(new CarVendorExtensionManager.CarVendorExtensionListener() {
@Override
public void onData(CarVendorExtensionManager carVendorExtensionManager, byte[] bytes) {
// Do something with data
}
});
mVexManager.sendData(new byte[] { (byte) 1, (byte) 2, (byte) 3 });
In order to use the vendor channel:
-
the package name of the application must be on the list provided by the car (use this app to see the list),
-
the app must have
<uses-permission android:name="com.google.android.gms.permission.CAR_VENDOR_EXTENSION"/>
in its AndroidManifest.xml (and granted at runtime on Marshmallow or later).
Usually, there's no need to build the SDK yourself. If you have a need, please share it by contributing pull requests. :)
To build the SDK yourself:
-
Set
ANDROID_HOME
enviroment variable to point to the Android SDK folder. -
Do this:
./gradlew build
The result is build/aauto.aar
.