By default, notifications are bridged (shared) 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 duplicate notifications. Wear OS by Google includes features to handle this problem of duplicate notifications.
Refer to the following related resources:
Note: You can use Firebase Cloud Messaging (FCM) to send notification alerts to devices. See Engage your users across Android, iOS and Chrome.
Developers can change the behavior of notifications with one or more of the following:
- Specify a bridging configuration in the manifest file
- Specify a bridging configuration at runtime
- Set a dismissal ID so notification dismissals are synced across devices
Specify a bridging configuration in the manifest file
An app's Android manifest file can indicate that notifications from the
corresponding phone app should not be bridged to the watch. Specifically,
to prevent bridging of notifications from a phone app, you can use a
<meta-data>
entry in the manifest file of the watch
app (e.g. the standalone watch app), as follows:
com.google.android.wearable.notificationBridgeMode
Add that <meta-data>
entry as a child of the
<application>
element. Set that entry to NO_BRIDGING
to prevent bridging:
<application> ... <meta-data android:name="com.google.android.wearable.notificationBridgeMode" android:value="NO_BRIDGING" /> ... </application>
The default bridging behavior occurs if you do not include the <meta-data>
entry or if you specify a value of BRIDGING
instead of NO_BRIDGING
.
The bridging configuration that is set in the manifest takes effect as soon as a watch app is installed.
Specify a bridging configuration at runtime
You can use the Bridging mode feature to specify a bridging configuration at runtime.
Specifically, you use the
BridgingManager
class.
You can set a bridging mode, and optionally set tags for notifications that are exempt
from the bridging mode, using a BridgingManager
object. Specifically,
create a
BridgingConfig
object and set it as shown in this section.
Specifying a bridging configuration at runtime overrides a bridging-related setting in the Android manifest file.
Disable bridging for all notifications
You can disable bridging for all notifications, as follows:
Kotlin
BridgingManager.fromContext(context).setConfig( BridgingConfig.Builder(context, false).build() )
Java
BridgingManager.fromContext(context).setConfig( new BridgingConfig.Builder(context, false) .build());
If the above configuration is not set, the bridging mode defaults to true.
Exempt notifications that are tagged
You can disable bridging for all notifications except those with certain tags.
For example, you can disable bridging for all notifications except those
tagged as foo
, bar
, or baz
.
Kotlin
BridgingManager.fromContext(context).setConfig( BridgingConfig.Builder(context, false) .addExcludedTags(listOf("foo", "bar", "baz")) .build() )
Java
BridgingManager.fromContext(context).setConfig( new BridgingConfig.Builder(context, false) .addExcludedTags(Arrays.asList("foo", "bar", "baz")) .build());
As another example, you can exclude notifications with specific tags
(such as foo
or bar
):
Kotlin
BridgingManager.fromContext(context).setConfig( BridgingConfig.Builder(context, false) .addExcludedTag("foo") .addExcludedTag("bar") .build() )
Java
BridgingManager.fromContext(context).setConfig( new BridgingConfig.Builder(context, false) .addExcludedTag("foo") .addExcludedTag("bar") .build());
Set a bridge tag
A bridge tag can be set on a notification by using the
setBridgeTag(String)
method as follows:
Kotlin
val notification = NotificationCompat.Builder(context, channelId) // ... set other fields ... .extend( NotificationCompat.WearableExtender() .setBridgeTag("foo") ) .build()
Java
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId) // ... set other fields ... .extend( new NotificationCompat.WearableExtender() .setBridgeTag("foo")); Notification notification = notificationBuilder.build();
Prevent bridging in an existing app
In an existing app, you may already have disabled bridging for when a phone is not connected when an alert is received. In this case, you may still want to dismiss the notification across other devices when it is dismissed in a watch app.
An existing way to prevent bridging is with the Notification.Builder
class; specify true
in the
setLocalOnly
method.
However, this way to prevent bridging may not be preferable. For example, if a user
installs a phone app but not the corresponding watch app, the setLocalOnly
method could prevent the bridging of helpful notifications. Additionally, users may
have multiple paired watches and the watch app may not be installed on all of them.
Use a dismissal ID to sync notification dismissals
If you prevent bridging with the
Bridging mode feature, dismissals (cancellations) of notifications are not synced
across a user's devices. However, the following methods of the
NotificationCompat.WearableExtender
class enable you to use dismissal
IDs:
Kotlin
fun setDismissalId(dismissalId: String): WearableExtender fun getDismissalId(): String
Java
public WearableExtender setDismissalId(String dismissalId) public String getDismissalId()
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()
.
In the following example, syncing of dismissals is enabled because a globally unique ID is specified for a new notification:
Kotlin
val notification = NotificationCompat.Builder(context, channelId) // ... set other fields ... .extend( NotificationCompat.WearableExtender() .setDismissalId("abc123") ) .build()
Java
NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender().setDismissalId("abc123"); Notification notification = new NotificationCompat.Builder(context) // ... set other fields ... .extend(wearableExtender) .build();
Dismissal IDs work if a watch is paired to an Android phone, but not if a watch is paired to an iPhone.
Best practices for bridged notifications
Bridged notifications take time to be pushed or removed from a wearable device. As you design your notifications, make sure to avoid unexpected behavior caused by this latency. The guidelines below will help you to ensure that your bridged notifications work with asynchronous notifications:
- If you cancel a notification on the phone, it may take some time for the corresponding notification on the watch to be canceled. During this time, a user could send one of the pending intents on that notification. For this reason, your app should be prepared to receive pending intents from notifications it has canceled. Thus, when canceling notifications, you should make sure to keep those notifications’ pending intent receivers valid.
- Do not cancel and retrigger an entire stack of notifications at one time. Only modify or remove the notifications that have actually been modified. This avoids the latency on updating the wearable device and ensures that the impact of your app on battery life is minimal.
Design considerations
Wear OS notifications have their own design guidelines. For more information, review the Material Design page.
- All notifications bridged from the paired phone to the Wear device use expanded notifications.
- To learn when to use the different notification templates supported on Wear OS, read the Notifications patterns design guide.
- To learn how to style your Wear notifications, read the Notifications style design guide.
-
If you have a chat messaging app, your notifications should use
NotificationCompat.MessagingStyle
. Wear uses the chat messages included in aMessagingStyle
notification (seeaddMessage()
) to provide a rich chat app-like experience in the expanded notification. -
Add an inline action
(
setHintDisplayActionInline(true)
) within the notification stream to include a primary action that a user can quickly take on a notification. Examples of good use cases for an inline action within a notification stream include replying to a text message, stopping a fitnes activity, or archiving an email message. -
Enable Smart Reply
(
setAllowGeneratedReplies(true)
) for yourMessagingStyle
notifications.