This page describes how to create notifications for a watch. This page also describes how to provide additional content for each notification that is bridged to the watch from a connected phone.
Notifications on watches have the same structure as notifications on phones. Additionally, to give users the best experience, Wear OS by Google provides APIs for adding wearable-specific features to notifications.
When you issue a notification from your app, each notification appears as a card on the Notification Stream.

Figure 1. The same notification displayed on a phone and on a watch.
Both the watch and the phone can be sources of notifications. Use the
NotificationCompat.Builder
class to create notifications
for wearables. When you build notifications with this class, the system takes care
of displaying notifications properly.
Note:
Notifications using RemoteViews
are stripped of custom
layouts and the wearable only displays the text and icons. However, you can
create custom
notifications that use custom card layouts by creating a wearable app that
runs on the watch.
Normally, all notifications are bridged from the phone to the watch. However, notifications are not bridged in the following cases:
-
"Local only" notifications set using
Notification.Builder.setLocalOnly(boolean)
. -
Ongoing notifications set using
Notification.Builder.setOngoing(boolean)
orNotification.FLAG_ONGOING_EVENT
. -
Non-clearable notifications set using
Notification.FLAG_NO_CLEAR
. - Notifications where the counterpart wearable app has disabled notification bridging.
Refer to the following related resources:
Import the necessary classes
To import the necessary packages, add this line to your build.gradle
file:
implementation 'androidx.core:core:1.2.0'
Now that your project has access to the necessary packages, import the necessary classes from the support library:
Kotlin
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationCompat.WearableExtender
Java
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationCompat.WearableExtender;
Create a notification with the notification builder
The Jetpack Core library allows you to create notifications using the latest notification features such as action buttons and icons, while remaining compatible with Android 1.6 (API level 4) and higher.
Note: Starting in Android 8.0 (API level 26), you need to create notification channels for each type of notification you want to display.
To create a notification:
-
Create an instance of
NotificationCompat.Builder
.Kotlin
val notificationId = 1 // The channel ID of the notification. val id = "my_channel_01" // Build intent for notification content val viewPendingIntent = Intent(this, ViewEventActivity::class.java).let { viewIntent -> viewIntent.putExtra(EXTRA_EVENT_ID, eventId) PendingIntent.getActivity(this, 0, viewIntent, 0) } // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent)
Java
int notificationId = 001; // The channel ID of the notification. String id = "my_channel_01"; // Build intent for notification content Intent viewIntent = new Intent(this, ViewEventActivity.class); viewIntent.putExtra(EXTRA_EVENT_ID, eventId); PendingIntent viewPendingIntent = PendingIntent.getActivity(this, 0, viewIntent, 0); // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent);
-
Issue the notification by passing the Notification object with a notification ID to
notify()
.Kotlin
NotificationManagerCompat.from(this).apply { notify(notificationId, notificationBuilder.build()) }
Java
// Get an instance of the NotificationManager service NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); // Issue the notification with notification manager. notificationManager.notify(notificationId, notificationBuilder.build());
When this notification appears on a phone, the user can invoke the
PendingIntent
specified by the
setContentIntent()
method by touching the notification. When this notification
appears on a wearable, it appears in the notification stream. For bridged notifications,
the user can click the notification to view the
expanded notification and trigger any defined action, such
as open action. Usually, these actions opens an
Activity
on your phone app.
Construct expanded notifications
Expanded notifications provide substantial additional content and actions for each notification. When you specify additional content pages and actions for a notification, those are available to the user within the expanded notification.
If the first action in the expanded notification has a
RemoteInput
(for example, a Reply action), then the choices you set with
setChoices()
appear within the expanded notification below the first action.
The user can view the expanded notification by tapping on a notification when either of the following is true:
- The notification is generated by an app on the paired phone and bridged to Wear.
-
The notification does not have a
contentIntent
.
Note:
An app-specific background color set for a notification with the
setColor()
method is shown only when you expand the notification.
Best practices for expanded notifications
To decide when to use expanded notifications, follow these guidelines:
- All notifications bridged from the paired phone to the Wear device will use expanded notifications.
-
If a notification is generated by an app running locally on Wear, you should
make the touch
target of your notification launch Notification object with a notification
ID within your app by calling
setContentIntent()
. We recommend that you do not use expanded notifications for notifications generated by an app running locally on Wear.
Add expanded notifications
Expanded Notifications allow you to include additional content and actions for a notification. You choose the level of detail that your app's notifications will provide; however, be judicious with the amount of detail you include in a notification.

Add additional content
To show additional text in your expanded notification, use the
BigTextStyle
.
To add images in your expanded notification, you can use the
BigPictureStyle
. If you want to add more than one image in your expanded
notification, use the
addPage()
method along with the BigPictureStyle
.
Primary action
The expanded notification will contain one primary action, which is the first
action in the notification unless a different action is specified using
setContentAction()
.
Additional actions
To specify additional actions, use
addAction()
or
addActions()
.
The action drawer of the expanded notification contains all available actions.
Add notification actions
In addition to the primary content action defined by
setContentIntent()
,
you can add other actions by passing a PendingIntent
to the
addAction()
method.
For example, the following code shows the same type of notification from above, but adds an action to view the event location on a map.
Kotlin
// Build an intent for an action to view a map val mapIntent = Intent(Intent.ACTION_VIEW) // The channel ID of the notification. val id = "my_channel_01" val mapPendingIntent = Intent(Intent.ACTION_VIEW).let { mapIntent -> mapIntent.data = Uri.parse("geo:0,0?q=" + Uri.encode(location)) PendingIntent.getActivity(this, 0, mapIntent, 0) } val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent)
Java
// Build an intent for an action to view a map Intent mapIntent = new Intent(Intent.ACTION_VIEW); // The channel ID of the notification. String id = "my_channel_01"; Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location)); mapIntent.setData(geoUri); PendingIntent mapPendingIntent = PendingIntent.getActivity(this, 0, mapIntent, 0); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent);
On a phone, the action appears as an additional button attached to the notification. On a wearable, the action appears in the expanded notification after the content text. When the user taps the action, the associated intent is invoked on the phone.
Tip: If your notifications include a "Reply" action (such as for a messaging app), you can enhance the behavior by enabling voice input replies directly from the wearable. For more information, read Adding Voice Input as a notification action.
Add an inline action

Inline action allows users to take actions on a notification from within the notification stream card. On Wear, the inline action appears as an additional button displayed at the bottom of the notification.
Inline actions are optional but recommended for cases in which users are likely to take an action on a notification after viewing the contents in the notification stream card (without going to the expanded notification). Examples of good use cases for inline action on a notification include: replying to a text message, stopping a fitness activity, and archiving an email message.
A notification can provide only one inline action. To display the inline action as an
additional button in the notification, set the
setHintDisplayActionInline()
method to true. When a user taps the inline
action, the system invokes the intent that you specified in the notification action.
The following code snippet adds a hint to display an action inline, and uses the
addAction
method to add the inline action to a notification.
Kotlin
//Wear OS requires a hint to display the reply action inline. val actionExtender = NotificationCompat.Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true) wearableExtender.addAction(actionBuilder.extend(actionExtender).build())
Java
//Wear OS requires a hint to display the reply action inline. Action.WearableExtender actionExtender = new Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true); wearableExtender.addAction(actionBuilder.extend(actionExtender).build());
Add wearable specific-features to a notification
If you ever need to add wearable-specific features to a notification, such as hiding
an app icon from the wearable notification or letting users dictate a text response
with voice input, you can use the
NotificationCompat.WearableExtender
class to specify the options.
To use this API:
-
Create an instance of a
WearableExtender
, setting the wearable-specific options for the notication. -
Create an instance of
NotificationCompat.Builder
, setting the desired properties for your notification as described earlier in this lesson. -
Call
extend()
on the notification and pass in theWearableExtender
. This applies the wearable options to the notification. -
Call
build()
to build the notification.
Note:
If you use the framework's NotificationManager
, some features from
NotificationCompat.WearableExtender
do not work, so make sure to use
NotificationCompat
.
You can sync dismissals (cancellations) of notifications across the user's devices. To
enable a dismissal to be synced, use the
setDismissalId()
method. For each notification, pass a globally unique
ID, as a string, when you call the
setDismissalId()
method. When the notification is dismissed, all other
notifications with the same dismissal ID are dismissed on the watch(es) and on the
companion phone. To retrieve a dismissal ID, use
getDismissalId()
.
Note:
The
setBackground()
method is not supported on Wear 2.0. You can use
NotificationCompat.BigPictureStyle
for notifications that include images.
The
setHintHideIcon()
method is also not supported on Wear 2.0.
Specify wearable-only actions
If you want the actions available on the wearable to be different from those on the phone,
then use
WearableExtender.addAction()
. Once you add an action with this method,
the wearable does not display any other actions added with
NotificationCompat.Builder.addAction()
. The actions added with
WearableExtender.addAction()
appear only on the wearable and they do not
appear on the phone.
Add voice input as a notification action
Voice actions are an important part of the wearable experience. To create an action that
supports voice input, create an instance of
RemoteInput.Builder
that you can add to your notification action.
This class's constructor accepts a string that the system uses as
the key for the voice input, which you'll later use to retrieve the text of the
input in your phone app.

For example, here's how to create a
RemoteInput
object that provides a custom label for the voice input prompt:
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build() }
Java
// Key for the string that's delivered in the action's intent private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; String replyLabel = getResources().getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build();
Add pre-defined text responses

In addition to allowing voice input, you can provide up to five text responses that
the user can select for quick replies. Call
setChoices()
and pass it a string array.
For example, you can define some responses in a resource array:
res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="reply_choices"> <item>Yes</item> <item>No</item> <item>Maybe</item> </string-array> </resources>
Then, inflate the string array and add it to the
RemoteInput
:
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> resources.getStringArray(R.array.reply_choices).let { replyChoices -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build() } }
Java
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; ... String replyLabel = getResources().getString(R.string.reply_label); String[] replyChoices = getResources().getStringArray(R.array.reply_choices); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build();
Receive the voice input as a string
To receive the user's transcribed message in the activity you declared in the reply
action's intent, call
getResultsFromIntent()
, passing in the "Reply" action's intent.
This method returns a Bundle
that contains the text response.
You can then query the Bundle
to obtain the response.
Note:
Do not use Intent.getExtras()
to obtain the
voice result, because the voice input is stored as ClipData
. The
getResultsFromIntent()
method provides a convenient way to receive a
character sequence without having to process the ClipData
yourself.
The following code shows a method that accepts an intent and returns the voice response,
which is referenced by the EXTRA_VOICE_REPLY
key that is used in the
previous examples:
Kotlin
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private fun getMessageText(intent: Intent): CharSequence? = RemoteInput.getResultsFromIntent(intent)?.run { getCharSequence(EXTRA_VOICE_REPLY) }
Java
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private CharSequence getMessageText(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(EXTRA_VOICE_REPLY); } return null; }
Kotlin
// Create an intent for the reply action val actionPendingIntent = Intent(this, ActionActivity::class.java).let { actionIntent -> PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT) } // Create the action val action = NotificationCompat.Action.Builder( R.drawable.ic_action, getString(R.string.label), actionPendingIntent ).build() // Build the notification and add the action via WearableExtender var notification = NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(NotificationCompat.WearableExtender().addAction(action)) .build()
Java
// Create an intent for the reply action Intent actionIntent = new Intent(this, ActionActivity.class); PendingIntent actionPendingIntent = PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Create the action NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_action, getString(R.string.label), actionPendingIntent) .build(); // Build the notification and add the action via WearableExtender Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(new WearableExtender().addAction(action)) .build();
Launch notifications from standalone wearable apps
Creating notifications from a standalone watch app is no different from creating bridged
notifications. Notifications sourced from a standalone Wear app look similar to bridged
notifications but they behave slightly differently. If no
contentIntent
is set or if the notification is bridged from a paired
phone, then tapping the notification opens an
expanded notification.
Whereas, if the notification is originating from a standalone watch app, then tapping
the notification fires the contentIntent
to open your Wear app. To learn
how to create notifications from a standalone app and mimic the expanded notification behavior,
see the
Wear Notifications sample.
By default, notifications are bridged from an app on a companion phone to the paired watch. If you build a standalone watch app and you have a companion phone app, the apps may create duplicate notifications. For information on handling the problem of duplicate notifications, see Bridging Mode for Notifications.