Using GoogleApiClient from Push Notification IntentService to Send Data to Android Wear
Asked Answered
Q

2

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");
        }
    }
}
Quinidine answered 22/7, 2014 at 0:43 Comment(0)
M
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!

Milker answered 25/7, 2014 at 18:4 Comment(2)
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.Unavailing
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 ?Sidell
F
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.

Fermentative answered 22/7, 2014 at 1:7 Comment(8)
That was it. Thanks for the quick help!Quinidine
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?Quinidine
@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?Fermentative
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.Quinidine
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: tinyurl.com/mmbrh7w Does this mean it's not possible to use in an IntentService?Quinidine
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();Quinidine
@Quinidine 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?Fermentative
Here is the response that I'm getting. imgur.com/EZV2jDc The wear device never receives the message in WearableListenerService.onDataChangedQuinidine
M
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!

Milker answered 25/7, 2014 at 18:4 Comment(2)
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.Unavailing
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 ?Sidell

© 2022 - 2024 — McMap. All rights reserved.