Templated messaging experiences are in beta At this time, anyone can publish communication apps with templated messaging experiences to internal testing and closed testing tracks on the Play Store. Publishing to open testing and production tracks will be permitted at a later date. [Nominate yourself to be an early access partner →](https://forms.gle/VsXEdDEBidxw8q8u8) ![](https://developer.android.com/static/images/picto-icons/test-tube-2.svg)

In addition to the basic notification-powered messaging experience for reading
and replying to messages, Android Auto supports richer messaging experiences
built using the [Android for Cars App Library](https://developer.android.com/training/cars/apps).

## Support notification-powered messaging experiences

All apps that support templated messaging experiences must also [extend
messaging notifications for Android Auto](https://developer.android.com/training/cars/communication/notification-messaging). This
integration allows users to read and reply to messages without having to open
the templated app.

## Build a templated messaging experience

Follow the guidance in [Use the Android for Cars App Library](https://developer.android.com/training/cars/apps) and [Add
support for Android Auto to your templated app](https://developer.android.com/training/cars/apps/auto) to get started
building your app's templated experience. Then, refer to the guidance on this
page to understand the specific requirements for templated messaging apps.

### Configure your app's manifest files

To inform Android Auto of your app's capabilities, your app must do the
following:

#### Declare category support in your manifest

Your app needs to declare the `androidx.car.app.category.MESSAGING` [car app
category](https://developer.android.com/training/cars/apps#supported-app-categories) in the intent filter of its
[`CarAppService`](https://developer.android.com/reference/androidx/car/app/CarAppService.md.txt).

```xml
<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.MESSAGING"/>
      </intent-filter>
    </service>
    ...
<application>
```

> [!NOTE]
> **Note:** If your app supports both messaging and [calling](https://developer.android.com/training/cars/communication/calling.md.txt), include both `androidx.car.app.category.CALLING` and `androidx.car.app.category.MESSAGING` `<category>` elements in the same intent filter.

#### Set the minimum car app API level

Because the [`ConversationItem`](https://developer.android.com/reference/androidx/car/app/messaging/model/ConversationItem.md.txt) API is only supported on
Car API 7 or higher, you should also set the `minCarApiLevel` metadata to that
value. See [Car App API Level](https://developer.android.com/training/cars/apps#api-level) for more information.

```xml
<application ...>
    ...
    <meta-data
        android:name="androidx.car.app.minCarApiLevel"
        android:value="7"/>
    ...
</application>
```

#### Declare Android Auto support

In the `automotive_app_desc.xml` file that you use to [declare Android Auto
support](https://developer.android.com/training/cars/apps/auto#declare-android-auto-support), verify that both the `notification` and
`template` capabilities are declared:

```xml
<automotiveApp>
    <uses name="notification" />
    <uses name="template" />
</automotiveApp>
```

If your app can be set as the [default SMS handler](https://developer.android.com/reference/android/provider/Telephony.md.txt#creating-an-sms-app),
make sure to include the following `<uses>` element. If you don't, a default
handler built-in to Android Auto will be used to handle incoming SMS/MMS
messages, which can lead to duplicate notifications.

```xml
<automotiveApp>
    ...
    <uses name="sms" />
</automotiveApp>
```

### Display conversations

To display an overview of a user's conversations, you can display a list of
[`ConversationItem`](https://developer.android.com/reference/androidx/car/app/messaging/model/ConversationItem.md.txt) objects in a
[`ListTemplate`](https://developer.android.com/reference/androidx/car/app/model/ListTemplate.md.txt) or
[`SectionedItemTemplate`](https://developer.android.com/reference/androidx/car/app/model/SectionedItemTemplate.md.txt).

For a good user experience, we recommend providing at most the 5-10 most
recent or most important conversations, with no more than the 5 most recent
messages for each conversation. This helps improve loading performance, lets
users see the most relevant content, and reduces interaction time.


```kotlin
class MyMessagingScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val itemListBuilder = ItemList.Builder()
        val conversations: List<MyConversation> = getConversations() // Retrieve conversations

        for (conversation: MyConversation in conversations) {
            val carMessages: List<CarMessage> = conversation.getMessages()
                .map { message ->
                    // CarMessage supports additional fields such as MIME type and URI,
                    // which you should set if available
                    CarMessage.Builder()
                        .setSender(message.sender)
                        .setBody(message.body)
                        .setReceivedTimeEpochMillis(message.receivedTimeEpochMillis)
                        .setRead(message.isRead)
                        .build()
                }

            itemListBuilder.addItem(
                ConversationItem.Builder(
                    conversation.id,
                    CarText.create(conversation.title),
                    Person.Builder()
                        .setName("Me")
                        .setKey("self_id")
                        .build(),
                    carMessages,
                    myConversationCallback
                )
                    .build()
            )
        }

        val header = Header.Builder()
            .setStartHeaderAction(Action.APP_ICON)
            .setTitle("Conversations")
            .build()

        return ListTemplate.Builder()
            .setHeader(header)
            .setSingleList(itemListBuilder.build())
            .build()
    }
}
```

<br />

Each `ConversationItem` automatically displays actions for playing a message
and marking it as read as and for replying. Those actions are handled by the
[`ConversationCallbackDelegate`](https://developer.android.com/reference/androidx/car/app/messaging/model/ConversationCallbackDelegate.md.txt) you supply when
building the `ConversationItem`.

> [!TIP]
> **Tip:** You can re-use the logic for marking messages as read and replying that enables your app's notification-powered experience.

If your app provides [conversation shortcuts](https://developer.android.com/develop/ui/views/notifications/conversations.md.txt#api-shortcuts), verify
that the ID provided when building the `ConversationItem` is the same as the
ID for that conversation's shortcut.

#### Update conversations

As users send and receive messages, you should refresh your app's screens to
include the new messages by calling [`invalidate()`](https://developer.android.com/reference/androidx/car/app/Screen.md.txt#invalidate()). See [Refresh
the contents of a template](https://developer.android.com/training/cars/apps#refresh-template).

For the best user experience, we recommend keeping refresh times to 500
milliseconds or fewer. If refreshing frequently takes longer, you can display a
loading state while you load the incoming messages.

#### Set notification importance appropriately

To reduce distractions, your app should lower the importance of incoming
notifications when a user is using your viewing a corresponding conversation
so the notifications don't appear as heads up notifications (HUNs).

You can track if a conversation is visible by observing the lifecycle of the
`Screen` that displays it. See [The lifecycle of a screen](https://developer.android.com/training/cars/apps#screen-lifecycle).

To prevent a notification from appearing as a HUN, set the priority to
[`IMPORTANCE_DEFAULT`](https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat.md.txt#IMPORTANCE_DEFAULT) or lower.

## Distribute templated messaging apps

Because apps that support templated messaging experiences can only be published
to Internal Testing and Closed Testing tracks on Google Play, you shouldn't
promote builds that include support to Open Testing or Production tracks, as
submissions containing builds on those tracks will be rejected.