| page.title=Syncing Data Items | |
| @jd:body | |
| <div id="tb-wrapper"> | |
| <div id="tb"> | |
| <h2>This lesson teaches you to</h2> | |
| <ol> | |
| <li><a href="#SyncData">Sync Data with a Data Map</a></li> | |
| <li><a href="#ListenEvents">Listen for Data Item Events</a></li> | |
| </ol> | |
| </div> | |
| </div> | |
| <p> | |
| A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> | |
| defines the data interface that the system uses to synchronize data between handhelds | |
| and wearables. A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> generally | |
| consists of the following items:</p> | |
| <ul> | |
| <li><b>Payload</b> - A byte array, which you can set with whatever data you wish, allowing you | |
| to do your own object serialization and deserialization. The size of the payload is limited | |
| to 100KB.</li> | |
| <li><b>Path</b> - A unique string that must start with a forward slash (for instance, | |
| <code>"/path/to/data"</code>)</li> | |
| </ul> | |
| <p> | |
| You normally don't implement <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> | |
| directly. Instead, you: | |
| <ol> | |
| <li>Create a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object, | |
| specifying a string path to uniquely identify the item. | |
| </li> | |
| <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])"> | |
| <code>setData()</code></a> to set the payload. | |
| </li> | |
| <li> | |
| If a delay in syncing would negatively impact user experience, call | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> | |
| {@code setUrgent()}</a>. | |
| </li> | |
| <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. | |
| </li> | |
| </ol> | |
| <p> | |
| When requesting data items, the system returns objects that properly implement the | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code> | |
| </a> interface. However, instead of working with raw bytes using | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])"> | |
| <code>setData()</code></a>, we recommend you <a href="#SyncData">use a data map</a>, which exposes | |
| a data item in an easy-to-use {@link android.os.Bundle}-like interface. | |
| </p> | |
| <h2 id="SyncData">Sync Data with a Data Map</h2> | |
| <p> | |
| When possible, use the <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html"> | |
| <code>DataMap</code></a> class. | |
| This approach lets you work with data items in the form of an Android {@link android.os.Bundle}, | |
| so the system does object serialization and deserialization for you, and you can manipulate data | |
| with key-value pairs. | |
| </p> | |
| <p>To use a data map:</p> | |
| <ol> | |
| <li>Create a | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html"><code>PutDataMapRequest</code></a> | |
| object, setting the path of the data item. | |
| <p class="note"><b>Note:</b> The path string is a unique identifier for the | |
| data item that allows you to access it from either side of the connection. The path must begin | |
| with a forward slash. If you're using hierarchical data in your | |
| app, you should create a path scheme that matches the structure of the data. | |
| </p> | |
| </li> | |
| <li>Call | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#getDataMap()"><code>PutDataMapRequest.getDataMap()</code></a> | |
| </a> to obtain a data map that you can set values on.</li> | |
| <li>Set any desired values for the data map using the <code>put...()</code> methods, such as | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html#putString(java.lang.String, java.lang.String)"><code>putString()</code></a>. | |
| </li> | |
| <li> | |
| If a delay in syncing would negatively impact user experience, call | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> | |
| {@code setUrgent()}</a>. | |
| </li> | |
| <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#asPutDataRequest()"><code>PutDataMapRequest.asPutDataRequest()</code></a> | |
| to obtain a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object. | |
| </li> | |
| <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. | |
| <p class="note"><b>Note:</b> | |
| If the handset and wearable devices are disconnected, | |
| the data is buffered and synced when the connection is re-established. | |
| </p> | |
| </li> | |
| </ol> | |
| <p>The <code>increaseCounter()</code> method in the following example shows how to create a | |
| data map and put data in it:</p> | |
| <pre> | |
| public class MainActivity extends Activity implements | |
| DataApi.DataListener, | |
| GoogleApiClient.ConnectionCallbacks, | |
| GoogleApiClient.OnConnectionFailedListener { | |
| private static final String COUNT_KEY = "com.example.key.count"; | |
| private GoogleApiClient mGoogleApiClient; | |
| private int count = 0; | |
| ... | |
| // Create a data map and put data in it | |
| private void <strong>increaseCounter</strong>() { | |
| PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count"); | |
| putDataMapReq.getDataMap().putInt(COUNT_KEY, count++); | |
| PutDataRequest putDataReq = putDataMapReq.asPutDataRequest(); | |
| PendingResult<DataApi.DataItemResult> pendingResult = | |
| Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq); | |
| } | |
| ... | |
| } | |
| </pre> | |
| <p>For more information about handling the | |
| <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"> | |
| <code>PendingResult</code></a> object, see | |
| <a href="{@docRoot}training/wearables/data-layer/events.html#Wait">Wait for the Status of Data | |
| Layer Calls</a>.</p> | |
| <h3>Set DataItem priority</h3> | |
| <p> | |
| In <a href="https://developers.google.com/android/guides/releases">Google Play services 8.3 and later</a>, | |
| the | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi">{@code DataApi}</a> interface | |
| allows urgent requests for syncing of | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>. | |
| Normally, the system may delay delivery of | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> | |
| to the Wear network in order to improve battery life | |
| for user devices, but if a delay in syncing | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> | |
| would negatively impact user experience, you | |
| can mark them as urgent. For example, in a remote control app where the user expects their actions to be | |
| reflected immediately, you can have the system sync your | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a> | |
| immediately by calling | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> | |
| {@code setUrgent()}</a>. | |
| </p> | |
| <p> | |
| If you do not call | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> | |
| {@code setUrgent()}</a>, the system may delay up to 30 minutes before syncing non-urgent | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem">{@code DataItems}</a>, | |
| but you can usually expect the delay to be a few minutes, if at all. | |
| The default urgency is now non-urgent, so you must use | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest#setUrgent()"> | |
| {@code setUrgent()}</a> if you wish to retain the immediate-sync behavior that | |
| existed in previous versions of the Wear API. | |
| </p> | |
| <h2 id="ListenEvents">Listen for Data Item Events</h2> | |
| <p>If one side of the data layer connection changes a data item, you probably want | |
| to be notified of any changes on the other side of the connection. | |
| You can do this by implementing a listener for data item events.</p> | |
| <p>The code snippet in the following example notifies your app when the value of the | |
| counter defined in the previous example changes:</p> | |
| <pre> | |
| public class MainActivity extends Activity implements | |
| DataApi.DataListener, | |
| GoogleApiClient.ConnectionCallbacks, | |
| GoogleApiClient.OnConnectionFailedListener { | |
| private static final String COUNT_KEY = "com.example.key.count"; | |
| private GoogleApiClient mGoogleApiClient; | |
| private int count = 0; | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_main); | |
| mGoogleApiClient = new GoogleApiClient.Builder(this) | |
| .addApi(Wearable.API) | |
| .addConnectionCallbacks(this) | |
| .addOnConnectionFailedListener(this) | |
| .build(); | |
| } | |
| @Override | |
| protected void onResume() { | |
| super.onResume(); | |
| mGoogleApiClient.connect(); | |
| } | |
| @Override | |
| public void onConnected(Bundle bundle) { | |
| <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this); | |
| } | |
| @Override | |
| protected void onPause() { | |
| super.onPause(); | |
| <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this); | |
| mGoogleApiClient.disconnect(); | |
| } | |
| @Override | |
| public void <strong>onDataChanged</strong>(DataEventBuffer dataEvents) { | |
| for (DataEvent event : dataEvents) { | |
| if (event.getType() == DataEvent.TYPE_CHANGED) { | |
| // DataItem changed | |
| DataItem item = event.getDataItem(); | |
| if (item.getUri().getPath().compareTo("/count") == 0) { | |
| DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap(); | |
| updateCount(dataMap.getInt(COUNT_KEY)); | |
| } | |
| } else if (event.getType() == DataEvent.TYPE_DELETED) { | |
| // DataItem deleted | |
| } | |
| } | |
| } | |
| // Our method to update the count | |
| private void updateCount(int c) { ... } | |
| ... | |
| } | |
| </pre> | |
| <p>This activity implements the | |
| <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"> | |
| <code>DataItem.DataListener</code></a> interface. This activity adds itself as a listener | |
| for data item events inside the <code>onConnected()</code> method and removes the listener | |
| in the <code>onPause()</code> method.</p> | |
| <p>You can also implement the listener as a service. For more information, see | |
| <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer | |
| Events</a>.</p> |