original source : https://developer.android.com/training/wearables/data-layer/events.html

Handling Data Layer Events

When you make a call to the Data Layer API, you can receive the status of the call when it completes.

Note: A Wear app can communicate with a phone app using the Data Layer API, but connecting to a network using this API is discouraged

Wait for the Status of Data Layer Calls

때때로 

Data Layer API call 작업(예를 들어 

putDataItem()

)은 

PendingResult를 결과로 되돌린다. 이때 이 

PendingResult 를 처리하는 방법에는 두가지가 있다.  (synchronously or asynchronously)

          Asynchronous calls(main thread에서 호출하는 경우)

If your code is running on the main UI thread, do not make blocking calls to the Data Layer API. You can run the calls asynchronously by adding a callback method to the PendingResult object, which fires when the operation is completed(버튼 클릭리스너를 만들어 버튼에 연결하듯 처리하는 방법)

pendingResult.setResultCallback(new ResultCallback<DataItemResult>() {
   @Override
   public void onResult(final DataItemResult result) {
       if(result.getStatus().isSuccess()) {
           Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
       }
   }
});

          Synchronous calls(다른 thread에서 호출하는 경우)

If your code is running on a separate handler thread in a background service (which is the case in a WearableListenerService), it’s fine for the calls to block. In this case, you can call await() on the PendingResult object, which blocks until the request completes and returns a Result object:

DataItemResult result = pendingResult.await();
if(result.getStatus().isSuccess()) {
   Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
}

Listen for Data Layer Events

data layer synchronizes and sends data across the handheld and wearable.

To listen for data layer events, you have two options:

          With a WearableListenerService

You typically create instances of this service in both your wearable and handheld apps. If you are not interested in data events in one of these apps, then you don’t need to implement this service in that particular app.

Some of the events you can listen for using WearableListenerService are as follows:

  • onDataChanged(): Whenever a data item object is created, deleted, or changed, the system triggers this callback on all connected nodes.
  • onMessageReceived(): A message sent from a node triggers this callback on the target node.
  • onCapabilityChanged(): When a capability that an instance of your app advertises becomes available on the network, that event triggers this callback. If you’re looking for a nearby node you can query the isNearby() method of the nodes provided in the callback.

In addition to those on this list, you can listen for events from ChannelApi.ChannelListener, such as onChannelOpened().

All of the above events are executed in a background thread, not on the main thread.

To create a WearableListenerService, follow these steps:

  1. Create a class that extends WearableListenerService.
  2. Listen for the events that you’re interested in, such as onDataChanged().
  3. Declare an intent filter in your Android manifest to notify the system about your WearableListenerService. This declaration allows the system to bind your service as needed.
public class DataLayerListenerService extends WearableListenerService {

   private static final String TAG = "DataLayerSample";
   private static final String START_ACTIVITY_PATH = "/start-activity";
   private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

   @Override
   public void onDataChanged(DataEventBuffer dataEvents) {
       if (Log.isLoggable(TAG, Log.DEBUG)) {
           Log.d(TAG, "onDataChanged: " + dataEvents);
       }

       GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
               .addApi(Wearable.API)
               .build();

       ConnectionResult connectionResult =
               googleApiClient.blockingConnect(30, TimeUnit.SECONDS);

       if (!connectionResult.isSuccess()) {
           Log.e(TAG, "Failed to connect to GoogleApiClient.");
           return;
       }

       // Loop through the events and send a message
       // to the node that created the data item.
       for (DataEvent event : dataEvents) {
           Uri uri = event.getDataItem().getUri();

           // Get the node id from the host value of the URI
           String nodeId = uri.getHost();
           // Set the data of the message to be the bytes of the URI
           byte[] payload = uri.toString().getBytes();

           // Send the RPC
           Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
                   DATA_ITEM_RECEIVED_PATH, payload);
       }
   }
}

          Using filters with WearableListenerService

<service android:name=".DataLayerListenerService">
 <intent-filter>
     <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
     <data android:scheme="wear" android:host="*"
              android:path="/start-activity" />
 </intent-filter>
</service>

manifest에 위와 같이 작성한 서비스를 등록하는 과정설명. 위의 경우 the watch listens for the /start-activity data item, and the phone listens for the /data-item-received message response. 

To match on a wildcard host, use host="*". To match on a specific host, specify host=<node_id>.

For more information on the filter types that Wear supports, see the API reference documentation for WearableListenerService.

For more information on data filters and matching rules, see the API reference documentation for the data manifest element.

When matching intent filters, there are two important rules to remember:

  • If a scheme is not specified for the intent filter, the system ignores all the other URI attributes.
  • If no host is specified for the filter, the system ignores all the path attributes.

          

With a live listener

If your app only cares about data-layer events when the user is interacting with the app, it may not need a long-running service to handle every data change. In such a case, you can listen for events in an activity by implementing one or more of the following interfaces:

To create an activity that listens for data events:

An alternative to adding listeners in onConnected() and removing them in onStop() is to add a filtered listener in an activity’s onResume() and remove it in onPause(), to only receive data that is relevant to the current application state.

public class MainActivity extends Activity implements
       DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {

   private GoogleApiClient mGoogleApiClient;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       setContentView(R.layout.main);
       mGoogleApiClient = new GoogleApiClient.Builder(this)
               .addApi(Wearable.API)
               .addConnectionCallbacks(this)
               .addOnConnectionFailedListener(this)
               .build();
   }

   @Override
   protected void onStart() {
       super.onStart();
       if (!mResolvingError) {
           mGoogleApiClient.connect();
       }
   }

   @Override
   public void onConnected(Bundle connectionHint) {
       if (Log.isLoggable(TAG, Log.DEBUG)) {
           Log.d(TAG, "Connected to Google Api Service");
       }
       Wearable.DataApi.addListener(mGoogleApiClient, this);
   }

   @Override
   protected void onStop() {
       if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
           Wearable.DataApi.removeListener(mGoogleApiClient, this);
           mGoogleApiClient.disconnect();
       }
       super.onStop();
   }

   @Override
   public void onDataChanged(DataEventBuffer dataEvents) {
       for (DataEvent event : dataEvents) {
           if (event.getType() == DataEvent.TYPE_DELETED) {
               Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
           } else if (event.getType() == DataEvent.TYPE_CHANGED) {
               Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
           }
       }
   }
}



Using filters with live listeners

Just as you can specify intent filters for manifest-based WearableListenerService objects, you can also use intent filters when registering a listener through the Wearable API. The same rules are applicable to both API-based listeners manifest-based listeners.

A common pattern is to register a listener with a specific path or path prefix in an activity’s onResume() method, and to remove the listener in the activity’s onPause() method. Implementing listeners in this fashion allows your app to more selectively receive events, improving its design and efficiency.

Comments are closed.

Post Navigation