Skip to content

Most visited

Recently visited


Handling Data Layer Events

When you make a call to the Data Layer API, you can receive the status of the call when it completes. You also can listen for data events, resulting from data changes that your app makes anywhere on the Android Wear network.

Note: A Wear app can communicate with a phone app using the Data Layer API, but connecting to a network using this API is discouraged.

Wait for the Status of Data Layer Calls

Calls to the Data Layer API sometimes return a PendingResult, such as putDataItem(). As soon as the PendingResult is created, the operation is queued in the background. If you do nothing else after this, the operation eventually completes silently. However, you'll usually want to do something with the result after the operation completes, so the PendingResult lets you wait for the result status, either synchronously or asynchronously.

Asynchronous calls

If your code is running on the main UI thread, do not make blocking calls to the Data Layer API. You can run the calls asynchronously by adding a callback method to the PendingResult object, which fires when the operation is completed:

pendingResult.setResultCallback(new ResultCallback<DataItemResult>() {
    public void onResult(final DataItemResult result) {
        if(result.getStatus().isSuccess()) {
            Log.d(TAG, "Data item set: " + result.getDataItem().getUri());

Synchronous calls

If your code is running on a separate handler thread in a background service (which is the case in a WearableListenerService), it's fine for the calls to block. In this case, you can call await() on the PendingResult object, which blocks until the request completes and returns a Result object:

DataItemResult result = pendingResult.await();
if(result.getStatus().isSuccess()) {
    Log.d(TAG, "Data item set: " + result.getDataItem().getUri());

Listen for Data Layer Events

Because the data layer synchronizes and sends data across the handheld and wearable, it is usually necessary to listen for important events. Examples of such events include creation of data items and receipt of messages.

To listen for data layer events, you have two options:

With both these options, you override the data event callback methods for the events you are interested in handling.

With a WearableListenerService

You typically create instances of this service in both your wearable and handheld apps. If you are not interested in data events in one of these apps, then you don't need to implement this service in that particular app.

For example, you can have a handheld app that sets and gets data item objects and a wearable app that listens for these updates to update its UI. The wearable never updates any of the data items, so the handheld app doesn't listen for any data events from the wearable app.

Some of the events you can listen for using WearableListenerService are as follows:

All of the above events are executed in a background thread, not on the main thread.

To create a WearableListenerService, follow these steps:

  1. Create a class that extends WearableListenerService.
  2. Listen for the events that you're interested in, such as onDataChanged().
  3. Declare an intent filter in your Android manifest to notify the system about your WearableListenerService. This declaration allows the system to bind your service as needed.

The following example shows how to implement a simple WearableListenerService:

public class DataLayerListenerService extends WearableListenerService {

    private static final String TAG = "DataLayerSample";
    private static final String START_ACTIVITY_PATH = "/start-activity";
    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

    public void onDataChanged(DataEventBuffer dataEvents) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: " + dataEvents);

        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)

        ConnectionResult connectionResult =
                googleApiClient.blockingConnect(30, TimeUnit.SECONDS);

        if (!connectionResult.isSuccess()) {
            Log.e(TAG, "Failed to connect to GoogleApiClient.");

        // Loop through the events and send a message
        // to the node that created the data item.
        for (DataEvent event : dataEvents) {
            Uri uri = event.getDataItem().getUri();

            // Get the node id from the host value of the URI
            String nodeId = uri.getHost();
            // Set the data of the message to be the bytes of the URI
            byte[] payload = uri.toString().getBytes();

            // Send the RPC
            Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
                    DATA_ITEM_RECEIVED_PATH, payload);

The next section explains how to use an intent filter with this listener.

Using filters with WearableListenerService

An intent filter for the WearableListenerService example shown in the previous section might look like this:

<service android:name=".DataLayerListenerService">
      <action android:name="" />
      <data android:scheme="wear" android:host="*"
               android:path="/start-activity" />

In this filter, the DATA_CHANGED action replaces the previously recommended BIND_LISTENER action so that only specific events wake or launch your app. This change improves system efficiency and reduces battery consumption and other overhead associated with your app. In this example, the watch listens for the /start-activity data item, and the phone listens for the /data-item-received message response.

Standard Android filter matching rules apply. You can specify multiple services per manifest, multiple intent filters per service, multiple actions per filter, and multiple data stanzas per filter. Filters can match on a wildcard host or on a specific one. To match on a wildcard host, use host="*". To match on a specific host, specify host=<node_id>.

You can also match a literal path or path prefix. If you are matching by path or path prefix, you must specify a wildcard or specific host. If you do not do so, the system ignores the path you specified.

For more information on the filter types that Wear supports, see the API reference documentation for WearableListenerService.

For more information on data filters and matching rules, see the API reference documentation for the data manifest element.

When matching intent filters, there are two important rules to remember:

With a live listener

If your app only cares about data-layer events when the user is interacting with the app, it may not need a long-running service to handle every data change. In such a case, you can listen for events in an activity by implementing one or more of the following interfaces:

To create an activity that listens for data events:

  1. Implement the desired interfaces.
  2. In onCreate(), create an instance of GoogleApiClient to work with the Data Layer API.
  3. In onStart(), call connect() to connect the client to Google Play services.
  4. When the connection to Google Play services is established, the system calls onConnected(). This is where you call DataApi.addListener(), MessageApi.addListener(), or CapabilityApi.addListener() to notify Google Play services that your activity is interested in listening for data layer events.
  5. In onStop(), unregister any listeners with DataApi.removeListener(), MessageApi.removeListener(), or CapabilityApi.removeListener().
  6. An alternative to adding listeners in onConnected() and removing them in onStop() is to add a filtered listener in an activity's onResume() and remove it in onPause(), to only receive data that is relevant to the current application state.

  7. Implement onDataChanged(), onMessageReceived(), onCapabilityChanged(), or methods from Channel API listener methods, depending on the interfaces that you implemented. These methods are called on the main thread. (However, in versions of the Google Play Services client library before 8.1, listener methods are not called on the main thread.)

Here's an example that implements DataApi.DataListener:

public class MainActivity extends Activity implements
        DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {

    private GoogleApiClient mGoogleApiClient;

    protected void onCreate(Bundle savedInstanceState) {

        mGoogleApiClient = new GoogleApiClient.Builder(this)

    protected void onStart() {
        if (!mResolvingError) {

    public void onConnected(Bundle connectionHint) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Connected to Google Api Service");
        Wearable.DataApi.addListener(mGoogleApiClient, this);

    protected void onStop() {
        if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
            Wearable.DataApi.removeListener(mGoogleApiClient, this);

    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());

Using filters with live listeners

Just as you can specify intent filters for manifest-based WearableListenerService objects, you can also use intent filters when registering a listener through the Wearable API. The same rules are applicable to both API-based listeners manifest-based listeners.

A common pattern is to register a listener with a specific path or path prefix in an activity’s onResume() method, and to remove the listener in the activity’s onPause() method. Implementing listeners in this fashion allows your app to more selectively receive events, improving its design and efficiency.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields


Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)