Apps, die Messaging unterstützen, können ihre Messaging-Benachrichtigungen so erweitern, dass sie von Android Auto verwendet werden können, wenn Auto ausgeführt wird. Diese Benachrichtigungen werden in Auto angezeigt und ermöglichen es Nutzern, Nachrichten in einer einheitlichen, ablenkungsarmen Benutzeroberfläche zu lesen und darauf zu antworten. Wenn Sie die MessagingStyle API verwenden, erhalten Sie optimierte Benachrichtigungen für alle Android-Geräte, einschließlich Android Auto. Die Optimierungen umfassen eine Benutzeroberfläche, die speziell für Benachrichtigungen über Nachrichten entwickelt wurde, verbesserte Animationen und Unterstützung für Inline-Bilder.
In dieser Anleitung erfahren Sie, wie Sie eine App, die dem Nutzer Nachrichten anzeigt und seine Antworten empfängt, z. B. eine Chat-App, so erweitern, dass die Nachrichtenanzeige und der Empfang von Antworten an ein Auto-Gerät übergeben werden. Durch diese Integration können Nutzer nur den Nachrichtenverlauf von Benachrichtigungen sehen, die sie während ihrer aktiven Android Auto-Sitzung erhalten haben. Wenn Sie Nachrichten anzeigen möchten, die vor Beginn der aktiven Android Auto-Sitzung gesendet wurden, können Sie eine Messaging-Funktion mit Vorlagen erstellen.
Weitere Informationen zum Design finden Sie auf der Website „Design for Driving“ unter Messaging apps.
Erste Schritte
Wenn Ihre App einen Messaging-Dienst für Auto-Geräte bereitstellen soll, müssen Sie im Manifest die Unterstützung von Android Auto deklarieren und die folgenden Anforderungen erfüllen:
NotificationCompat.MessagingStyle
-Objekte erstellen und senden, dieAction
-Objekte für Antworten und „Als gelesen markieren“ enthalten.- Antworten und das Markieren einer Unterhaltung als gelesen mit einem
Service
verarbeiten.
Konzepte und Objekte
Bevor Sie mit dem Design Ihrer App beginnen, sollten Sie wissen, wie Android Auto Nachrichten verarbeitet.
Ein einzelner Kommunikationsabschnitt wird als Nachricht bezeichnet und durch die Klasse MessagingStyle.Message
dargestellt. Eine Nachricht enthält einen Absender, den Inhalt der Nachricht und den Zeitpunkt, zu dem die Nachricht gesendet wurde.
Die Kommunikation zwischen Nutzern wird als Unterhaltung bezeichnet und durch ein MessagingStyle
-Objekt dargestellt. Eine Unterhaltung oder MessagingStyle
enthält einen Titel, die Nachrichten und Informationen dazu, ob es sich um eine Gruppenunterhaltung handelt.
Um Nutzer über Aktualisierungen einer Unterhaltung, z. B. eine neue Nachricht, zu informieren, senden Apps eine Notification
an das Android-System.
Diese Notification
verwendet das MessagingStyle
-Objekt, um messaging-spezifische UI im Benachrichtigungsfeld anzuzeigen. Die Android-Plattform übergibt diese Notification
auch an Android Auto. Die MessagingStyle
wird extrahiert und verwendet, um eine Benachrichtigung auf dem Display des Autos zu posten.
Android Auto erfordert außerdem, dass Apps Action
-Objekte zu einem Notification
hinzufügen, damit der Nutzer direkt über die Benachrichtigungsleiste schnell auf eine Nachricht antworten oder sie als gelesen markieren kann.
Zusammenfassend lässt sich sagen, dass eine einzelne Unterhaltung durch ein Notification
-Objekt dargestellt wird, das mit einem MessagingStyle
-Objekt formatiert ist. Das MessagingStyle
enthält alle Nachrichten in der Unterhaltung in einem oder mehreren MessagingStyle.Message
-Objekten. Damit eine App mit Android Auto kompatibel ist, müssen der Notification
die Objekte „Antworten“ und „Als gelesen markieren“ Action
angehängt werden.
Messaging-Ablauf
In diesem Abschnitt wird ein typischer Nachrichtenfluss zwischen Ihrer App und Android Auto beschrieben.
- Ihre App erhält eine Nachricht.
- Ihre App generiert eine
MessagingStyle
-Benachrichtigung mit den ObjektenAction
für Antworten und als gelesen markieren. - Android Auto empfängt das Ereignis „Neue Benachrichtigung“ vom Android-System und findet die
MessagingStyle
, die AntwortAction
und die Markierung als gelesenAction
. - Android Auto generiert und zeigt eine Benachrichtigung im Auto an.
- Wenn der Nutzer auf dem Display des Autos auf die Benachrichtigung tippt, löst Android Auto das Markieren als gelesen
Action
aus.- Ihre App muss dieses Ereignis im Hintergrund verarbeiten.
- Wenn der Nutzer per Sprache auf die Benachrichtigung antwortet, fügt Android Auto eine Transkription der Antwort des Nutzers in die Antwort
Action
ein und löst sie dann aus.- Im Hintergrund muss Ihre App dieses Antwort-Ereignis verarbeiten.
Vorläufige Annahmen
Auf dieser Seite wird nicht beschrieben, wie Sie eine vollständige Messaging-App erstellen. Das folgende Codebeispiel enthält einige der Dinge, die Ihre App benötigt, bevor Sie Messaging mit Android Auto unterstützen können:
data class YourAppConversation(
val id: Int,
val title: String,
val recipients: MutableList<YourAppUser>,
val icon: Bitmap) {
companion object {
/** Fetches [YourAppConversation] by its [id]. */
fun getById(id: Int): YourAppConversation = // ...
}
/** Replies to this conversation with the given [message]. */
fun reply(message: String) {}
/** Marks this conversation as read. */
fun markAsRead() {}
/** Retrieves all unread messages from this conversation. */
fun getUnreadMessages(): List<YourAppMessage> { return /* ... */ }
}
data class YourAppUser(val id: Int, val name: String, val icon: Uri)
data class YourAppMessage(
val id: Int,
val sender: YourAppUser,
val body: String,
val timeReceived: Long)
Android Auto-Unterstützung deklarieren
Wenn Android Auto eine Benachrichtigung von einer Messaging-App erhält, wird geprüft, ob die App die Unterstützung von Android Auto deklariert hat. Um diese Unterstützung zu aktivieren, fügen Sie den folgenden Eintrag in das Manifest Ihrer App ein:
<application>
...
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Dieser Manifesteintrag verweist auf eine andere XML-Datei, die Sie mit dem folgenden Pfad erstellen müssen: YourAppProject/app/src/main/res/xml/automotive_app_desc.xml
.
Deklariere in automotive_app_desc.xml
die Android Auto-Funktionen, die deine App unterstützt. Wenn Sie beispielsweise Unterstützung für Benachrichtigungen deklarieren möchten, fügen Sie Folgendes ein:
<automotiveApp>
<uses name="notification" />
</automotiveApp>
Wenn Ihre App als Standard-SMS-Handler festgelegt werden kann, müssen Sie das folgende <uses>
-Element einfügen. Andernfalls wird ein in Android Auto integrierter Standard-Handler verwendet, um eingehende SMS/MMS-Nachrichten zu verarbeiten, wenn Ihre App als Standard-SMS-Handler festgelegt ist. Dies kann zu doppelten Benachrichtigungen führen.
<automotiveApp>
...
<uses name="sms" />
</automotiveApp>
AndroidX-Kernbibliothek importieren
Für die Entwicklung von Benachrichtigungen für die Verwendung mit Auto-Geräten ist die AndroidX-Kernbibliothek erforderlich. Importieren Sie die Bibliothek so in Ihr Projekt:
- Fügen Sie in der
build.gradle
-Datei auf oberster Ebene eine Abhängigkeit vom Maven-Repository von Google ein, wie im folgenden Beispiel gezeigt:
Groovy
allprojects { repositories { google() } }
Kotlin
allprojects { repositories { google() } }
- Fügen Sie in die
build.gradle
-Datei Ihres App-Moduls die Abhängigkeit der AndroidX Core-Bibliothek ein, wie im folgenden Beispiel gezeigt:
Groovy
dependencies { // If your app is written in Java implementation 'androidx.core:core:1.17.0' // If your app is written in Kotlin implementation 'androidx.core:core-ktx:1.17.0' }
Kotlin
dependencies { // If your app is written in Java implementation("androidx.core:core:1.17.0") // If your app is written in Kotlin implementation("androidx.core:core-ktx:1.17.0") }
Nutzeraktionen verarbeiten
Ihre Messaging-App muss eine Möglichkeit haben, eine Unterhaltung über eine Action
zu aktualisieren. Für Android Auto gibt es zwei Arten von Action
-Objekten, die Ihre App verarbeiten muss: „reply“ (Antworten) und „mark-as-read“ (Als gelesen markieren). Wir empfehlen, sie mit einem IntentService
zu verarbeiten, da so potenziell teure Aufrufe im Hintergrund ausgeführt werden können, wodurch der Hauptthread Ihrer App entlastet wird.
Intent-Aktionen definieren
Intent
-Aktionen sind einfache Strings, die angeben, wofür die Intent
verwendet wird.
Da ein einzelner Dienst mehrere Arten von Intents verarbeiten kann, ist es einfacher, mehrere Aktionsstrings zu definieren, anstatt mehrere IntentService
-Komponenten zu definieren.
Die Beispiel-Messaging-App in diesem Leitfaden hat die beiden erforderlichen Arten von Aktionen: „Antworten“ und „Als gelesen markieren“, wie im folgenden Codebeispiel gezeigt.
private const val ACTION_REPLY = "com.example.REPLY"
private const val ACTION_MARK_AS_READ = "com.example.MARK_AS_READ"
Dienst erstellen
Wenn Sie einen Dienst erstellen möchten, der diese Action
-Objekte verarbeitet, benötigen Sie die Konversations-ID. Das ist eine beliebige Datenstruktur, die von Ihrer App definiert wird und die Konversation identifiziert. Außerdem benötigen Sie eine Remote-Eingabetaste, die später in diesem Abschnitt ausführlich beschrieben wird. Im folgenden Codebeispiel wird ein Dienst erstellt, der die erforderlichen Aktionen ausführt:
private const val EXTRA_CONVERSATION_ID_KEY = "conversation_id"
private const val REMOTE_INPUT_RESULT_KEY = "reply_input"
/**
* An [IntentService] that handles reply and mark-as-read actions for
* [YourAppConversation]s.
*/
class MessagingService : IntentService("MessagingService") {
override fun onHandleIntent(intent: Intent?) {
// Fetches internal data.
val conversationId = intent!!.getIntExtra(EXTRA_CONVERSATION_ID_KEY, -1)
// Searches the database for that conversation.
val conversation = YourAppConversation.getById(conversationId)
// Handles the action that was requested in the intent. The TODOs
// are addressed in a later section.
when (intent.action) {
ACTION_REPLY -> TODO()
ACTION_MARK_AS_READ -> TODO()
}
}
}
Damit Sie diesen Dienst mit Ihrer App verknüpfen können, müssen Sie ihn auch im Manifest Ihrer App registrieren, wie im folgenden Beispiel gezeigt:
<application>
<service android:name="com.example.MessagingService" />
...
</application>
Intents generieren und verarbeiten
Andere Apps, einschließlich Android Auto, können die Intent
, die den MessagingService
auslöst, nicht abrufen, da Intent
über einen PendingIntent
an andere Apps übergeben werden. Aufgrund dieser Einschränkung müssen Sie ein RemoteInput
-Objekt erstellen, damit andere Apps den Antworttext an Ihre App zurückgeben können, wie im folgenden Beispiel gezeigt:
/**
* Creates a [RemoteInput] that lets remote apps provide a response string
* to the underlying [Intent] within a [PendingIntent].
*/
fun createReplyRemoteInput(context: Context): RemoteInput {
// RemoteInput.Builder accepts a single parameter: the key to use to store
// the response in.
return RemoteInput.Builder(REMOTE_INPUT_RESULT_KEY).build()
// Note that the RemoteInput has no knowledge of the conversation. This is
// because the data for the RemoteInput is bound to the reply Intent using
// static methods in the RemoteInput class.
}
/** Creates an [Intent] that handles replying to the given [appConversation]. */
fun createReplyIntent(
context: Context, appConversation: YourAppConversation): Intent {
// Creates the intent backed by the MessagingService.
val intent = Intent(context, MessagingService::class.java)
// Lets the MessagingService know this is a reply request.
intent.action = ACTION_REPLY
// Provides the ID of the conversation that the reply applies to.
intent.putExtra(EXTRA_CONVERSATION_ID_KEY, appConversation.id)
return intent
}
Extrahieren Sie in der ACTION_REPLY
-Switch-Klausel innerhalb von MessagingService
die Informationen, die in die Antwort Intent
einfließen, wie im folgenden Beispiel gezeigt:
ACTION_REPLY -> {
// Extracts reply response from the intent using the same key that the
// RemoteInput uses.
val results: Bundle = RemoteInput.getResultsFromIntent(intent)
val message = results.getString(REMOTE_INPUT_RESULT_KEY)
// This conversation object comes from the MessagingService.
conversation.reply(message)
}
Die Markierung als gelesen Intent
wird auf ähnliche Weise behandelt. Es ist jedoch kein RemoteInput
erforderlich, wie im folgenden Beispiel gezeigt:
/** Creates an [Intent] that handles marking the [appConversation] as read. */
fun createMarkAsReadIntent(
context: Context, appConversation: YourAppConversation): Intent {
val intent = Intent(context, MessagingService::class.java)
intent.action = ACTION_MARK_AS_READ
intent.putExtra(EXTRA_CONVERSATION_ID_KEY, appConversation.id)
return intent
}
Die ACTION_MARK_AS_READ
-Switch-Klausel in MessagingService
erfordert keine weitere Logik, wie im folgenden Beispiel gezeigt:
// Marking as read has no other logic.
ACTION_MARK_AS_READ -> conversation.markAsRead()
Nutzer über Mitteilungen benachrichtigen
Nachdem die Verarbeitung der Unterhaltungsaktion abgeschlossen ist, müssen Android Auto-kompatible Benachrichtigungen generiert werden.
Aktionen erstellen
Action
-Objekte können über einen Notification
an andere Apps übergeben werden, um Methoden in der ursprünglichen App auszulösen. So kann Android Auto eine Unterhaltung als gelesen markieren oder darauf antworten.
Um eine Action
zu erstellen, beginnen Sie mit einer Intent
. Das folgende Beispiel zeigt, wie Sie ein Intent
vom Typ „reply“ erstellen:
fun createReplyAction(
context: Context, appConversation: YourAppConversation): Action {
val replyIntent: Intent = createReplyIntent(context, appConversation)
// ...
Schließen Sie dann diesen Intent
in ein PendingIntent
ein, um ihn für die externe App-Nutzung vorzubereiten. Ein PendingIntent
schränkt den Zugriff auf das umschlossene Intent
ein, indem nur eine ausgewählte Gruppe von Methoden verfügbar gemacht wird, mit denen die empfangende App das Intent
auslösen oder den Paketnamen der ursprünglichen App abrufen kann. Die externe App kann niemals auf die zugrunde liegende Intent
oder die darin enthaltenen Daten zugreifen.
// ...
val replyPendingIntent = PendingIntent.getService(
context,
createReplyId(appConversation), // Method explained later.
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
// ...
Bevor Sie die Antwort Action
einrichten, sollten Sie sich mit den drei Anforderungen von Android Auto an die Antwort Action
vertraut machen:
- Die semantische Aktion muss auf
Action.SEMANTIC_ACTION_REPLY
festgelegt sein. - Die
Action
muss angeben, dass beim Auslösen keine Benutzeroberfläche angezeigt wird. Action
muss ein einzelnesRemoteInput
-Element enthalten.
Im folgenden Codebeispiel wird eine Antwort Action
eingerichtet, die die oben aufgeführten Anforderungen erfüllt:
// ...
val replyAction = Action.Builder(R.drawable.reply, "Reply", replyPendingIntent)
// Provides context to what firing the Action does.
.setSemanticAction(Action.SEMANTIC_ACTION_REPLY)
// The action doesn't show any UI, as required by Android Auto.
.setShowsUserInterface(false)
// Don't forget the reply RemoteInput. Android Auto will use this to
// make a system call that will add the response string into
// the reply intent so it can be extracted by the messaging app.
.addRemoteInput(createReplyRemoteInput(context))
.build()
return replyAction
}
Die Verarbeitung der Aktion „Als gelesen markieren“ ist ähnlich, nur dass es kein RemoteInput
gibt.
Daher gelten für die Funktion „Als gelesen markieren“ Action
in Android Auto zwei Anforderungen:
- Die semantische Aktion ist auf
Action.SEMANTIC_ACTION_MARK_AS_READ
festgelegt. - Die Aktion gibt an, dass beim Auslösen keine Benutzeroberfläche angezeigt wird.
Im folgenden Codebeispiel wird ein Action
für „Als gelesen markieren“ eingerichtet, das diese Anforderungen erfüllt:
fun createMarkAsReadAction(
context: Context, appConversation: YourAppConversation): Action {
val markAsReadIntent = createMarkAsReadIntent(context, appConversation)
val markAsReadPendingIntent = PendingIntent.getService(
context,
createMarkAsReadId(appConversation), // Method explained below.
markAsReadIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
val markAsReadAction = Action.Builder(
R.drawable.mark_as_read, "Mark as Read", markAsReadPendingIntent)
.setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ)
.setShowsUserInterface(false)
.build()
return markAsReadAction
}
Beim Generieren der ausstehenden Intents werden zwei Methoden verwendet: createReplyId()
und createMarkAsReadId()
. Diese Methoden dienen als Anforderungscodes für die einzelnen PendingIntent
, die von Android verwendet werden, um vorhandene ausstehende Intents zu steuern. Die create()
-Methoden müssen für jede Unterhaltung eindeutige IDs zurückgeben. Bei wiederholten Aufrufen für dieselbe Unterhaltung muss jedoch die bereits generierte eindeutige ID zurückgegeben werden.
Betrachten wir ein Beispiel mit zwei Unterhaltungen, A und B: Die Antwort-ID von Unterhaltung A ist 100 und die ID für „Als gelesen markieren“ ist 101. Die Antwort-ID von Unterhaltung B ist 102 und die ID für „Als gelesen markieren“ ist 103. Wenn Konversation A aktualisiert wird, sind die IDs für „Antworten“ und „Als gelesen markieren“ weiterhin 100 und 101. Weitere Informationen finden Sie unter PendingIntent.FLAG_UPDATE_CURRENT
.
MessagingStyle erstellen
MessagingStyle
ist der Träger der Messaging-Informationen und wird von Android Auto verwendet, um jede Nachricht in einer Unterhaltung vorzulesen.
Zuerst muss der Nutzer des Geräts in Form eines Person
-Objekts angegeben werden, wie im folgenden Beispiel gezeigt:
fun createMessagingStyle(
context: Context, appConversation: YourAppConversation): MessagingStyle {
// Method defined by the messaging app.
val appDeviceUser: YourAppUser = getAppDeviceUser()
val devicePerson = Person.Builder()
// The display name (also the name that's read aloud in Android auto).
.setName(appDeviceUser.name)
// The icon to show in the notification shade in the system UI (outside
// of Android Auto).
.setIcon(appDeviceUser.icon)
// A unique key in case there are multiple people in this conversation with
// the same name.
.setKey(appDeviceUser.id)
.build()
// ...
Anschließend können Sie das MessagingStyle
-Objekt erstellen und einige Details zum Gespräch angeben.
// ...
val messagingStyle = MessagingStyle(devicePerson)
// Sets the conversation title. If the app's target version is lower
// than P, this will automatically mark the conversation as a group (to
// maintain backward compatibility). Use `setGroupConversation` after
// setting the conversation title to explicitly override this behavior. See
// the documentation for more information.
messagingStyle.setConversationTitle(appConversation.title)
// Group conversation means there is more than 1 recipient, so set it as such.
messagingStyle.setGroupConversation(appConversation.recipients.size > 1)
// ...
Fügen Sie zum Schluss die ungelesenen Nachrichten hinzu.
// ...
for (appMessage in appConversation.getUnreadMessages()) {
// The sender is also represented using a Person object.
val senderPerson = Person.Builder()
.setName(appMessage.sender.name)
.setIcon(appMessage.sender.icon)
.setKey(appMessage.sender.id)
.build()
// Adds the message. More complex messages, like images,
// can be created and added by instantiating the MessagingStyle.Message
// class directly. See documentation for details.
messagingStyle.addMessage(
appMessage.body, appMessage.timeReceived, senderPerson)
}
return messagingStyle
}
Benachrichtigung verpacken und senden
Nachdem Sie die Action
- und MessagingStyle
-Objekte generiert haben, können Sie die Notification
erstellen und posten.
fun notify(context: Context, appConversation: YourAppConversation) {
// Creates the actions and MessagingStyle.
val replyAction = createReplyAction(context, appConversation)
val markAsReadAction = createMarkAsReadAction(context, appConversation)
val messagingStyle = createMessagingStyle(context, appConversation)
// Creates the notification.
val notification = NotificationCompat.Builder(context, channel)
// A required field for the Android UI.
.setSmallIcon(R.drawable.notification_icon)
// Shows in Android Auto as the conversation image.
.setLargeIcon(appConversation.icon)
// Adds MessagingStyle.
.setStyle(messagingStyle)
// Adds reply action.
.addAction(replyAction)
// Makes the mark-as-read action invisible, so it doesn't appear
// in the Android UI but the app satisfies Android Auto's
// mark-as-read Action requirement. Both required actions can be made
// visible or invisible; it is a stylistic choice.
.addInvisibleAction(markAsReadAction)
.build()
// Posts the notification for the user to see.
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.notify(appConversation.id, notification)
}
Zusätzliche Ressourcen
Problem mit Android Auto Messaging melden
Wenn beim Entwickeln Ihrer Messaging-App für Android Auto ein Problem auftritt, können Sie es über die Google-Problemverfolgung melden. Achten Sie darauf, dass Sie alle erforderlichen Informationen in der Problemvorlage angeben.
Bevor Sie ein neues Problem melden, sehen Sie bitte in der Liste der Probleme nach, ob es bereits gemeldet wurde. Sie können Probleme abonnieren und für sie abstimmen, indem Sie im Tracker auf den Stern klicken. Weitere Informationen finden Sie unter Probleme abonnieren.