24

I'm writing a custom Android Wear application that's supposed to fire a one-off message to the connected host device (the phone). Digging through the API, I found the following tutorial that should work well: http://developer.android.com/training/wearables/data-layer/messages.html

My Android app has a WearableListenerService and my Android Wear app fires off messages using the Message API. The WearableListenerService get's called when the emulator gets connected based on logging the following method, so I'm pretty sure the service is wired up fine

@Override
public void onPeerConnected(Node peer) {
    super.onPeerConnected(peer);

    String id = peer.getId();
    String name = peer.getDisplayName();

    Log.d(LOG_TAG, "Connected peer name & ID: " + name + "|" + id);
}

Log output:

/AndroidWearListenerService(19892): Connected peer name & ID: facdc219-37f5-4326-8fa6-1c8b8d3b6669|facdc219-37f5-4326-8fa6-1c8b8d3b6669

However, the onMessageReceived method never gets triggered:

@Override
public void onMessageReceived(MessageEvent messageEvent) {
    Log.d(LOG_TAG, "MessageEvent received: " + messageEvent.getData());
    //do work
}

Here's my Android Wear code. I've removed most of the boiler plate code leaving only the necessary bits

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

    final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .build();

    googleApiClient.connect();

    final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override
        public void onLayoutInflated(WatchViewStub stub) {
            fireMessage();
        }

        private void fireMessage() {
            // Send the RPC
            PendingResult<NodeApi.GetConnectedNodesResult> nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient);
            nodes.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
                @Override
                public void onResult(NodeApi.GetConnectedNodesResult result) {
                    for (int i = 0; i < result.getNodes().size(); i++) {
                        Node node = result.getNodes().get(i);
                        String nName = node.getDisplayName();
                        String nId = node.getId();
                        Log.d(TAG, "Node name and ID: " + nName + " | " + nId);

                        Wearable.MessageApi.addListener(googleApiClient, new MessageApi.MessageListener() {
                            @Override
                            public void onMessageReceived(MessageEvent messageEvent) {
                                Log.d(TAG, "Message received: " + messageEvent);
                            }
                        });

                        PendingResult<MessageApi.SendMessageResult> messageResult = Wearable.MessageApi.sendMessage(googleApiClient, node.getId(),
                                PATH, null);
                        messageResult.setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
                            @Override
                            public void onResult(MessageApi.SendMessageResult sendMessageResult) {
                                Status status = sendMessageResult.getStatus();
                                Log.d(TAG, "Status: " + status.toString());
                                if (status.getStatusCode() != WearableStatusCodes.SUCCESS) {
                                    alertButton.setProgress(-1);
                                    label.setText("Tap to retry. Alert not sent :(");
                                }
                            }
                        });
                    }
                }
            });
        }
    });
}

Logging seems to indicate the message was sent successfully, but the Android app's WearableListenerService.onMessageReceived never fires.

D/MyWearApp MyActivity( 2014): Node name and ID: a2ba665d-a559-4a95-91d2-c16fc7873e28 | a2ba665d-a559-4a95-91d2-c16fc7873e28
D/MyWearApp MyActivity( 2014): Status: Status{statusCode=SUCCESS, resolution=null}

Any ideas?

ebernie
  • 820
  • 1
  • 8
  • 13
  • i use your code in my app, and gain same issue. Im cheked build.gradle and `applicationId` is the same for mobile and wear apps. But the error persists – Garf1eld Sep 09 '14 at 12:02
  • It looks like you add one listener per connected node in your code. I probably does not cause your problem, but it does not look right. – Glenn Bech Feb 28 '15 at 11:16

7 Answers7

52

Did you ensure that the "applicationId" is the same for both apps, i.e. for the app on the Android Wear and the app on the phone?

Dominique
  • 2,356
  • 1
  • 19
  • 19
  • 2
    This fixed it for me. Had no idea there's an applicationId in the Android Wear build.gradle. Funny enough, in the Android app I don't have an applicationId defined. To make it work, I just made sure the applicationId in the Android Wear app matched the Android app's package name. – ebernie Jul 07 '14 at 16:51
  • The applicationId has to be the same for both apps, because otherwise Android wouldn't know to which the messages should be sent. None of the messaging functions take a parameter to specify the peer. So it is automatically specified by the applicationId. – Dominique Jul 08 '14 at 06:57
  • 1
    Yes, this worked. Do they have this in the documentation anywhere? Is this standard for Google Play Services Client stuff? – Fraggle Jul 18 '14 at 22:08
  • i use your code in my app, and gain same issue. Im cheked build.gradle and applicationId is the same for mobile and wear apps. But the error persists – Garf1eld Sep 09 '14 at 12:03
  • @Dominique you mean that in byild.gradle application id must be same for module `wear` and `mobile`? – Garf1eld Sep 16 '14 at 05:59
  • 1
    Here's a little more on the applicationId in the build.gradle file: [Android Tools Project](http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename) It would help if the answer itself contained the defaultConfig() snippet. – SurlyDre Oct 30 '14 at 20:14
  • In addition, the mobile and wear apps must be signed with the same certificate: http://stackoverflow.com/a/24990069/483708 – Theo Dec 29 '14 at 02:42
  • I can't believe I spent three hours debugging this. Thanks a lot, and man, the android documentation could really say something to that extent! – Christian Fritz Mar 01 '15 at 22:36
  • I spent the whole afternoon trying to figure this out! +10 if I could! – Bryan Johnson Oct 28 '15 at 20:18
  • If I remember it right it's mention here on the video tutorial by Udacity - https://www.udacity.com/course/android-wear-development--ud875A – Apirak Lunla Jan 30 '16 at 22:37
4

I had the same problem when I added Android Wear support for an existing app. However after way to many hours of frustration. I discovered the problem.

I forgot to add the signing parts from the build.gradle in the device app in the wear app. So make sure the buildTypes part and the signingConfigs part are the same in both apps.

Timores
  • 14,439
  • 3
  • 46
  • 46
ui-jakob
  • 417
  • 1
  • 4
  • 11
3

I have had a similar issue as discussed here https://plus.google.com/116088533685577893615/posts/deCyoF6ALvV. Based on my experiments it seems (although not documented) that the package name of the watch app needs to be the same as of the handheld app. I have created an example project for the message api here https://github.com/petrnalevka/wear.

Petr Nalevka
  • 1,579
  • 1
  • 10
  • 18
2

Try add await() at the end of your sendMessage() method.

PendingResult<MessageApi.SendMessageResult> messageResult = Wearable.MessageApi.sendMessage(googleApiClient, node.getId(),
                                PATH, null).await();

The previous answer below is for sending message only when the Activity in Android device (mobile) is active.

Since you are trying to send message from Android Wear to Android device, the message listener should be added in the Activity in the Android device not in Android Wear, the following codes should be added into MainActivity in Android (mobile)

final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
        .addApi(Wearable.API)
        .build();

googleApiClient.connect();

Wearable.MessageApi.addListener(googleApiClient, new MessageApi.MessageListener() {
         @Override
         public void onMessageReceived(MessageEvent messageEvent) {
                  Log.d(TAG, "Message received: " + messageEvent.getPath());
         }
});

You can also try the simpler SendMessage() method

SendMessageResult result = Wearable.MessageApi.sendMessage(
        mGoogleApiClient, node.getId(), "STRING TO BE SENT", null).await();
if (!result.getStatus().isSuccess()) {
    Log.e(TAG, "ERROR: failed to send Message: " + result.getStatus());
}
wenjiun
  • 61
  • 4
  • On my phone, I implemented the WearableListenerService On my Android Wear, I use the Message API to fire messages the MessageListener bit in the Android Wear is to listen if the message was successfully delivered (is this an incorrect usage?) I can't implement the MessageApi.MessageListener in an activity because I want my app to react even if it's not running (hence WearableListenerService) – ebernie Jul 06 '14 at 20:55
  • @ebernie can u show your code or give a link to GitHub please. I cant solve this issue fow two week – Garf1eld Sep 16 '14 at 06:02
2

I have some sample code where I have the messages working, from both wear to device and device to wear. https://github.com/kentarosu/AndroidWearAndLIFX

gatlingxyz
  • 781
  • 6
  • 12
1

A few months ago, I had the same problem while working with android wear.My issue was - different signatures(SHA fingerprints generated after signing apks) of both apk's while application keys were same.Refer to link below:

OnMessageReceived not called in WearableListenerService

Hope this helps someone.

Community
  • 1
  • 1
Lakhan Sharma
  • 1,741
  • 1
  • 12
  • 19
0

The usual suspects are:

  • the applicationId as others have mentioned and
  • the signing certificates used

In the basic case, the following parts should be identical, in the gradle configurations of both apps.

defaultConfig {
    applicationId = "com.your.domain" 
}

signingConfigs {
    debug {
        storeFile file("../debug.keystore")
    }
    release {
        storeFile file("../release.keystore")
    }
} 

Both apps need to use the same applicationId and be signed with the same certificate.

Plato
  • 2,338
  • 18
  • 21