Mesajlar üzerinden iletişim kurmak birçok sürücü için önemlidir. Chat uygulamaları, kullanıcılara bir çocuğun alınması gerekip gerekmediğini veya akşam yemeği konumunun değişip değişmediğini bildirebilir. Android çerçevesi, sürücülerin gözlerini yoldan ayırmalarına olanak tanıyan standart bir kullanıcı arayüzü kullanarak mesajlaşma uygulamalarının hizmetlerini sürüş deneyimine genişletmesine olanak tanır.
Mesajlaşmayı destekleyen uygulamalar, Auto çalışırken Android Auto'nun bildirimleri kullanabilmesi için mesajlaşma bildirimlerinin kapsamını genişletebilir. Bu bildirimler Auto'da gösterilir ve kullanıcıların mesajları tutarlı, dikkat dağıtıcı bir arayüzde okumasına ve yanıtlamasına olanak tanır. MessagingStyle API'yi kullandığınızda Android Auto dahil tüm Android cihazlar için optimize edilmiş mesaj bildirimleri alırsınız. Optimizasyonlar arasında mesaj bildirimleri, iyileştirilmiş animasyonlar ve satır içi resim desteği için uzmanlaşmış bir kullanıcı arayüzü yer alır.
Bu kılavuzda, kullanıcıya mesaj görüntüleyen ve kullanıcının yanıtlarını (ör. sohbet uygulaması) alan bir uygulamanın, mesaj görüntüleme ve yanıt makbuzunu bir Auto cihaza aktarmak için nasıl genişletileceği gösterilmektedir. İlgili tasarım yardımı için Sürüş İçin Tasarım sitesindeki Mesajlaşma uygulamaları konusuna bakın.
Başlayın
Auto cihazlarda mesajlaşma hizmeti sağlamak için uygulamanızın, manifest dosyasında Android Auto'yu desteklediğini beyan etmesi ve aşağıdakileri yapabilmesi gerekir:
- Yanıt ve okundu olarak işaretle
Action
nesneleri içerenNotificationCompat.MessagingStyle
nesneleri oluşturup gönderin. Service
ile yanıt verebilir ve ileti dizisini okundu olarak işaretleyebilirsiniz.
Kavramlar ve nesneler
Uygulamanızı tasarlamaya başlamadan önce, Android Auto'nun mesajları nasıl işlediğini anlamanız faydalı olacaktır.
Tek bir iletişim parçasına mesaj adı verilir ve bu yığın, MessagingStyle.Message
sınıfı ile temsil edilir. İletide gönderen, ileti içeriği ve
mesajın gönderilme zamanı bulunur.
Kullanıcılar arasındaki iletişim ileti dizisi olarak adlandırılır ve bir MessagingStyle
nesnesiyle temsil edilir. Bir görüşme veya MessagingStyle
, bir başlığı, mesajları ve görüşmenin bir kullanıcı grubu arasında olup olmadığını içerir.
Uygulamalar, bir görüşmede yapılan güncellemeleri (ör. yeni bir mesaj) bildirmek için Android sistemine bir Notification
yayınlar.
Bu Notification
, bildirim gölgesinde mesajlaşmaya özel kullanıcı arayüzünü görüntülemek için MessagingStyle
nesnesini kullanır. Android platformu da bu Notification
öğesini Android Auto'ya iletir ve MessagingStyle
çıkarılıp arabanın ekranından bir bildirim yayınlamak için kullanılır.
Android Auto, kullanıcıların bir mesajı hızlıca yanıtlayabilmesi veya doğrudan bildirim gölgesinden okundu olarak işaretleyebilmesi için uygulamaların Notification
öğesine Action
nesneleri eklemesini de gerektirir.
Özetle, tek bir ileti dizisi, stili MessagingStyle
nesnesiyle belirlenmiş bir Notification
nesnesiyle temsil edilir. MessagingStyle
, söz konusu ileti dizisindeki tüm mesajları bir veya daha fazla MessagingStyle.Message
nesnesinde içerir. Ayrıca, Android Auto ile uyumlu olması için uygulamaların Notification
öğesine yanıt ve okundu olarak işaretle Action
nesnelerini eklemesi gerekir.
Mesajlaşma akışı
Bu bölümde, uygulamanız ile Android Auto arasındaki tipik bir mesajlaşma akışı açıklanmaktadır.
- Uygulamanız bir mesaj alır.
- Uygulamanız, yanıt ve okundu olarak işaretle
Action
nesneleri içeren birMessagingStyle
bildirimi oluşturur. - Android Auto, Android sisteminden "yeni bildirim" etkinliğini alır ve
MessagingStyle
, yanıtıAction
ve okundu olarak işaretleAction
öğelerini bulur. - Android Auto, arabada bir bildirim oluşturup görüntüler.
- Kullanıcı, arabanın ekranındaki bildirime dokunursa Android Auto, okundu olarak işaretle
Action
özelliğini tetikler.- Arka planda, uygulamanız bu okundu olarak işaretleme etkinliğini işlemelidir.
- Kullanıcı bildirime sesi kullanarak yanıt verirse Android Auto, kullanıcının yanıtının metne dönüştürülmüş halini
Action
yanıtına ekler ve ardından tetikler.- Arka planda, uygulamanızın bu yanıt etkinliğini işlemesi gerekir.
Ön varsayımlar
Bu sayfa, bir mesajlaşma uygulamasının tamamını oluşturma konusunda size yol göstermemektedir. Aşağıdaki kod örneği, Android Auto ile mesajlaşmayı desteklemeye başlamadan önce uygulamanızın ihtiyaç duyduğu bazı şeyleri içerir:
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 desteği beyan etme
Android Auto bir mesajlaşma uygulamasından bildirim aldığında, uygulamanın Android Auto'yu desteklediğini beyan edip etmediğini kontrol eder. Bu desteği etkinleştirmek için uygulamanızın manifest dosyasına aşağıdaki girişi ekleyin:
<application>
...
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Bu manifest girişi, şu yolla oluşturmanız gereken başka bir XML dosyasına başvurur: YourAppProject/app/src/main/res/xml/automotive_app_desc.xml
.
automotive_app_desc.xml
içinde, uygulamanızın desteklediği Android Auto özelliklerini beyan edin. Örneğin, bildirimlerin desteklendiğini beyan etmek için aşağıdakileri ekleyin:
<automotiveApp>
<uses name="notification" />
</automotiveApp>
Uygulamanız varsayılan SMS işleyici olarak ayarlanabiliyorsa aşağıdaki <uses>
öğesini eklediğinizden emin olun. Bunu yapmazsanız uygulamanız varsayılan SMS işleyici olarak ayarlandığında gelen SMS/MMS mesajlarını işlemek için Android Auto'da yerleşik bir varsayılan işleyici kullanılır ve bu da yinelenen bildirimlere yol açabilir.
<automotiveApp>
...
<uses name="sms" />
</automotiveApp>
AndroidX çekirdek kitaplığını içe aktarın
Auto cihazlarıyla kullanmak üzere bildirim oluşturmak için AndroidX temel kitaplığı gerekir. Kitaplığı projenize aşağıdaki şekilde aktarın:
- Üst düzey
build.gradle
dosyasına, aşağıdaki örnekte gösterildiği gibi Google'ın Maven deposuna bir bağımlılık ekleyin:
Modern
allprojects { repositories { google() } }
Kotlin
allprojects { repositories { google() } }
- Uygulama modülünüzün
build.gradle
dosyasında, aşağıdaki örnekte gösterildiği gibi AndroidX Core kitaplık bağımlılığını ekleyin:
Modern
dependencies { // If your app is written in Java implementation 'androidx.core:core:1.13.0' // If your app is written in Kotlin implementation 'androidx.core:core-ktx:1.13.0' }
Kotlin
dependencies { // If your app is written in Java implementation("androidx.core:core:1.13.0") // If your app is written in Kotlin implementation("androidx.core:core-ktx:1.13.0") }
Kullanıcı işlemlerini yönetme
Mesajlaşma uygulamanızın, Action
üzerinden bir görüşme güncellemeyi işlemesi gerekiyor. Android Auto için uygulamanızın işlemesi gereken iki tür Action
nesnesi vardır: yanıtla ve okundu olarak işaretle. Bunları IntentService
kullanarak yönetmenizi öneririz. Bu özellik, pahalı olabilecek çağrıları arka planda yöneterek uygulamanızın ana iş parçacığını serbest bırakma esnekliği sağlar.
Amaç işlemlerini tanımlayın
Intent
işlemleri, Intent
öğesinin ne işe yaradığını tanımlayan basit dizelerdir.
Tek bir hizmet birden fazla amaç türünü işleyebileceği için birden fazla IntentService
bileşeni tanımlamak yerine birden çok işlem dizesi tanımlamak daha kolaydır.
Bu kılavuzun örnek mesajlaşma uygulamasında, aşağıdaki kod örneğinde gösterildiği gibi zorunlu iki işlem türü bulunur: yanıtla ve okundu olarak işaretle.
private const val ACTION_REPLY = "com.example.REPLY"
private const val ACTION_MARK_AS_READ = "com.example.MARK_AS_READ"
Hizmeti oluşturma
Bu Action
nesnelerini işleyen bir hizmet oluşturmak için görüşme kimliğine ihtiyacınız vardır. Bu konuşma kimliğine, uygulamanız tarafından tanımlanan ve görüşmeyi tanımlayan rastgele bir veri yapısı bulunur. Ayrıca, bu bölümün ilerleyen kısımlarında ayrıntılı olarak açıklanacak olan bir uzak giriş anahtarı da gereklidir. Aşağıdaki kod örneği, gerekli işlemleri gerçekleştirecek bir hizmet oluşturur:
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()
}
}
}
Bu hizmeti uygulamanızla ilişkilendirmek için aşağıdaki örnekte gösterildiği gibi hizmeti uygulamanızın manifest dosyasında da kaydetmeniz gerekir:
<application>
<service android:name="com.example.MessagingService" />
...
</application>
Amaç oluşturma ve işleme
Intent
'ler PendingIntent
üzerinden diğer uygulamalara iletildiğinden, Android Auto dahil olmak üzere diğer uygulamaların MessagingService
işlemini tetikleyen Intent
'yi edinebilmesi mümkün değildir. Bu sınırlama nedeniyle, aşağıdaki örnekte gösterildiği gibi, diğer uygulamaların yanıt metnini uygulamanıza geri sağlaması için bir RemoteInput
nesnesi oluşturmanız gerekir:
/**
* 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
}
MessagingService
içindeki ACTION_REPLY
Switch deyiminde, aşağıdaki örnekte gösterildiği gibi Intent
yanıtına giren bilgileri çıkarın:
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)
}
Okundu olarak işaretleme Intent
öğesini benzer bir şekilde ele alırsınız. Ancak bu, aşağıdaki örnekte gösterildiği gibi bir RemoteInput
gerektirmez:
/** 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
}
MessagingService
içindeki ACTION_MARK_AS_READ
geçiş ifadesi için aşağıdaki örnekte gösterildiği gibi başka bir mantık gerekmez:
// Marking as read has no other logic.
ACTION_MARK_AS_READ -> conversation.markAsRead()
Kullanıcılara mesajları bildirme
Görüşme işleminin işlenmesi tamamlandıktan sonraki adım, Android Auto uyumlu bildirimler oluşturmaktır.
İşlem oluştur
Orijinal uygulamada yöntemleri tetiklemek için Notification
kullanılarak diğer uygulamalara Action
nesne geçirilebilir. Android Auto, bu şekilde bir ileti dizisini okundu veya yanıtlandı olarak işaretleyebilir.
Action
oluşturmaya Intent
ile başlayın. Aşağıdaki örnekte "yanıt" Intent
oluşturma işleminin nasıl yapılacağı gösterilmektedir:
fun createReplyAction(
context: Context, appConversation: YourAppConversation): Action {
val replyIntent: Intent = createReplyIntent(context, appConversation)
// ...
Ardından, bu Intent
öğesini bir PendingIntent
içine sarmalayın. Bu işlem, cihazı harici uygulama kullanımına hazırlar. PendingIntent
, yalnızca alıcı uygulamanın Intent
öğesini tetiklemesine veya kaynak uygulamanın paket adını almasına izin veren belirli bir grup yöntemi göstererek sarmalanmış Intent
öğesine tüm erişimi kilitler. Harici uygulama, temel Intent
öğesine veya içindeki verilere hiçbir zaman erişemez.
// ...
val replyPendingIntent = PendingIntent.getService(
context,
createReplyId(appConversation), // Method explained later.
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
// ...
Action
yanıtını oluşturmadan önce Android Auto'nun Action
yanıtı için üç şartı olduğunu göz önünde bulundurun:
- Anlamsal işlem
Action.SEMANTIC_ACTION_REPLY
olarak ayarlanmalıdır. Action
, etkinleştiğinde herhangi bir kullanıcı arayüzü göstermeyeceğini belirtmelidir.Action
, tek birRemoteInput
içermelidir.
Aşağıdaki kod örneği, yukarıda listelenen gereksinimleri ele alan bir Action
yanıtı oluşturur:
// ...
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
}
Okundu olarak işaretle işlemi, RemoteInput
olmadığı sürece benzer şekilde kullanılır.
Bu nedenle Android Auto'nun okundu olarak işaretle Action
özelliğinin iki şartı vardır:
- Anlamsal işlem
Action.SEMANTIC_ACTION_MARK_AS_READ
olarak ayarlandı. - İşlem, etkinleştiğinde herhangi bir kullanıcı arayüzü göstermeyeceğini belirtiyor.
Aşağıdaki kod örneği, bu gereksinimleri ele alan bir okundu olarak işaretle Action
özelliğini ayarlar:
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
}
Beklemedeki amaçlar oluşturulurken iki yöntem kullanılır:
createReplyId()
ve createMarkAsReadId()
. Bu yöntemler, her bir PendingIntent
için istek kodu görevi görür. Bu kodlar Android tarafından mevcut bekleyen amaçları kontrol etmek amacıyla kullanılır. create()
yöntemleri, her görüşme için benzersiz kimlikler döndürmelidir ancak aynı ileti dizisi için tekrarlanan çağrılar, önceden oluşturulmuş benzersiz kimliği döndürmelidir.
A ve B olmak üzere iki ileti dizisi içeren bir örneği ele alalım: Görüşme A'nın yanıt kimliği 100, okundu olarak işaretleme kimliği ise 101'dir. Görüşme B'nin yanıt kimliği 102 ve okundu olarak işaretleme kimliği 103'tür. İleti dizisi A güncellenirse yanıtlama ve okundu olarak işaretleme kimlikleri hâlâ 100 ve 101 olur. Daha fazla bilgi için PendingIntent.FLAG_UPDATE_CURRENT
bölümünü inceleyin.
MessagingStyle oluşturma
MessagingStyle
, mesajlaşma bilgilerinin operatörüdür ve Android Auto'yu bir görüşmedeki her mesajı sesli okumak için kullanır.
Öncelikle, cihazın kullanıcısı aşağıdaki örnekte gösterildiği gibi bir Person
nesnesi biçiminde belirtilmelidir:
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()
// ...
Ardından, MessagingStyle
nesnesini oluşturabilir ve ileti dizisi hakkında bazı ayrıntılar sağlayabilirsiniz.
// ...
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)
// ...
Son olarak, okunmamış iletileri ekleyin.
// ...
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
}
Bildirimi paketleyin ve aktarın
Action
ve MessagingStyle
nesnelerini oluşturduktan sonra Notification
öğesini oluşturup yayınlayabilirsiniz.
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)
}
Ek kaynaklar
Android Auto Mesajlaşma sorunu bildirme
Android Auto için mesajlaşma uygulamanızı geliştirirken bir sorunla karşılaşırsanız Google Sorun İzleyici'yi kullanarak bu sorunu bildirebilirsiniz. Sorun şablonunda istenen tüm bilgileri doldurduğunuzdan emin olun.
Yeni bir sorun oluşturmadan önce, sorunun zaten sorunlar listesinde bildirilip bildirilmediğini kontrol edin. İzleyicideki bir sorun için yıldızı tıklayarak abone olabilir ve sorunlara oy verebilirsiniz. Daha fazla bilgi için Bir Soruna Abone Olma bölümüne bakın.