1

I am working on an Android Wearable project and I am trying to send data from the mobile device to the Wearable emulator. I am trying log the received data in the wearable but it is not logging.

These are what I've done so far.

1) Open the Android Wear app to get the Emulator status to be "connected"

2) Connect my mobile device

3) run adb -d forward tcp:5601 tcp:5601 to connect mobile device with emulator

4) Implement GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener in the sending class in my mobile device and building client in onCreate:

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

5) In my mobile device, create a dataItem, using 'weatherDescription" that logs perfectly, where I can using the DataApi to send to the wearable using putDataItem:

This is the log for weatherDescription: I/weatherDescription: scattered clouds

            putDataMapReq = PutDataMapRequest.create("/data");
            Log.i("weatherDescription", weatherDescription);
            putDataMapReq.getDataMap().putString("weatherDescription", weatherDescription);

            PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
            Wearable.DataApi.putDataItem(googleClient, putDataReq); 

5)Implement GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener in the receiving class (My custom watchface class) in my Wearable device and building client in onCreate:

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

6) Set up the listener in onConnect in the Wearable:

@Override
public void onConnected(Bundle bundle) {

    Wearable.DataApi.addListener(mGoogleApiClient, this).setResultCallback(new ResultCallback<Status>() {
        @Override
        public void onResult(Status status) {
            Log.i("myTag", String.valueOf(status));
        }
    });
}

It looks like it's connecting properly on the receiving/wearable end:

I/myTag: Status{statusCode=SUCCESS, resolution=null}

7) In onDataChanged, log the received information:

    public void onDataChanged(DataEventBuffer dataEventBuffer) {
        Log.i("myTag", "in on Data Changed");
        for (DataEvent event : dataEventBuffer){
            if(event.getType() == DataEvent.TYPE_CHANGED){
                DataItem item = event.getDataItem();

                if(item.getUri().getPath().compareTo("/data") == 0 ){
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();

                    dataMap.getString("weatherDescription");

                    Log.i("myTag", dataMap.getString("weatherDescription"));
                }
            }
        }
    }
Ben Wong
  • 691
  • 2
  • 19
  • 29
  • 1
    Here are a couple of the common reasons that the Wear Data (and Message) API won't deliver. I'm not proposing this as an *answer* at this point, but you don't mention either of them in your question. **Package names**: need to be the same for both apps (handheld and wearable) **APK signatures**: again, need to be the same on both sides for data to be delivered. Most likely, this isn't an issue for you if you're running both directly form the IDE, but it's worth checking. – Sterling Mar 01 '16 at 03:22

4 Answers4

3

Sounds like your dataMap is not changing its values, Then it won't send data to the wearable.

You can send Long.toString(System.currentTimeMillis()) to verify that as it changes every time.

Santhosh
  • 3,781
  • 2
  • 14
  • 11
  • You save me a week, my app sometimes sent data to phone sometime doesn't, I couldn't figure out why until read and try your code. Thanks very much – Khang Tran Jun 15 '17 at 10:10
1

Here are some leads :

  1. On your fifth point, try putting setUrgent() here :

    PutDataRequest putDataReq = putDataMapReq.asPutDataRequest().setUrgent();

Also, if you get a success in the callback, it means your data was sent successfully. It doesn't imply it was received well, or received at well.

  1. Maybe you did, but do you call googleClient.connect() at onStart() or anywhere else ?

  2. onDataChanged() is only called when the data put is really different, if you eep putting the same data, it won't be called. To test, you can add a timestamp to your DataMap.

  3. You need to have the same package names for your mobile and wear applications for them to be able to exchange messages/data.

  4. Maybe you can try implementing a WearableListenerService to receive the data on onDataChanged. The code is not different, it's just that this service is created when data is received, so you don't have to have your app open. Make sure you add the BIND_LISTENER action in this service intent filter on your manifest.

<service android:name=".AnalogWatchFaceConfigListenerService"> <intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter> </service>

Kapouter
  • 147
  • 10
  • Thanks @ Kapouter. Tried all that including changing my package name, adding the bind_listener action in the manifest, and logging the connection on the Wearable side when it's connected (which logs SUCCESS). So the connection is fine, sending the data is fine too, just the receiving not working. – Ben Wong Mar 02 '16 at 23:26
  • Your emulator and your mobile are connected on the Android Wear app? You can get the list of connected nodes with [getConnectedNodes](https://developers.google.com/android/reference/com/google/android/gms/wearable/NodeApi.html#getConnectedNodes(com.google.android.gms.common.api.GoogleApiClient)), there you would know if your mobile can see your emulator. Could i see more of your code ? You can check this android [sample](https://github.com/googlesamples/android-DataLayer) to compare with your implementation. – Kapouter Mar 03 '16 at 09:26
  • This is the printout when I did adb devices - List of devices attached ZX1G22GXBV device emulator-5554 device 192.168.57.101:5555 device . So it seems that things are connected. https://github.com/bwong199/Udacity-Project-7-Android-Wear-WatchFace-Project But here's the github if you want to check it out. – Ben Wong Mar 03 '16 at 16:48
  • adb just sees which devices are currently present, it doesn't tell if they're connected "between each other". So, if you don't connect manually your emulator and your phone on the AndroidWear app like [this](http://www.tech-recipes.com/rx/49586/how-do-i-connect-an-android-wear-emulator-to-a-real-phone/), they won't be connected. Maybe you've done that already but i wasn't sure from your last answer. – Kapouter Mar 03 '16 at 17:13
  • Per my Android Wear app on my mobile, it says Emulator connected in the upper left corner. Thanks. – Ben Wong Mar 03 '16 at 17:36
0

First, try to log the result of putting the DataItem:

Wearable.DataApi.putDataItem(googleClient, putDataReq)
    .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                @Override
                public void onResult(DataApi.DataItemResult dataItemResult) {
                    Log.d(TAG, "putDataItem status: "
                            + dataItemResult.getStatus().toString());
                }
            });

The dataItemResult.getStatus() call will tell you if something went wrong. Next, make sure you are listening to the onDataChanged() event. On your Wear app onConnected() method, add:

Wearable.DataApi.addListener(googleClient, yourListenerHere);

Finally, to force the data to be sent immediately to the Wear device, use setUrgent():

putDataMapReq = PutDataMapRequest.create("/data").setUrgent();

Hope that helps.

Ricardo
  • 7,785
  • 8
  • 40
  • 60
  • Thanks Ricardo. I implemented your codes and it seems like the data was transmitted successfully: 02-29 13:53:40.151 5686-5686/? D/myTag: putDataItem status: Status{statusCode=SUCCESS, resolution=null}. I also added the listener in onConnected in the Wearable (updated in my post). But I am still not seeing the log in the wearable/receiving end. – Ben Wong Feb 29 '16 at 20:54
  • @BenWong Did you use `setUrgent()` as well? One other thing, try adding a different value to the `DataMap` every time you create it, like `putDataMapRequest.getDataMap().putLong("current_time", System.currentTimeMillis());`. If the data you are putting is always the same, it won't be updated. – Ricardo Feb 29 '16 at 21:10
  • I did use .setUrger() and I also created a different dataMap. I also added a callback in onConnected on the Wearable side to log the status of the connection (reflected in the code) and it is showing up as successful - Status{statusCode=SUCCESS, resolution=null}. – Ben Wong Feb 29 '16 at 21:23
  • I'm out of options, sorry. :( Please update this post when you find the solution. I would be interested in knowing what was the problem. – Ricardo Feb 29 '16 at 21:27
  • 1
    I cloned your repo and implemented the .setUrgent() method. I also moved the log statement out side the loop (although that shouldn't matter). I was able to get the log to print using my LG G Watch. I looked through your code and compared it to several repositories as well as some tutorials and your code looks fine to me. I suspect that your problem is due to the emulator. Though what exactly the root of the problem is I'm not sure of yet. – sam_c Mar 02 '16 at 21:51
  • @sam_c - Hi Sam, are you running the Watchface? I have a module there called wear and it's for a wearable app. That worked for me, but now I am trying to receive using watchface and that's where I am stuck on. So I just want to be sure that you are receiving on the watchface end, and not the wearable app. https://github.com/bwong199/Udacity-Project-7-Android-Wear-WatchFace-Project . This is the newest push with the package name changed. Cheers – Ben Wong Mar 03 '16 at 16:51
  • @BenWong. I was running the wear app, you don't mention watch face until step 5. – sam_c Mar 04 '16 at 18:29
0

I finally figured it out. In the watchface side, I declared the Google Api Client instance, mGoogleApiClient, in the WeatherWatchFaceService class as opposed to the Engine class. After I moved it from WeatherWatchFaceService to Engine, the watch side received what I was trying to send from the mobile.

Cheers.

Ben Wong
  • 691
  • 2
  • 19
  • 29