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 es Nutzern, Nachrichten über eine einheitliche, ablenkungsarme Oberflä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 zu Nachrichten entwickelt wurde, verbesserte Animationen und Unterstützung für Inline-Bilder.
In diesem Leitfaden 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 Android Auto ü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 Designrichtlinien findest du im Hub „Design for Cars“ unter Kommunikations-Apps.
Erste Schritte
Wenn Ihre App einen Messaging-Dienst für Android Auto bereitstellen soll, muss sie im Manifest die Unterstützung von Android Auto deklarieren und Folgendes können:
- Unterstützung für Android Auto deklarieren
NotificationCompat.MessagingStyle-Objekte erstellen und senden, dieAction-Objekte für Antworten und Markierungen als gelesen enthalten.- Antworten und das Markieren einer Unterhaltung als gelesen mit einem
Serviceverarbeiten.
Konzepte und Objekte
Bevor Sie mit dem Design Ihrer App beginnen, sollten Sie sich mit der Nachrichtenverarbeitung in Android Auto vertraut machen.
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 die Unterhaltung zwischen einer Gruppe von Nutzern stattfindet.
Wenn Nutzer über Aktualisierungen einer Unterhaltung, z. B. eine neue Nachricht, benachrichtigt werden sollen, senden Apps ein 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.
Für Android Auto müssen Apps auch Action-Objekte zu einem 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 wird. Das MessagingStyle-Objekt 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 „reply“ und „mark-as-read“ Action angehängt werden.
Messaging-Ablauf
In diesem Abschnitt wird ein typischer Messaging-Ablauf zwischen Ihrer App und Android Auto beschrieben.
- Ihre App erhält eine Nachricht.
- Ihre App generiert eine
MessagingStyle-Benachrichtigung mit den ObjektenActionfür Antworten und als gelesen markieren. - Android Auto empfängt das Ereignis „Neue Benachrichtigung“ vom Android-System und findet die
MessagingStyle, die AntwortActionund 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
Actionaus.- 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
Actionein 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. Wenn Sie diese Unterstützung aktivieren möchten, 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, automotive_app_desc.xml, die Sie im res/xml-Verzeichnis Ihres App-Moduls erstellen müssen. Deklarieren Sie in automotive_app_desc.xml die von Ihrer App unterstützten Android Auto-Funktionen. So deklarieren Sie die Unterstützung für Benachrichtigungen:
<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 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-Kernbibliothek importieren
Für die Entwicklung 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 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 in der Lage sein, 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. So können Sie potenziell teure Aufrufe im Hintergrund ausführen und den Hauptthread Ihrer App entlasten.
Intent-Aktionen definieren
Intent-Aktionen sind einfache Strings Ihrer Wahl, 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
Um einen Dienst zu erstellen, 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 einen Remote-Eingabeschlüssel, der 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 die MessagingService auslöst, nicht abrufen, da Intents über eine PendingIntent an andere Apps übergeben werden. Erstellen Sie aufgrund dieser Einschränkung ein RemoteInput-Objekt, damit andere Apps Ihrer App Antworttext zur Verfügung stellen 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 der 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 Unterhaltungsaktion abgeschlossen ist, besteht der nächste Schritt darin, Android Auto-kompatible Benachrichtigungen zu generieren.
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 mit der Methode createReplyIntent() aus dem vorherigen Abschnitt eine 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 nicht 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_REPLYfestgelegt sein. - Im
Actionmuss angegeben werden, dass beim Auslösen keine Benutzeroberfläche angezeigt wird. Actionmuss ein einzelnesRemoteInput-Element enthalten.
Im folgenden Codebeispiel wird eine Antwort Action eingerichtet, die den oben aufgeführten Anforderungen entspricht:
// ...
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_READfestgelegt. - 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 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 Anfragecodes 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 die Antwort und das Markieren als gelesen 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 müssen Sie den Nutzer des Geräts als 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 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-Nachrichtenbenachrichtigungen melden
Wenn beim Entwickeln von Messaging-Benachrichtigungen für Android Auto ein Problem auftritt, können Sie es über die Google-Problemverfolgung melden. Achte darauf, dass du alle erforderlichen Informationen in der Problemvorlage angibst.
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.