Home | History | Annotate | Download | only in data-layer
      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&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
    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     &#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
    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