Apps, die Messaging unterstützen, können ihre Messaging-Benachrichtigungen so erweitern, dass sie von Android Auto verwendet werden können, wenn es ausgeführt wird. Diese Benachrichtigungen werden von Android Auto angezeigt und ermöglichen Nutzern, Nachrichten in einer einheitlichen, ablenkungsarmen Benutzeroberfläche zu lesen und darauf zu antworten. Wenn Sie die MessagingStyle API verwenden, erhalten Sie optimierte Nachrichtenbenachrichtigungen für alle Android-Geräte, einschließlich Android
Auto. Zu den Optimierungen gehören eine Benutzeroberfläche, die speziell für Nachrichtenbenachrichtigungen entwickelt wurde, verbesserte Animationen und Unterstützung für Inline-Bilder.
In dieser Anleitung erfahren Sie, wie Sie eine App, die Nachrichten für den Nutzer anzeigt und die Antworten des Nutzers empfängt, z. B. eine Chat-App, so erweitern, dass die Nachrichtenanzeige und der Empfang von Antworten an Android Auto übergeben werden. Durch diese Integration können Nutzer nur den Nachrichtenverlauf aus Benachrichtigungen sehen, die während ihrer aktiven Android Auto-Sitzung empfangen wurden. Wenn Sie Nachrichten anzeigen möchten, die vor Beginn der aktiven Android Auto-Sitzung empfangen wurden, können Sie eine Messaging-Funktion mit Vorlagen erstellen.
Entsprechende Designrichtlinien finden Sie im Design for Cars -Hub unter Kommunikations-Apps.
Jetzt starten
Damit Ihre App Messaging-Dienste für Android Auto bereitstellen kann, muss sie im Manifest die Unterstützung für Android Auto deklarieren und Folgendes können:
- Unterstützung für Android Auto deklarieren
NotificationCompat.MessagingStyle-Objekte erstellen und senden, die Antworten- und Als-gelesen-markieren-Action-Objekte enthalten- Antworten und Markieren einer Unterhaltung als gelesen mit einem
Serviceverarbeiten
Konzepte und Objekte
Bevor Sie mit dem Design Ihrer App beginnen, sollten Sie wissen, wie Android Auto mit Messaging umgeht.
Ein einzelner Kommunikationsabschnitt wird als Nachricht bezeichnet und durch
die Klasse MessagingStyle.Message dargestellt. Eine Nachricht enthält einen Absender, den Nachrichteninhalt 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 die Unterhaltung zwischen einer Gruppe von Nutzern stattfindet.
Um Nutzer über Aktualisierungen einer Unterhaltung zu informieren, z. B. über eine neue Nachricht, senden Apps eine
Notification an das Android-System. Diese Notification verwendet das MessagingStyle-Objekt, um eine Messaging-spezifische Benutzeroberfläche im Benachrichtigungsfeld anzuzeigen. Die Android-Plattform übergibt diese Notification auch an Android Auto. Das MessagingStyle-Objekt wird extrahiert und verwendet, um eine Benachrichtigung auf dem Display des Autos zu posten.
Android Auto erfordert außerdem, dass Apps Action-Objekte zu einer Notification
hinzufügen, damit der Nutzer direkt über das Display des Autos 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 dieser Unterhaltung in einem oder mehreren MessagingStyle.Message
Objekten. Damit eine App mit Android Auto kompatibel ist, muss sie Action-Objekte für Antworten und zum Markieren als gelesen an die Notification anhängen.
Messaging-Ablauf
In diesem Abschnitt wird ein typischer Messaging-Ablauf zwischen Ihrer App und Android Auto beschrieben.
- Ihre App empfängt eine Nachricht.
- Ihre App generiert eine
MessagingStyle-Benachrichtigung mitAction-Objekten für Antworten und zum Markieren als gelesen. - Android Auto empfängt das Ereignis „Neue Benachrichtigung“ vom Android-System und findet das
MessagingStyle-Objekt sowie dieAction-Objekte für Antworten und zum Markieren als gelesen.Action - 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 die
Actionzum Markieren als gelesen aus.- Im Hintergrund muss Ihre App dieses Ereignis zum Markieren als gelesen verarbeiten.
- Wenn der Nutzer per Sprachbefehl auf die Benachrichtigung antwortet, fügt Android Auto eine Transkription der Antwort des Nutzers in die
Actionfür Antworten ein und löst sie dann aus.- Im Hintergrund muss Ihre App dieses Ereignis zum Antworten 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)
Unterstützung von Android Auto deklarieren
Wenn Android Auto eine Benachrichtigung von einer Messaging-App empfängt, wird geprüft, ob die App die Unterstützung für Android Auto deklariert hat. Fügen Sie dazu 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, automotive_app_desc.xml, die
Sie im Verzeichnis res/xml Ihres App-Moduls erstellen müssen. Deklarieren Sie in automotive_app_desc.xml die Android Auto-Funktionen, die Ihre App unterstützt. Wenn Sie die Unterstützung für Benachrichtigungen deklarieren möchten, fügen Sie Folgendes ein:
<automotiveApp>
<uses name="notification" />
</automotiveApp>
Wenn Ihre App als der Standard-SMS-Handler festgelegt werden kann, fügen Sie das
folgende <uses> Element ein. Andernfalls verwendet Android Auto den integrierten Standard-Handler, 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 Core-Bibliothek importieren
Zum Erstellen von Benachrichtigungen für Android Auto ist die AndroidX Core Bibliothek 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 der
build.gradle-Datei Ihres App-Moduls die AndroidX Core -Bibliotheksabhängigkeit ein, wie im folgenden Beispiel gezeigt:
Groovy
dependencies { // If your app is written in Java implementation 'androidx.core:core:1.19.0' // If your app is written in Kotlin implementation 'androidx.core:core-ktx:1.19.0' }
Kotlin
dependencies { // If your app is written in Java implementation("androidx.core:core:1.19.0") // If your app is written in Kotlin implementation("androidx.core:core-ktx:1.19.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: Antworten und Markieren als gelesen. Wir empfehlen, sie mit einem
IntentService zu verarbeiten. So können potenziell
aufwendige Aufrufe im Hintergrund verarbeitet werden, wodurch der Hauptthread Ihrer App entlastet wird.
Intent-Aktionen definieren
Intent -Aktionen sind grundlegende Strings Ihrer Wahl, die angeben, wofür der 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 dieser Anleitung hat die beiden erforderlichen Arten von Aktionen: Antworten und Markieren als gelesen, 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
Um einen Dienst zu erstellen, der diese Action-Objekte verarbeitet, benötigen Sie die Unterhaltungs-ID. Das ist eine beliebige Datenstruktur, die von Ihrer App definiert wird und die Unterhaltung identifiziert. Außerdem benötigen Sie einen Remote-Eingabeschlüssel, der später in diesem Abschnitt ausführlich behandelt wird. Im folgenden Codebeispiel wird ein Dienst erstellt, der die erforderlichen Aktionen verarbeitet:
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()
}
}
}
Um diesen Dienst mit Ihrer App zu verknüpfen, 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 den Intent, der den
MessagingService auslöst, nicht abrufen, da Intents über einen
PendingIntent an andere Apps übergeben werden. Erstellen Sie aufgrund dieser Einschränkung ein RemoteInput
Objekt, damit andere Apps Ihrer App Antworttext bereitstellen 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 des MessagingService die Informationen, die in den Antwort-Intent aufgenommen werden, 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)
}
Sie verarbeiten den Intent zum Markieren als gelesen auf ähnliche Weise. Dafür 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 innerhalb des 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 Nachrichten benachrichtigen
Nachdem die Verarbeitung der Unterhaltungsaktionen abgeschlossen ist, besteht der nächste Schritt darin, Android Auto-konforme Benachrichtigungen zu generieren.
Aktionen erstellen
Action -Objekte können über eine 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 einem Intent. Im folgenden Beispiel wird gezeigt, wie
Sie mit der Methode aus dem
vorherigen Abschnitt einen Antwort-"reply" Intent erstellen:createReplyIntent()
fun createReplyAction(
context: Context, appConversation: YourAppConversation): Action {
val replyIntent: Intent = createReplyIntent(context, appConversation)
// ...
Umschließen Sie dieses Intent dann mit einem PendingIntent, um es für die Verwendung durch externe
Apps vorzubereiten. Ein PendingIntent sperrt den gesamten Zugriff auf das umschlossene Intent, 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 nicht auf den zugrunde liegenden 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, beachten Sie, dass Android Auto drei Anforderungen an die Antwort-Action stellt:
- Die semantische Aktion muss auf
Action.SEMANTIC_ACTION_REPLYfestgelegt sein. - Die
Actionmuss angeben, dass beim Auslösen keine Benutzeroberfläche angezeigt wird. - Die
Actionmuss einen einzelnenRemoteInputenthalten.
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 zum Markieren als gelesen ist ähnlich, nur dass kein RemoteInput vorhanden ist.
Android Auto stellt daher zwei Anforderungen an die Action zum Markieren als gelesen:
- Die semantische Aktion ist auf
Action.SEMANTIC_ACTION_MARK_AS_READfestgelegt. - Die Aktion gibt an, dass beim Auslösen keine Benutzeroberfläche angezeigt wird.
Im folgenden Codebeispiel wird eine Action zum Markieren als gelesen eingerichtet, die 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 later.
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
}
Wenn Sie die ausstehenden Intents generieren, verwenden Sie zwei Methoden: createReplyId und createMarkAsReadId. Diese Methoden dienen als Anforderungscodes für jeden PendingIntent, die von Android verwendet werden, um vorhandene ausstehende Intents zu steuern.
Die create-Methoden müssen eindeutige IDs für jede Unterhaltung zurückgeben. Bei wiederholten Aufrufen für dieselbe Unterhaltung muss jedoch die bereits generierte eindeutige ID zurückgegeben werden.
Ein Beispiel: Es gibt zwei Unterhaltungen, A und B. Die Antwort-ID für Unterhaltung A ist 100 und die ID zum Markieren als gelesen ist 101. Die Antwort-ID für Unterhaltung B ist 102 und die ID zum Markieren als gelesen ist 103. Wenn Unterhaltung A aktualisiert wird, bleiben die Antwort-ID und die ID zum Markieren als gelesen 100 und 101. Weitere Informationen finden Sie unter
PendingIntent.FLAG_UPDATE_CURRENT.
MessagingStyle erstellen
MessagingStyle enthält die Messaging-Informationen und wird von Android Auto verwendet, um jede Nachricht in einer Unterhaltung vorzulesen.
Zuerst müssen Sie den Nutzer des Geräts als ein Person-Objekt angeben, 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 zur Unterhaltung 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 abschließend 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 Messaging-Benachrichtigungen in Android Auto melden
Wenn beim Entwickeln Ihrer Messaging-Benachrichtigungen für Android Auto ein Problem auftritt, können Sie es über die Google-Problemverfolgung melden. Achten Sie darauf, dass Sie alle angeforderten Informationen in der Problemvorlage angeben.
Bevor Sie ein neues Problem melden, prüfen Sie, ob es bereits in der Liste der Probleme aufgeführt ist. Sie können Probleme abonnieren und dafür abstimmen, indem Sie in der Problemverfolgung auf den Stern für ein Problem klicken. Weitere Informationen finden Sie unter Ein Problem abonnieren.