12728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lypage.title=Handling Data Layer Events
22728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
32728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly@jd:body
42728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
52728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<div id="tb-wrapper">
62728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<div id="tb">
72728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
82728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h2>This lesson teaches you to</h2>
92728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ol>
102728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="#Wait">Wait for the Status of Data Layer Calls</a></li>
112728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="#Listen">Listen for Data Layer Events</a></li>
122728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ol>
132728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
142728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</div>
152728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</div>
162728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
17eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<p>When you make calls to the Data Layer API, you can receive the status
182728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyof the call when it completes as well as listen for any changes that
192728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lythe call ends up making with listeners.
202728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
212728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
222728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h2 id="Wait">Wait for the Status of Data Layer Calls</h2>
232728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
24eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<p>You'll notice that calls to the Data Layer API sometimes return a
252728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
262728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lysuch as
272728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
282728c2a93abd74ef19e550f3530ee70ea41424b3Robert LyAs soon as the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
292728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lythe operation is queued in the background. If you do nothing else after this, the operation
302728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyeventually completes silently. However, you'll usually want to do something with the result
312728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyafter the operation completes, so the
322728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
332728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lylets you wait for the result status, either synchronously or asynchronously.
342728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
352728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
36eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<h3 id="async-waiting">Asynchronous calls</h3>
37eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<p>If your code is running on the main UI thread, do not make blocking calls
38eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerverato the Data Layer API. You can run the calls asynchronously by adding a callback method
392728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyto the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
402728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lywhich fires when the operation is completed:</p>
412728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
422728c2a93abd74ef19e550f3530ee70ea41424b3Robert LypendingResult.setResultCallback(new ResultCallback&lt;DataItemResult&gt;() {
432728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
442728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    public void onResult(final DataItemResult result) {
452728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if(result.getStatus().isSuccess()) {
467a04794186dcb679501a7a9383caae8df01428d0Chris Smith            Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
477a04794186dcb679501a7a9383caae8df01428d0Chris Smith        }
482728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
492728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly});
502728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</pre>
512728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
52eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<h3 id="sync-waiting">Synchronous calls</h3>
532728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>If your code is running on a separate handler thread in a background service (which is the case
542728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyin a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
552728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyit's fine for the calls to block. In this case, you can call
562728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
57eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerveraon the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
58eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerveraobject, which blocks until the request completes and returns a
59eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<a href="{@docRoot}reference/com/google/android/gms/common/api/Result.html"><code>Result</code></a>
602728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyobject:
612728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
622728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
632728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
642728c2a93abd74ef19e550f3530ee70ea41424b3Robert LyDataItemResult result = pendingResult.await();
652728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyif(result.getStatus().isSuccess()) {
662728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
672728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly}
682728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</pre>
692728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
702728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
712728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h2 id="Listen">Listen for Data Layer Events </h2>
722728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>Because the data layer synchronizes and sends data across the handheld and
732728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lywearable, you normally want to listen for important events, such as when data items
742728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyare created, messages are received, or when the wearable and handset are connected.
752728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
762728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>To listen for data layer events, you have two options:</p>
772728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
782728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ul>
792728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li>Create a service that extends
802728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
812728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
822728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li>Create an activity that implements
832728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>.
842728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
852728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ul>
862728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
87eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<p>With both these options, you override the data event callback methods for the events you
88eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerveraare interested in handling.</p>
892728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
902728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h3 id="listener-service">With a WearableListenerService</h3>
912728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
922728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>
932728c2a93abd74ef19e550f3530ee70ea41424b3Robert LyYou typically create instances of this service in both your wearable and handheld apps. If you
94eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerveraare not interested in data events in one of these apps, then you don't need to implement this
952728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyservice in that particular app.</p>
962728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
972728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>For example, you can have a handheld app that sets and gets data item objects and a wearable app
982728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lythat listens for these updates to update it's UI. The wearable never updates any of the data items,
992728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyso the handheld app doesn't listen for any data events from the wearable app.</p>
1002728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1012728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>You can listen for the following events with
1022728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:</p>
1032728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1042728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ul>
1052728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code></a>
1062728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly- Called when data item objects are created, changed, or deleted. An event on one side of a connection
107321e030202cb74cad0dd8a4950cffe361a5072c8Ricardo Cerveratriggers this callback on both sides.</li>
1082728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)"><code>onMessageReceived()</code></a>
1092728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly-  A message sent from one side of a connection triggers this callback on the other side of the connection.</li>
1102728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)"><code>onPeerConnected()</code></a>
1112728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  and <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onPeerDisconnected(com.google.android.gms.wearable.Node)"><code>onPeerDisconnected()</code></a> -
112eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera  Called when the connection with the handheld or wearable is connected or disconnected.
113eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera  Changes in connection state on one side of the connection trigger these callbacks on both sides
114eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera  of the connection.
1152728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
1162728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ul>
1172728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1182728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>To create a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:</p>
1192728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1202728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ol>
1212728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li>Create a class that extends
1222728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
1232728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
124eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera  <li>Listen for the events that you're interested in, such as
125eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code></a>.
1262728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
1272728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li>Declare an intent filter in your Android manifest to notify the system about your
1282728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
1292728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  This allows the system to bind your service as needed.
1302728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </li>
1312728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ol>
1322728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1332728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <p>The following example shows how to implement a simple
1342728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:
1352728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  </p>
1362728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1372728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
1382728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lypublic class DataLayerListenerService extends WearableListenerService {
1392728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1402728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    private static final String TAG = "DataLayerSample";
1412728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    private static final String START_ACTIVITY_PATH = "/start-activity";
1422728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";
1432728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1442728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
1452728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    public void onDataChanged(DataEventBuffer dataEvents) {
1462728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if (Log.isLoggable(TAG, Log.DEBUG)) {
1472728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            Log.d(TAG, "onDataChanged: " + dataEvents);
1482728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
1492728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        final List<DataEvent> events = FreezableUtils
1502728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .freezeIterable(dataEvents);
1512728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1522728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
1532728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .addApi(Wearable.API)
1542728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .build();
1552728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1562728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        ConnectionResult connectionResult =
1572728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
1582728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1592728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if (!connectionResult.isSuccess()) {
1602728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            Log.e(TAG, "Failed to connect to GoogleApiClient.");
1612728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            return;
1622728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
1632728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1642728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        // Loop through the events and send a message
165bcb15cc1b16f64c6ab3f22b19b6fd7daff48304aLuan Nguyen        // to the node that created the data item.
1662728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        for (DataEvent event : events) {
1672728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            Uri uri = event.getDataItem().getUri();
1682728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1692728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            // Get the node id from the host value of the URI
1702728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            String nodeId = uri.getHost();
171eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera            // Set the data of the message to be the bytes of the URI
1722728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            byte[] payload = uri.toString().getBytes();
1732728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1742728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            // Send the RPC
1752728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
1762728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                    DATA_ITEM_RECEIVED_PATH, payload);
1772728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
1782728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
1792728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly}
180321e030202cb74cad0dd8a4950cffe361a5072c8Ricardo Cervera</pre>
1812728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1822728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>Here's the corresponding intent filter in the Android manifest file:</p>
1832728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1842728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
1852728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly&lt;service android:name=".DataLayerListenerService"&gt;
1862728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  &lt;intent-filter&gt;
1872728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly      &lt;action android:name="com.google.android.gms.wearable.BIND_LISTENER" /&gt;
1882728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  &lt;/intent-filter&gt;
1892728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly&lt;/service&gt;
1902728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</pre>
1912728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1922728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
1932728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h4>Permissions within Data Layer Callbacks</h4>
1942728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
195eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera<p>
196eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo CerveraTo deliver callbacks to your application for data layer events, Google Play services
1972728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lybinds to your <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>,
1982728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyand calls your callbacks via IPC. This has the consequence
1992728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lythat your callbacks inherit the permissions of the calling process.</p>
2002728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2012728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>If you try to perform a privileged operation within a callback, the security check fails because your callback is
2022728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyrunning with the identity of the calling process, instead of the identity of your app's
2032728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyprocess.</p>
2042728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2052728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>To fix this, call {@link android.os.Binder#clearCallingIdentity} </a>,
2062728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyto reset identity after crossing the IPC boundary, and then restore identity with
2072728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly{@link android.os.Binder#restoreCallingIdentity restoreCallingIdentity()} when
2082728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyyou've completed the privileged operation:
2092728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
2102728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2112728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
2122728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lylong token = Binder.clearCallingIdentity();
2132728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lytry {
2142728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    performOperationRequiringPermissions();
2152728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly} finally {
2162728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    Binder.restoreCallingIdentity(token);
2172728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly}
2182728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</pre>
2192728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2202728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<h3 id="Listen">With a Listener Activity</h3>
2212728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2222728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>
2232728c2a93abd74ef19e550f3530ee70ea41424b3Robert LyIf your app only cares about data layer events when the user is interacting
2242728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lywith the app and does not need a long-running service to handle every data
2252728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lychange, you can listen for events in an activity by implementing one or more
2262728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyof the following interfaces:
2272728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2282728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ul>
2292728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a></li>
2302728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.MessageListener.html"><code>MessageApi.MessageListener</code></a></li>
2312728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html"><code>NodeApi.NodeListener</code></a></li>
2322728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ul>
2332728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</p>
2342728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2352728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>To create an activity that listens for data events:</p>
2362728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<ol>
2372728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>Implement the desired interfaces.</li>
2382728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>In {@link android.app.Activity#onCreate}, create an instance of
2392728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>
240eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cerverato work with the Data Layer API.
2412728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>
2422728c2a93abd74ef19e550f3530ee70ea41424b3Robert LyIn {@link android.app.Activity#onStart onStart()}, call <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"><code>connect()</code></a> to connect the client to Google Play services.
2432728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</li>
2442728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>When the connection to Google Play services is established, the system calls
2452728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
2462728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.addListener()</code></a>,
2472728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.addListener()</code></a>,
2482728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  or <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.NodeApi.NodeListener)"><code>NodeApi.addListener()</code></a>
2492728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  to notify Google Play services that your activity is interested in listening for data layer events.
2502728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</li>
2512728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>In {@link android.app.Activity#onStop onStop()}, unregister any listeners with
2522728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
2532728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>,
2542728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lyor <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.NodeApi.NodeListener)"><code>NodeApi.removeListener()</code></a>.
2552728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</li>
2562728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<li>Implement <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code>,
2572728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerConnected(com.google.android.gms.wearable.Node)"><code>onMessageReceived()</code></a>,
2582728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerConnected(com.google.android.gms.wearable.Node)"><code>onPeerConnected()</code></a>, and
2592728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly  <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerDisconnected(com.google.android.gms.wearable.Node)"><code>onPeerDisconnected()</code></a>, depending on the interfaces that you implemented.
2602728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</li>
2612728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly</ol>
2622728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2632728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<p>Here's an example that implements
2642728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
2652728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2662728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly<pre>
2672728c2a93abd74ef19e550f3530ee70ea41424b3Robert Lypublic class MainActivity extends Activity implements
2682728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
2692728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
270c2be8a6da0c193a0592586cfc8bdfdb7903cc055Ricardo Cervera    private GoogleApiClient mGoogleApiClient;
271c2be8a6da0c193a0592586cfc8bdfdb7903cc055Ricardo Cervera
2722728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
2732728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    protected void onCreate(Bundle savedInstanceState) {
2742728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        super.onCreate(savedInstanceState);
2752728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2762728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        setContentView(R.layout.main);
2772728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        mGoogleApiClient = new GoogleApiClient.Builder(this)
2782728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .addApi(Wearable.API)
2792728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .addConnectionCallbacks(this)
2802728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .addOnConnectionFailedListener(this)
2812728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                .build();
2822728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
2832728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
2842728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
2852728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    protected void onStart() {
2862728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        super.onStart();
2872728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if (!mResolvingError) {
2882728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            mGoogleApiClient.connect();
2892728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
2902728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
2912728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
292eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera    &#64;Override
2932728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    public void onConnected(Bundle connectionHint) {
2942728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if (Log.isLoggable(TAG, Log.DEBUG)) {
2952728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            Log.d(TAG, "Connected to Google Api Service");
2962728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
2972728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        Wearable.DataApi.addListener(mGoogleApiClient, this);
2982728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
2992728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
3002728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
3012728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    protected void onStop() {
3022728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
3037a04794186dcb679501a7a9383caae8df01428d0Chris Smith            Wearable.DataApi.removeListener(mGoogleApiClient, this);
3042728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            mGoogleApiClient.disconnect();
3052728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
3062728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        super.onStop();
3072728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
3082728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly
3092728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    &#64;Override
3102728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    public void onDataChanged(DataEventBuffer dataEvents) {
3112728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        for (DataEvent event : dataEvents) {
3122728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            if (event.getType() == DataEvent.TYPE_DELETED) {
3132728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
3142728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
315eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera                Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
3162728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly            }
3172728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly        }
3182728c2a93abd74ef19e550f3530ee70ea41424b3Robert Ly    }
319c2be8a6da0c193a0592586cfc8bdfdb7903cc055Ricardo Cervera}
320eff209d2c40221d2f9be2fd6b0c9cde51dd5362bRicardo Cervera</pre>
321