Rimanere in contatto attraverso i messaggi è importante per molti conducenti. Le app di chat consentono agli utenti sapere se un bambino deve essere a prendere o se è stato cambiato il luogo della cena. Il framework Android consente alle app di messaggistica di estendere personalizzati nell'esperienza di guida grazie a un'interfaccia utente standard che consente ai conducenti di gli occhi sulla strada.
Le app che supportano la messaggistica possono estendere le notifiche dei messaggi per consentire ad Android Auto e consumarle quando è in esecuzione la modalità Auto. Queste notifiche vengono visualizzate in modalità Automatica e consentono agli utenti leggere e rispondere ai messaggi in un'interfaccia coerente e senza distrazioni. E quando usi API MessagingStyle, ricevi notifiche dei messaggi ottimizzate per tutti i dispositivi Android tra cui Android Auto. Le ottimizzazioni includono una UI specializzata notifiche di messaggi, animazioni migliorate e supporto per le immagini in linea.
Questa guida illustra come estendere un'app che mostra messaggi all'utente e riceve le risposte dell'utente, ad esempio un'app di chat, alla visualizzazione dei messaggi e rispondi alla ricevuta su un dispositivo automatico. Per indicazioni di progettazione correlate, consulta Messaggistica app sul sito Design for Driving.
Inizia
Per poter fornire un servizio di messaggistica per i dispositivi Auto, la tua app deve dichiarare la propria supporto per Android Auto nel file manifest ed essere in grado di:
- Crea e invia
NotificationCompat.MessagingStyle
che contengono oggetti di risposta e contrassegna come lettoAction
. - Gestisci la risposta e il contrassegno di una conversazione come letta con un
Service
.
Concetti e oggetti
Prima di iniziare a progettare la tua app, è utile comprendere in che modo Android Auto gestisce i messaggi.
Un singolo blocco di comunicazione è chiamato messaggio ed è rappresentato da un
la classe MessagingStyle.Message
. Un messaggio contiene un mittente, il messaggio
contenuti e l'ora di invio del messaggio.
La comunicazione tra gli utenti è chiamata conversazione ed è rappresentata da un
MessagingStyle
oggetto. Una conversazione, o MessagingStyle
, contiene un titolo,
i messaggi e se la conversazione fa parte di un gruppo di utenti.
Per informare gli utenti degli aggiornamenti di una conversazione, ad esempio un nuovo messaggio, le app pubblicano
un Notification
al sistema Android.
Questo Notification
utilizza l'oggetto MessagingStyle
per visualizzare messaggi specifici
UI nell'area notifiche. La piattaforma Android trasmette anche questo Notification
ad Android Auto; il valore MessagingStyle
viene estratto e usato per pubblicare
tramite il display dell'auto.
Android Auto richiede anche alle app di aggiungere oggetti Action
a Notification
per
consente all'utente di rispondere rapidamente a un messaggio o di contrassegnarlo come letto direttamente dal
area notifiche.
In sintesi, una singola conversazione è rappresentata da un Notification
a cui è associato uno stile MessagingStyle
. MessagingStyle
contiene tutti i messaggi all'interno della conversazione in uno o più
MessagingStyle.Message
oggetti. Per essere conforme ad Android Auto,
deve collegare gli oggetti Action
risposta e contrassegna come letto al Notification
.
Flusso di messaggi
Questa sezione descrive un tipico flusso di messaggi tra la tua app e Android Auto.
- La tua app riceve un messaggio.
- La tua app genera una notifica
MessagingStyle
con risposta e contrassegna come lettiAction
oggetti. - Android Auto riceve l'evento "nuova notifica" dal sistema Android
e trova
MessagingStyle
, rispondeAction
e contrassegna come lettoAction
. - Android Auto genera e mostra una notifica nell'auto.
- Se l'utente tocca la notifica sul display dell'auto, Android Auto
attiva Contrassegna come letto
Action
.- In background, l'app deve gestire questo evento Segna come letto.
- Se l'utente risponde alla notifica con la voce, Android Auto inserisce
una trascrizione della risposta dell'utente nella risposta
Action
e poi lo attiva.- In background, la tua app deve gestire questo evento di risposta.
Ipotesi preliminari
Questa pagina non ti guida nella creazione di un'intera app di messaggistica. La Il seguente esempio di codice include alcune cose di cui la tua app ha bisogno Prima di iniziare a supportare la messaggistica con Android Auto:
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)
Dichiara il supporto di Android Auto
Quando Android Auto riceve una notifica da un'app di messaggistica, controlla che l'app ha dichiarato il supporto di Android Auto. Per attivare questo supporto, includi la seguente voce nel file manifest dell'app:
<application>
...
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Questa voce manifest si riferisce a un altro file XML che devi creare con
seguente percorso: YourAppProject/app/src/main/res/xml/automotive_app_desc.xml
.
In automotive_app_desc.xml
, dichiara le funzionalità di Android Auto della tua app
Google Cloud. Ad esempio, per dichiarare il supporto delle notifiche, includi la
seguenti:
<automotiveApp>
<uses name="notification" />
</automotiveApp>
Se la tua app può essere impostata come gestore di SMS predefinito:
assicurati di includere il seguente elemento <uses>
. In caso contrario, verrà eseguito un
per gestire i messaggi SMS/MMS in arrivo verrà usato un gestore integrato in Android Auto
se la tua app è impostata come gestore predefinito di SMS, il che può generare duplicati
notifiche.
<automotiveApp>
...
<uses name="sms" />
</automotiveApp>
Importa la libreria di base AndroidX
La creazione delle notifiche per l'utilizzo con i dispositivi Auto richiede la libreria di base di AndroidX. Importa la raccolta nel tuo progetto come segue:
- Nel file
build.gradle
di primo livello, includi una dipendenza da Maven di Google come mostrato nell'esempio seguente:
Alla moda
allprojects { repositories { google() } }
Kotlin
allprojects { repositories { google() } }
- Nel file
build.gradle
del modulo dell'app, includi AndroidX Core della libreria, come mostrato nell'esempio seguente:
Alla moda
dependencies { // If your app is written in Java implementation 'androidx.core:core:1.13.1' // If your app is written in Kotlin implementation 'androidx.core:core-ktx:1.13.1' }
Kotlin
dependencies { // If your app is written in Java implementation("androidx.core:core:1.13.1") // If your app is written in Kotlin implementation("androidx.core:core-ktx:1.13.1") }
Gestire le azioni degli utenti
La tua app di messaggistica deve essere in grado di gestire l'aggiornamento di una conversazione tramite
Action
. Per Android Auto, esistono due tipi di oggetti Action
nella tua app
deve gestire: rispondere e contrassegnare come letto. Ti consigliamo di usarli
un IntentService
, che
offre la flessibilità necessaria per gestire
chiamate in background, liberando il thread principale dell'app.
Definisci le azioni per intent
Le azioni Intent
sono semplici stringhe che identificano lo scopo di Intent
.
Dato che un singolo servizio è in grado di gestire più tipi di intent, è più facile
definire più stringhe di azioni invece di definire più
IntentService
componenti.
L'app di messaggistica di esempio di questa guida presenta i due tipi di azioni richiesti: rispondi e contrassegna come letto, come mostrato nel seguente esempio di codice.
private const val ACTION_REPLY = "com.example.REPLY"
private const val ACTION_MARK_AS_READ = "com.example.MARK_AS_READ"
Crea il servizio
Per creare un servizio che gestisca questi oggetti Action
, devi disporre dell'ID conversazione,
, una struttura di dati arbitraria definita dalla tua app che identifica
la conversazione. È inoltre necessario un tasto di input remoto, di cui parleremo
più avanti in questa sezione. Il seguente esempio di codice crea un servizio
per gestire le azioni richieste:
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()
}
}
}
Per associare questo servizio alla tua app, devi anche registrare il servizio nel file manifest dell'app, come mostrato nell'esempio seguente:
<application>
<service android:name="com.example.MessagingService" />
...
</application>
Genera e gestisci gli intent
Altre app, inclusa Android Auto, non possono ottenere Intent
che attiva MessagingService
, perché i Intent
vengono trasmessi ad altre app
tramite una PendingIntent
. A causa di
questa limitazione, devi creare un'istanza RemoteInput
per consentire ad altre app di fornire il testo di risposta alla tua app, come mostrato
nel seguente esempio:
/**
* 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
}
Nella clausola di switch ACTION_REPLY
in MessagingService
,
estrarre le informazioni contenute nella risposta Intent
, come mostrato
nell'esempio seguente:
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)
}
Puoi gestire il contrassegno come letto Intent
in modo simile. Tuttavia,
richiedono un RemoteInput
, come mostrato nell'esempio seguente:
/** 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
}
Clausola di switch ACTION_MARK_AS_READ
in MessagingService
non richiede ulteriore logica, come mostrato nell'esempio seguente:
// Marking as read has no other logic.
ACTION_MARK_AS_READ -> conversation.markAsRead()
Avvisare gli utenti dei messaggi
Una volta completata la gestione delle azioni di conversazione, il passaggio successivo generare notifiche conformi ad Android Auto.
Crea azioni
Action
oggetti possono essere trasmessi ad altre app utilizzando un Notification
per
di trigger nell'app originale. Ecco come Android Auto può contrassegnare
conversazione come letta o rispondere.
Per creare un Action
, inizia con un Intent
. L'esempio seguente mostra
come si crea una "risposta" Intent
:
fun createReplyAction(
context: Context, appConversation: YourAppConversation): Action {
val replyIntent: Intent = createReplyIntent(context, appConversation)
// ...
Quindi, aggrega questo Intent
in un PendingIntent
, per prepararlo per l'uso
utilizzo delle app. Un PendingIntent
blocca tutti gli accessi al Intent
con wrapping per
solo un insieme selezionato di metodi che consentono all'app ricevente di attivare
Intent
o recupera il nome del pacchetto dell'app di origine. L'app esterna
non possono mai accedere all'oggetto Intent
sottostante o ai dati al suo interno.
// ...
val replyPendingIntent = PendingIntent.getService(
context,
createReplyId(appConversation), // Method explained later.
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
// ...
Prima di configurare la risposta Action
, tieni presente che Android Auto ha tre
requisiti per la risposta Action
:
- L'azione semantica deve essere impostata su
Action.SEMANTIC_ACTION_REPLY
. - L'elemento
Action
deve indicare che non mostrerà alcuna interfaccia utente quando viene attivato. Action
deve contenere un singolo elementoRemoteInput
.
Il seguente esempio di codice configura una risposta Action
che gestisce le
requisiti sopra elencati:
// ...
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
}
La gestione dell'azione Segna come letto è simile, tranne per il fatto che non sono presenti RemoteInput
.
Di conseguenza, Android Auto ha due requisiti per l'attributo Action
Contrassegna come letto:
- L'azione semantica è impostata su
Action.SEMANTIC_ACTION_MARK_AS_READ
. - L'azione indica che non mostrerà alcuna interfaccia utente quando viene attivata.
Il seguente esempio di codice configura un Action
Contrassegna come letto che risolve questi
requisiti:
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
}
Quando generi gli intent in attesa, vengono utilizzati due metodi:
createReplyId()
e createMarkAsReadId()
. Questi metodi fungono da
codici di richiesta per ogni PendingIntent
, che vengono usati da Android per controllare
intent in attesa esistenti. I metodi create()
devono
restituiscono ID univoci per ogni conversazione, ma chiamate ripetute per la stessa
deve restituire l'ID univoco già generato.
Considera un esempio con due conversazioni, A e B: l'ID risposta della conversazione A è 100.
e il relativo ID contrassegna come letto è 101. L'ID risposta della conversazione B è
102, mentre l'ID Segna come letto è 103. Se la conversazione A viene aggiornata,
gli ID risposta e Segna come letto sono sempre 100 e 101. Per ulteriori informazioni, vedi
PendingIntent.FLAG_UPDATE_CURRENT
Crea un MessagingStyle
MessagingStyle
è l'operatore delle informazioni di messaggistica ed è ciò che Android
Lettura automatica ad alta voce di ogni messaggio di una conversazione.
Innanzitutto, l'utente del dispositivo deve essere specificato sotto forma di
Person
, come mostrato nell'oggetto
nell'esempio seguente:
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()
// ...
Puoi quindi creare l'oggetto MessagingStyle
e fornire alcuni dettagli
della conversazione.
// ...
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)
// ...
Infine, aggiungi i messaggi da leggere.
// ...
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
}
Imballa la notifica ed esegui il push della notifica
Dopo aver generato gli oggetti Action
e MessagingStyle
, puoi
crea e pubblica Notification
.
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)
}
Risorse aggiuntive
Segnalare un problema della messaggistica di Android Auto
Se riscontri un problema durante lo sviluppo della tua app di messaggistica per Android Auto: puoi segnalarlo utilizzando Google Issue Tracker. Assicurati di compilare tutte le informazioni richieste nel modello di problema.
Prima di inviare un nuovo problema, controlla se è già segnalato nei problemi. dall'elenco di lettura. Puoi iscriverti e votare per i problemi facendo clic sulla stella relativa a un problema in il tracker. Per ulteriori informazioni, vedi Abbonarsi a un problema.