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&lt;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;

    &#64;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();
    }

    &#64;Override
    protected void onResume() {
        super.onResume();
        mGoogleApiClient.connect();
    }

    &#64;Override
    public void onConnected(Bundle bundle) {
        <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
    }

    &#64;Override
    protected void onPause() {
        super.onPause();
        <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
        mGoogleApiClient.disconnect();
    }

    &#64;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>