• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Syncing Data Items
2
3@jd:body
4
5<div id="tb-wrapper">
6<div id="tb">
7
8<h2>This lesson teaches you to</h2>
9<ol>
10  <li><a href="#SyncData">Sync Data with a Data Map</a></li>
11  <li><a href="#ListenEvents">Listen for Data Item Events</a></li>
12</ol>
13
14</div>
15</div>
16
17<p>
18A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
19defines the data interface that the system uses to synchronize data between handhelds
20and wearables. A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> generally
21consists of the following items:</p>
22<ul>
23  <li><b>Payload</b> - A byte array, which you can set with whatever data you wish, allowing you
24  to do your own object serialization and deserialization. The size of the payload is limited
25  to 100KB.</li>
26  <li><b>Path</b> - A unique string that must start with a forward slash (for instance,
27  <code>"/path/to/data"</code>)</li>
28</ul>
29
30<p>
31You normally don't implement <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
32directly. Instead, you:
33
34<ol>
35  <li>Create a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object,
36  specifying a string path to uniquely identify the item.
37  </li>
38  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">
39  <code>setData()</code></a> to set the payload.
40  </li>
41
42  <li>
43  If a delay in syncing would negatively impact user experience, call
44  <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()">
45  {@code setUrgent()}</a>.
46  </li>
47
48  <li>Call <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>DataApi.putDataItem()</code></a> to request the system to create the data item.
49  </li>
50  </ol>
51
52<p>
53When requesting data items, the system returns objects that properly implement the
54<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code>
55</a> interface. However, instead of working with raw bytes using
56<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">
57<code>setData()</code></a>, we recommend you <a href="#SyncData">use a data map</a>, which exposes
58a data item in an easy-to-use {@link android.os.Bundle}-like interface.
59</p>
60
61
62<h2 id="SyncData">Sync Data with a Data Map</h2>
63<p>
64When possible, use the <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html">
65<code>DataMap</code></a> class.
66This approach lets you work with data items in the form of an Android {@link android.os.Bundle},
67so the system does object serialization and deserialization for you, and you can manipulate data
68with key-value pairs.
69</p>
70
71<p>To use a data map:</p>
72
73<ol>
74  <li>Create a
75<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html"><code>PutDataMapRequest</code></a>
76object, setting the path of the data item.
77<p class="note"><b>Note:</b> The path string is a unique identifier for the
78data item that allows you to access it from either side of the connection. The path must begin
79with a forward slash. If you're using hierarchical data in your
80app, you should create a path scheme that matches the structure of the data.
81</p>
82</li>
83<li>Call
84<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#getDataMap()"><code>PutDataMapRequest.getDataMap()</code></a>
85</a> to obtain a data map that you can set values on.</li>
86  <li>Set any desired values for the data map using the <code>put...()</code> methods, such as
87  <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html#putString(java.lang.String, java.lang.String)"><code>putString()</code></a>.
88  </li>
89
90   <li>
91   If a delay in syncing would negatively impact user experience, call
92   <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()">
93   {@code setUrgent()}</a>.
94   </li>
95
96
97  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#asPutDataRequest()"><code>PutDataMapRequest.asPutDataRequest()</code></a>
98  to obtain a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object.
99   </li>
100
101
102  <li>Call <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>DataApi.putDataItem()</code></a> to request the system to create the data item.
103
104  <p class="note"><b>Note:</b>
105
106  If the handset and wearable devices are disconnected,
107  the data is buffered and synced when the connection is re-established.
108  </p>
109  </li>
110</ol>
111
112<p>The <code>increaseCounter()</code> method in the following example shows how to create a
113data map and put data in it:</p>
114
115<pre>
116public class MainActivity extends Activity implements
117        DataApi.DataListener,
118        GoogleApiClient.ConnectionCallbacks,
119        GoogleApiClient.OnConnectionFailedListener {
120
121    private static final String COUNT_KEY = "com.example.key.count";
122
123    private GoogleApiClient mGoogleApiClient;
124    private int count = 0;
125
126    ...
127
128    // Create a data map and put data in it
129    private void <strong>increaseCounter</strong>() {
130        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
131        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
132        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
133        PendingResult&lt;DataApi.DataItemResult> pendingResult =
134                Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
135    }
136
137    ...
138}
139</pre>
140
141<p>For more information about handling the
142<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">
143<code>PendingResult</code></a> object, see
144<a href="{@docRoot}training/wearables/data-layer/events.html#Wait">Wait for the Status of Data
145Layer Calls</a>.</p>
146
147
148<h3>Set DataItem priority</h3>
149
150<p>
151In <a href="https://developers.google.com/android/guides/releases">Google Play services 8.3 and later</a>,
152the
153<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi">{@code DataApi}</a> interface
154allows urgent requests for syncing of
155<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>.
156Normally, the system may delay delivery of
157<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>
158to the Wear network in order to improve battery life
159for user devices, but if a delay in syncing
160<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>
161would negatively impact user experience, you
162can mark them as urgent. For example, in a remote control app where the user expects their actions to be
163reflected immediately, you can have the system sync your
164<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>
165immediately by calling
166<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()">
167{@code setUrgent()}</a>.
168</p>
169
170<p>
171If you do not call
172<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()">
173{@code setUrgent()}</a>, the system may delay up to 30 minutes before syncing non-urgent
174<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>,
175but you can usually expect the delay to be a few minutes, if at all.
176The default urgency is now non-urgent, so you must use
177<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()">
178{@code setUrgent()}</a> if you wish to retain the immediate-sync behavior that
179existed in previous versions of the Wear API.
180</p>
181
182<h2 id="ListenEvents">Listen for Data Item Events</h2>
183
184<p>If one side of the data layer connection changes a data item, you probably want
185to be notified of any changes on the other side of the connection.
186You can do this by implementing a listener for data item events.</p>
187
188<p>The code snippet in the following example notifies your app when the value of the
189counter defined in the previous example changes:</p>
190
191<pre>
192public class MainActivity extends Activity implements
193        DataApi.DataListener,
194        GoogleApiClient.ConnectionCallbacks,
195        GoogleApiClient.OnConnectionFailedListener {
196
197    private static final String COUNT_KEY = "com.example.key.count";
198
199    private GoogleApiClient mGoogleApiClient;
200    private int count = 0;
201
202    &#64;Override
203    protected void onCreate(Bundle savedInstanceState) {
204        super.onCreate(savedInstanceState);
205        setContentView(R.layout.activity_main);
206
207        mGoogleApiClient = new GoogleApiClient.Builder(this)
208                .addApi(Wearable.API)
209                .addConnectionCallbacks(this)
210                .addOnConnectionFailedListener(this)
211                .build();
212    }
213
214    &#64;Override
215    protected void onResume() {
216        super.onResume();
217        mGoogleApiClient.connect();
218    }
219
220    &#64;Override
221    public void onConnected(Bundle bundle) {
222        <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
223    }
224
225    &#64;Override
226    protected void onPause() {
227        super.onPause();
228        <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
229        mGoogleApiClient.disconnect();
230    }
231
232    &#64;Override
233    public void <strong>onDataChanged</strong>(DataEventBuffer dataEvents) {
234        for (DataEvent event : dataEvents) {
235            if (event.getType() == DataEvent.TYPE_CHANGED) {
236                // DataItem changed
237                DataItem item = event.getDataItem();
238                if (item.getUri().getPath().compareTo("/count") == 0) {
239                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
240                    updateCount(dataMap.getInt(COUNT_KEY));
241                }
242            } else if (event.getType() == DataEvent.TYPE_DELETED) {
243                // DataItem deleted
244            }
245        }
246    }
247
248    // Our method to update the count
249    private void updateCount(int c) { ... }
250
251    ...
252}
253</pre>
254
255<p>This activity implements the
256<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html">
257<code>DataItem.DataListener</code></a> interface. This activity adds itself as a listener
258for data item events inside the <code>onConnected()</code> method and removes the listener
259in the <code>onPause()</code> method.</p>
260
261<p>You can also implement the listener as a service. For more information, see
262<a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer
263Events</a>.</p>
264