1 page.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> 18 A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> 19 defines the data interface that the system uses to synchronize data between handhelds 20 and wearables. A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> generally 21 consists 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> 31 You normally don't implement <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> 32 directly. 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> 53 When 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 58 a 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> 64 When possible, use the <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html"> 65 <code>DataMap</code></a> class. 66 This approach lets you work with data items in the form of an Android {@link android.os.Bundle}, 67 so the system does object serialization and deserialization for you, and you can manipulate data 68 with 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> 76 object, setting the path of the data item. 77 <p class="note"><b>Note:</b> The path string is a unique identifier for the 78 data item that allows you to access it from either side of the connection. The path must begin 79 with a forward slash. If you're using hierarchical data in your 80 app, 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 113 data map and put data in it:</p> 114 115 <pre> 116 public 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<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 145 Layer Calls</a>.</p> 146 147 148 <h3>Set DataItem priority</h3> 149 150 <p> 151 In <a href="https://developers.google.com/android/guides/releases">Google Play services 8.3 and later</a>, 152 the 153 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi">{@code DataApi}</a> interface 154 allows urgent requests for syncing of 155 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>. 156 Normally, the system may delay delivery of 157 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> 158 to the Wear network in order to improve battery life 159 for user devices, but if a delay in syncing 160 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> 161 would negatively impact user experience, you 162 can mark them as urgent. For example, in a remote control app where the user expects their actions to be 163 reflected immediately, you can have the system sync your 164 <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> 165 immediately by calling 166 <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> 167 {@code setUrgent()}</a>. 168 </p> 169 170 <p> 171 If 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>, 175 but you can usually expect the delay to be a few minutes, if at all. 176 The 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 179 existed 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 185 to be notified of any changes on the other side of the connection. 186 You 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 189 counter defined in the previous example changes:</p> 190 191 <pre> 192 public 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 @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 @Override 215 protected void onResume() { 216 super.onResume(); 217 mGoogleApiClient.connect(); 218 } 219 220 @Override 221 public void onConnected(Bundle bundle) { 222 <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this); 223 } 224 225 @Override 226 protected void onPause() { 227 super.onPause(); 228 <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this); 229 mGoogleApiClient.disconnect(); 230 } 231 232 @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 258 for data item events inside the <code>onConnected()</code> method and removes the listener 259 in 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 263 Events</a>.</p> 264