5

This is a follow up question to... Android Wear Bundled Notifications and Background Images

I'd like to create a Android Wear GridViewPager layout that get's created when a new push notification comes in.

Below is my code that initializes a GoogleApiClient connection when a new message comes in so I can then send data to the wear app which then creates the GridView Pager.

My problem is that the GoogleApiClient never gets a connection. I've successfully run the SynchonizedNotifications sample app in the sdk folder so I know my device and watch are paired correctly.

Below is current code...

public class GCMIntentService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener{

    @Override
    protected void onHandleIntent(Context context, Intent intent) {

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

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

        // Extract the payload from the message
        Bundle extras = intent.getExtras();
        if (this.mGoogleApiClient.isConnected())        {

           // sending a simple message works
           MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(mGoogleApiClient,
                node.getId(), "path", null).await();

            PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(Constants.BOTH_PATH);
            putDataMapRequest.getDataMap().putString(Constants.KEY_CONTENT, "content");
            putDataMapRequest.getDataMap().putString(Constants.KEY_TITLE, "title");
            PutDataRequest request = putDataMapRequest.asPutDataRequest();

            // push data to wear app here
            Wearable.DataApi.putDataItem(mGoogleApiClient, request)
                .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                    @Override
                    public void onResult(DataApi.DataItemResult dataItemResult) {
                        if (!dataItemResult.getStatus().isSuccess()) {
                            Log.e(TAG, "Failed to set the data, status: " + dataItemResult.getStatus().getStatusCode());
                        }else{
                            // get here, but no message received from wear
                            Log.i(TAG,"SUCCESSFUL RESPONSE RECEIVED FROM WEAR");
                        }
                        mGoogleApiClient.disconnect();
                    }
                });

        } else {
            Log.e(TAG, "no Google API Client connection");
        }
    }
}
Community
  • 1
  • 1
TWilly
  • 4,863
  • 3
  • 43
  • 73

2 Answers2

6

First of all, if this is your full code, you're not actually calling connect() on the GoogleApiClient.

Secondly, connect() is asynchronous, so you cannot just do something like

mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) ... 

You need to wait for the connection callbacks instead. Or, if you're executing this code in a background thread, you can use blockingConnect() instead.

matiash
  • 54,791
  • 16
  • 125
  • 154
  • That was it. Thanks for the quick help! – TWilly Jul 22 '14 at 02:31
  • I was able to get connected and I'm able to send a message via Wearable.DataApi.putDataItem and I get a success response back, but the wearable device is not getting the message. The wearable has received the message 2 out of 50 tries so far. I've implemented the same code that sends the message to the wearable in the main activity of the handset and it works every time there. I upgraded my Push notification receiver to use WakefulBroadcastReceiver and I still get the same results. Any ideas? – TWilly Jul 24 '14 at 00:21
  • @Twilly You should disconnect only _after_ the push is actually performed, since that is asynchronous too, either with `await()` or inside a listener. Maybe you could post your `push data to wear app here`? – matiash Jul 24 '14 at 00:32
  • Thanks for the quick response. I moved the disconnect call inside the response call back and still don't see the response come through on the wearable. I added code to my initial question that shows sending of the data. – TWilly Jul 24 '14 at 00:40
  • From the docs, it says.... You should instantiate a client object in your Activity's onCreate(Bundle) method and then call connect() in onStart() and disconnect() in onStop(), regardless of the state. Doc: http://tinyurl.com/mmbrh7w Does this mean it's not possible to use in an IntentService? – TWilly Jul 24 '14 at 00:46
  • Also, the following works fine but I need to send more than just a simple message. // test send message MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), "path", null).await(); – TWilly Jul 24 '14 at 00:57
  • @TWilly AFAIK, service or Activity should make no difference whatsoever in regards to `GoogleApiClient`. I'm a bit lost as to your current status though :/ Are you getting the "SUCCESSFUL RESPONSE..." message but the wearable doesn't have the data available? – matiash Jul 24 '14 at 22:11
  • Here is the response that I'm getting. http://imgur.com/EZV2jDc The wear device never receives the message in WearableListenerService.onDataChanged – TWilly Jul 24 '14 at 23:14
6

It looks like your data isn't ever changing. When you're using the DataItem API approach, don't think of it as sending data over from the device to the wearable (or vice versa). Instead, remember that you're just manipulating a cache that is shared across devices: you're syncing data, not transferring it.

This ultimately means that your listener won't trigger unless the data is changed. That's why the method is called onDataChanged(). The underlying API handles updating the cache with your PutDataRequest intelligently to be much more efficient. If you're syncing a payload that contains the same information, you won't notice anything.

So try this: add a timestamp to your payload. Maybe something like putDataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis()); Your payload will be different each time, and you should see that onDataChanged() will now trigger.

Yeah, it took me a while to figure this out!

Makario
  • 2,097
  • 21
  • 19
  • It's not always the data changes are picked up, I have a DataMap containing an Asset and even with a cache buster, it's not always transferred. Not even a cache buster fields seems to do the job. – Sveinung Kval Bakken Jul 25 '14 at 21:45
  • HI All, onDataChanged() doesnt gets called when sending a specific byteArray in PutDataMapRequest. This is when I capture a audio in watch and sync with Phone. First time onDataChanged() gets called, audio plays nicely on phone but second time onwards, onDataChanged() never triggers. Any clue ? – Vny Kumar Dec 02 '14 at 09:42