Before we dive into code, we should explain the difference between Android Auto and Android Automotive. Android Auto is just a mirroring application that allows to stream features from mobile phone or tablet to the vehicle dashboard. Android Automotive puts a Hardware Abstraction Layer on the vehicle subsystems, which allows gathering car-related data and using it inside Android applications.
Now, let’s move to the development part. Assuming that we already have the SDK containing AA (Android Automotive) packages built from AOSP (Android Open Source Project) sources and the emulator with Car Data options (if not, there is one Linux SDK available to download on my GitLab: https://gitlab.com/filipmg/android-automotive-sdk), we can create a new project (with minimum API level 23) in Android Studio. Make sure to set
a proper SDK in the Project Structure.
In the first step, we need to add a library reference to the module build file:
Then, we need to declare a Car object, which will be responsible for establishing connections and getting specific car managers:
Now we are ready to create our object and establish a connection with the car service. Before we do that, we should perform a check if our system supports the automotive feature. Otherwise, our call to Car API may throw an exception. After this, we can use a static createCar() method provided by Car API, which takes two arguments: context and ServiceConnection object in which we must override two function callbacks. The successful connection establishment will call the first of them, and the connection break will call the latter
Our next step is to set up a car service connection and make our application properly manage it during the activity lifecycle. The best way to achieve this is to invoke proper methods in onResume() and onPause(). Also, we have to make sure that we will not connect or disconnect twice, because an exception may occur:
Great. Now we are ready to test another AA features. Let’s take a look on a list of available sensors in the emulator:
For example, we can try to gather data from the speed sensor. Let’s create a new method called watchSpeedSensor() and initialize CarSensorManager with Car.SENSOR_SERVICE. We should also register a listener to receive sensor data. In our case, we can use a simple logging function:
At this moment our implementation cannot work and cannot be used anywhere. Why? Because each sensor requires it’s own specific permission. We can distinguish some of them:
We have to note that the current version of the emulator does not provide support for many permissions. Let’s use adb to list all that we can use:
Command execution should result with:
For now, we need to get single permission if we want to use a speed sensor. In the first order, we have to add a proper line to our AndroidManifest.xml file:
Then, we must take care of permission checks in our activity code. We can start by creating an array of needed permissions, containing only one of them in our case:
In the next step, we must invoke check and request functions before establishing a connection:
Finally, we are ready to finish our implementation and start watching our sensor in onCarServiceReady(). We must also handle the one specific case when the user accepts permissions by overriding onRequestPermissionsResult():
Of course, permission and sensor logic should be excluded from MainActivity and moved to different classes, but in this particular case, we can keep it here. If we run our application, we may notice that every time we change speed sensor value, our log appears:
Well, that’s all for now. In the future articles, we will go through using multiple sensors and permission management, and we will create a simple reusable skeleton for our Android Automotive applications.
Android Automotive documentation: https://developer.android.com/reference/android/car/classes
Android Automotive description: https://source.android.com/devices/automotive