Develop Android Auto App using Android Studio

After serving several years of Android OS into mobile phones, Google launches Android platform for vehicles named Android Auto. While driving a car it is a difficult task to get connected with friends and family especially when it is urgent to inform about the meeting plan and so on.

android-auto-tutorial-mobilesiri

By: Ambreen Altaf Hussain

Android Auto

Android Auto provides great experiences into your car devices such as Voice reply of your text messages without losing concentration from the road. It provides Car-Optimized Android User Interface which is quite easy to interact with Voice Actions and Touchscreen.
Android Auto launches with support of two types of applications.
Audio Apps
Messaging Apps
You can create a new application or can modify your existing messaging or audio application to run into cars.
Let’s get start with creating an application for android auto:
Note: Install v4 support library that is required to create notifications compatible for android auto devices.

androidauto

Declaring Auto Capabilities:
The features that your automotive app is going to support should be declared in an XML Configuration file and make a reference of that file in your app’s manifest by adding these lines.

<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />

Now, Create an XML file named “automotive_app_desc” under res/XML directory and declare the feature you want to access in your Android auto, basically there are two features
Media – Used for media elements and auto playback.
Notifications – Used for notifications and auto messaging.

Declare the feature you want to use in automotive_app_desc

<automotiveApp>
<uses name="notification" />
</automotiveApp>

You need to add a MessageReplyReciever for replying from you android auto. Add by right click on project new Others BroadCast Reciever.
android-auto-tutorial-mobilesiri-3
Register this activity in your android’s manifest by adding these lines

<receiver android:name=".MessageReplyReceiver">
<intent-filter>
<action android:name="com.mobilesiri.androidauto.ACTION_MESSAGE_REPLY" />
</intent-filter>
</receiver>

Now, when you have added a Replying Service you have to add also a Read Service which extends Broadcast Receiver.
Also register this activity into app’s manifest. Now your manifest should look like this.
Androidmanifest.xml:

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

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

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

<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />

<service android:name=".MyMessagingService" />

<receiver android:name=".MessageReadReceiver">
<intent-filter>
<action android:name="com.mobilesiri.androidauto.ACTION_MESSAGE_READ" />
</intent-filter>
</receiver>
<receiver android:name=".MessageReplyReceiver">
<intent-filter>
<action android:name="com.mobilesiri.androidauto.ACTION_MESSAGE_REPLY" />
</intent-filter>
</receiver>
</application>

</manifest>

Let’s move towards the coding.
Now first step is to create the intent and pendingintent for which will be triggered when the messages heard and replied to the participant

int conversation_id = 42;
private Intent createIntent(int conversationId, String action) {
return new Intent()
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setAction(REPLY_ACTION)
.putExtra("CONVERSATION_ID", conversation_id);
}

setAction method will take the action parameter you declared in the intent-filter in app’s manifest whereas conversation_id connects the participant to the user.
Now declare the pending intent for read and reply separately.
PendingIntent For Read:

PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversation_id,
createIntent(conversation_id, READ_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);

PendingIntent For Write:

PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversation_id,
createIntent(conversation_id, REPLY_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);

Build a RemoteInput for receiving voice input in a Car Notification

RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel("Reply by voice")
.build();

Create the Unread Conversation and populate it with the participant name,read and reply intents.

UnreadConversation.Builder unreadConvBuilder =
new UnreadConversation.Builder(participant)
.setLatestTimestamp(timestamp)
.setReadPendingIntent(readPendingIntent)
.setReplyAction(replyIntent, remoteInput);

Create the NotificationCompat Builder to show notifications on android auto.

NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
.setContentText(message)
.setWhen(timestamp)
.setContentTitle(participant)
.setContentIntent(readPendingIntent)
.extend(new CarExtender().setUnreadConversation(unreadConvBuilder.build()));
mNotificationManager.notify(conversation_id, builder.build());

CarExtender Constructor is used to extend regular notifications into Android Auto notifications.
.extend(new CarExtender().setUnreadConversation(unreadConvBuilder.build());
Now, lets’s have a look at complete code:

MessageReadReceiver.java:

package com.mobilesiri.androidauto;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;

public class MessageReadReceiver extends BroadcastReceiver {
private static final String TAG = MessageReadReceiver.class.getSimpleName();

@Override
public void onReceive(Context context, Intent intent) {
if (MyMessagingService.READ_ACTION.equals(intent.getAction())) {
int conversationId = intent.getIntExtra(MyMessagingService.CONVERSATION_ID, -1);
if (conversationId != -1) {
Log.d(TAG, "Conversation " + conversationId + " was read");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(conversationId);
}
}
}
}

MessageReplyReceiver.java:

package com.mobilesiri.androidauto;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.RemoteInput;
import android.util.Log;
public class MessageReplyReceiver extends BroadcastReceiver {

private static final String TAG = MessageReplyReceiver.class.getSimpleName();

@Override
public void onReceive(Context context, Intent intent) {
if (MyMessagingService.REPLY_ACTION.equals(intent.getAction())) {
int conversationId = intent.getIntExtra(MyMessagingService.CONVERSATION_ID, -1);
CharSequence reply = getMessageText(intent);
Log.d(TAG, "Got reply (" + reply + ") for ConversationId " + conversationId);
}
}

private CharSequence getMessageText(Intent intent) {

Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(MyMessagingService.EXTRA_VOICE_REPLY);
}
return null;
}
}

MainActivity.java:

package com.mobilesiri.androidauto;

import android.app.PendingIntent;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
public static final String READ_ACTION =
"com.mobilesiri.androidauto.ACTION_MESSAGE_READ";
public static final String REPLY_ACTION =
"com.mobilesiri.androidauto.ACTION_MESSAGE_REPLY";
public static final String CONVERSATION_ID = "conversation_id";
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
private static final String TAG = MyMessagingService.class.getSimpleName();
final Messenger mMessenger = new Messenger(new IncomingHandler());
private NotificationManagerCompat mNotificationManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNotificationManager = NotificationManagerCompat.from(getApplicationContext());
}

public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
int conversation_id = 42;
private Intent createIntent(int conversationId, String action) {
return new Intent()
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setAction(REPLY_ACTION)
.putExtra("CONVERSATION_ID", conversation_id);
}
private void sendNotification(int conversationId, String message,
String participant, long timestamp) {
PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversation_id,
createIntent(conversation_id, READ_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel("Reply by voice")
.build();
PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversation_id,
createIntent(conversation_id, REPLY_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.CarExtender.UnreadConversation.Builder unreadConvBuilder =
new NotificationCompat.CarExtender.UnreadConversation.Builder(participant)
.setLatestTimestamp(timestamp)
.setReadPendingIntent(readPendingIntent)
.setReplyAction(replyIntent, remoteInput);

NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
.setContentText(message)
.setWhen(timestamp)
.setContentTitle(participant)
.setContentIntent(readPendingIntent)
.extend(new NotificationCompat.CarExtender().setUnreadConversation(unreadConvBuilder.build()));

mNotificationManager.notify(conversation_id, builder.build());
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
sendNotification(1, "Hello! How are you?", "Ambreen Altaf",
System.currentTimeMillis());
}
}
}

Test Your Application on Emulator:

It’s not necessary that you should have a car device to test your application. You can run it on your emulator by installing Android Auto API from the SDK manager. When you have done with installation check your sdk extras google simulators, you will get two apk’s one for media browsing and second one is for messaging-simulator. Now you have to install this apk into your emulator for this copy messaging-simulator.apk into sdkplatform-tools. Now run command prompt here and type these command

android-auto-tutorial-mobilesiri-4

Run messaging simulator in your emulator, it will ask you for the notification enabling.


android-auto-tutorial-mobilesiri-5

android-auto-tutorial-mobilesiri-6

MobileSiri.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com. Read about our Affiliates Disclosure Policy here.

Read More:  Develop your first android app using Android Studio!