4

I am making a wear app which fetches data from database(which is on handheld) on launch of app home screen. So when the homepage activity launches, It sends a message using Wearable.MessageApi.sendMessage function from the android wear to handheld. On the handheld I have the WearableListenerService which receives this message in onMessageReceived function and reads database. After reading database it sends putDatamapRequest to the wear.

Now on the wear side, I have another WearableListenerService. In this service, onDataChanged() function is never invoked. It runs at times, so far it ran for 2-3 times but otherwise it doesn't run. It's very random. Also once the data is received in Wear side, I set a static Arraylist, which I use to display data in Activity. But since the onDataChanged function is not always called, it gives empty array list.

Here is my AndroidManifest file of wear app where I declared the service:

   <service
        android:name="com.example.deals.DataListenerService"
        android:enabled="true"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
        </intent-filter>
    </service>

Here is my code to send message from wear to handheld:

mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {

        @Override
        public void onConnected(Bundle bundle) {
                                    Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
                        @Override
                        public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
                            if(!getConnectedNodesResult.getNodes().isEmpty())
                            {
                                node = getConnectedNodesResult.getNodes().get(0);
                                System.out.println("Connected: "+ node.getId());
                                Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), FETCH_ALL_DEALS, null).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
                                    @Override
                                    public void onResult(MessageApi.SendMessageResult sendMessageResult) {
                                        if (!sendMessageResult.getStatus().isSuccess()) {
                                            Log.e("Wear:", "ERROR: failed to send Message: " + sendMessageResult.getStatus());
                                        }
                                        else
                                            System.out.println("success");
                                    }
                                });

                            }
                            else
                                System.out.println("Wear not connected to Phone");
                        }
                    });

        }

            @Override
            public void onConnectionSuspended(int i) {

            }



        })
        .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
            @Override
            public void onConnectionFailed(ConnectionResult result) {
                Log.v("Phone to wear connection failed", "onConnectionFailed: " + result);
            }
        })
        .addApi(Wearable.API)
        .build();
        mGoogleApiClient.connect();

Here is my code for onMessageReceive on Handheld:

 public void onMessageReceived(MessageEvent messageEvent) {
    System.out.println("Message Received on Phone on launch of wear homepage");
    if(messageEvent.getPath().equals(FETCH_ALL_DEALS)) {
        sendSavedDeals(); //fetch from db and make a datamap object using PutDataRequest
        System.out.println("Message Received on Phone on launch of wear homepage");
    }
    else {
        System.out.println("Unable to recognise action for "+messageEvent.getPath());
    }

}

Now on my wear side I have a WearableListenerService but it's onDataChanged method never gets called. Could you please help me with that.

Kristy
  • 121
  • 2
  • 6

3 Answers3

13

onDataChanged() is only called when the data really did change. If you put the same data into the DataApi multiple times, the method is only called once until you write different data.

To trigger an action on the wear side, even when the data didn't change, send a message after putting data into the DataApi.

Tom
  • 5,068
  • 5
  • 29
  • 41
  • 1
    Sir, you are a genius. Here I was, repeatedly sending "dad" text and marveling why it only works once, after reinstalling the app... -.- Can't upvote you enough. – Kelevandos Feb 01 '15 at 11:24
  • 1
    It is sad that the documentation doesn't give you a hint on that. It is generally a very poor documentation. – Maverick283 Feb 23 '16 at 10:55
  • There is another thing you have to mind. the payload for DataItems is limited to 100KB. If your DataItem exceeds this limit, onDataChanged() is not called as well. – Ascot Harris Dec 01 '17 at 10:52
1

Data should be changed or deleted to get call-back to onDataChanged in WearabaleListenerService in your wear. if you want make changes open APP-info from settings and clear-data then after force stop . Finally launch your app in phone..but ensure that wearable listener service should be already started in your wear..

Anees
  • 514
  • 5
  • 20
  • 1
    I realized I was sending same data everytime and hence it wasn't working because data was not cleared. – Kristy Aug 31 '17 at 21:36
0

When onDataChanged() is not being called :

Firstly, ensure that the handheld activity is connecting to the API at the start :


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

otherwise, it fails silently.

If it still doesn't work, to facilitate the debug, add this override method and this class in the handheld activity to generate data every 5 seconds :


    @Override
    public void onResume() {
        super.onResume();
        mDataItemGeneratorFuture = mGeneratorExecutor.scheduleWithFixedDelay(
            new DataItemGenerator(), 1, 5, TimeUnit.SECONDS
        );
    }


    /** Generates a DataItem based on an incrementing count. */
    private class DataItemGenerator implements Runnable {
        private int count = 0;

        @Override
        public void run() {
        PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(COUNT_PATH);
        putDataMapRequest.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest request = putDataMapRequest.asPutDataRequest();

        Log.d("yourApp", "Generating DataItem: " + request);
        if (!mGoogleApiClient.isConnected()) {
            return;
        }
        Wearable.DataApi.putDataItem(mGoogleApiClient, request)
            .setResultCallback(new ResultCallback() {

                @Override
                public void onResult(DataItemResult dataItemResult) {
                    if (!dataItemResult.getStatus().isSuccess()) {
                        Log.e("YourApp", "ERROR: failed to putDataItem, status code: "
                            + dataItemResult.getStatus().getStatusCode());
                    }
                }
            });
        }
    }

Pierre Maoui
  • 5,976
  • 2
  • 27
  • 28