3

My Goal
I am creating an app/package where the wear and handheld are able to both make changes on the Data Layer and be notified of such changes. I am using the GoogleApiClient and the DataApi.DataListener interface.

Current Progress
As of right now, an action on my Wearable successfully updates the counts in the Data Layer, and this change is then detected and reflected in the Handheld via new counts being displayed.

Problem
The detection only works one way. While a change initiated by the Wearable successfully updates counts on the Handheld, a change initiated by the Handheld is not detected on the Wearable.

What I Have Tried
I've looked on StackExchange and Google for hours and I haven't found cases where both the Wearable and the Handheld have been updating data layer objects. In most cases, it was only the Handheld updating something and the Wearable detecting, or vice-versa. One-way communication works just fine for me. I'm needing two-way.

Snippet of Handheld Code

public class ListenActivity extends Activity implements
    DataApi.DataListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {
// ConnectionCallback methods, UI methods not included in snippet

private static final String COUNT_KEY = "com.example.count";
private int count = 0;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_listen);

    handler.post(displayCounts);

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

@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
    for (DataEvent event : dataEvents)
    {
        if (event.getType() == DataEvent.TYPE_CHANGED)
        {
            DataItem item = event.getDataItem();
            if (item.getUri().getPath().compareTo("/count") == 0)
            {
                DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                count = dataMap.getInt(COUNT_KEY);
            }
        }
    }
}

// A UI button calls this method to reset the count, but the Wearable isn't calling its onDataChanged() method.
public void resetCount(View view)
{
    PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
    putDataMapReq.getDataMap().putInt(COUNT_KEY, 0);
    PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
    PendingResult<DataApi.DataItemResult> pendingResult =
            Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
} }

Snippet of Wearable Code

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

// ConnectionCallback methods, UI methods not included in snippet

private static final String COUNT_KEY = "com.example.count";
private int count = 0;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mDismissOverlay = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
    mDismissOverlay.showIntroIfNecessary();
    mGestureDetector = new GestureDetectorCompat(this, new GestureListener());

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApiIfAvailable(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
}

// This method is never called on the Wearable. 
// It isn't detecting the changes made by Handheld's resetCount() method?
@Override
public void onDataChanged(DataEventBuffer dataEvents)
{
    for (DataEvent event : dataEvents)
    {
        if (event.getType() == DataEvent.TYPE_CHANGED)
        {
            DataItem item = event.getDataItem();
            if (item.getUri().getPath().compareTo("/count") == 0)
            {
                DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                count = dataMap.getInt(COUNT_KEY);
            }
        }
    }
}

// User taps the screen, this method is called. Works perfectly fine since handheld updates its counts.
private void updateDataLayer()
{
    PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
    putDataMapReq.getDataMap().putInt(COUNT_KEY, count);
    PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
    PendingResult<DataApi.DataItemResult> pendingResult =
            Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
} }
meta.orphic
  • 58
  • 1
  • 8
  • Is there more code in your Wearable where you call [DataApi.addListener](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi#addListener(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.wearable.DataApi.DataListener)) (such as in an `onConnected()` method)? Any particular reason you are registering your listener in each activity rather than a [WearableListenerService](https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService) which would work whether your activity is running or not? – ianhanniballake Jun 24 '15 at 20:23
  • 1
    I have an app that does this. The code is the same on both sides, I have a shared data manager class that both activities use. A couple things to keep in mind; your activity will be notified even if it was the one that made the change, notifications are only sent if the data is different that it was before (sending the same string twice will be ignored) and sometimes there is stale data in the data map. For each data item, I store a device id and timestamp to account for this. Post more code of your code and we may be able to find the issue. – blackcj Jun 24 '15 at 22:19
  • @ianhanniballake Yes, I add the Listener in the onConnected() method. The reason I am registering my listener in each activity is because what I'm implementing is a single module of a larger app, and the rest of the app doesn't require data listening capabilities. However, I'm contemplating using WearableListenerService anyway, based on all of your answers/comments. – meta.orphic Jun 25 '15 at 18:26
  • @blackcj Thanks for the heads up. I figured out all of those things by stepping through the code multiple times. I'm going to go ahead with everyone's suggestion, including yours, and use a separate/shared data manager class. – meta.orphic Jun 25 '15 at 18:27

1 Answers1

2

That may be because you are listening to events in Activity. I'm using WearableListenerService and it works for in in both ways.

You can find an example here: Handling Data Layer Events

Nick Moskalenko
  • 941
  • 9
  • 10
  • For your class extending WearableListenerService, are you connecting to the GoogleApiClient immediately in onCreate() or do you only connect to send data, as in the example you linked? – meta.orphic Jun 26 '15 at 17:12
  • I played around with extending the WearableListenerService and managed to get things working. Thanks a lot! – meta.orphic Jul 01 '15 at 18:03