I've been battling with the Android Wear Message API all day today and have finally accepted I need some help with this.
My app is very straightforward. The Mobile portion consists of a MainActivity (which does nothing but display "Hello world" and a Service which extends WearableListenerService. The Wear portion is just a MainActivity with a single Button, and implements MessageApi.MessageListener.
The idea is simple: press the Button on the Wear device which sends a message to the Mobile. When the Mobile receives the message, it displays a Toast with the sender's message path (e.g. /mobile). Immediately after doing this, the Mobile should send a message back to the Wear device using my reply() method. All I want to do then is Log this message.
I can achieve the first part perfectly fine. When the Button is pressed, the Mobile pops up a Toast saying "/mobile". The reply, however, seems to just get lost in the aether; no errors, but no message either.
Can someone please help me understand what I'm doing wrong? I have pasted my files below.
This is the tutorial I am following. Cheers!
package org.thecosmicfrog.toastdroidmessageapitutorial;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.util.Log;
import android.view.View;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity implements MessageApi.MessageListener {
private final String LOG_TAG = MainActivity.class.getSimpleName();
private static final long CONNECTION_TIME_OUT_MS = 100;
private static final String MOBILE_PATH = "/mobile";
private GoogleApiClient googleApiClient;
private String nodeId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initGoogleApiClient();
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override
public void onLayoutInflated(WatchViewStub stub) {
initWidgets();
}
});
}
private void initGoogleApiClient() {
googleApiClient = getGoogleApiClient(this);
retrieveDeviceNode();
}
private GoogleApiClient getGoogleApiClient(Context context) {
return new GoogleApiClient.Builder(context)
.addApi(Wearable.API)
.build();
}
private void retrieveDeviceNode() {
new Thread(new Runnable() {
@Override
public void run() {
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
NodeApi.GetConnectedNodesResult result =
Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
List<Node> nodes = result.getNodes();
if (nodes.size() > 0)
nodeId = nodes.get(0).getId();
Log.v(LOG_TAG, "Node ID of phone: " + nodeId);
googleApiClient.disconnect();
}
}).start();
}
private void initWidgets() {
findViewById(R.id.button_toast).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendToast();
}
});
}
private void sendToast() {
if (nodeId != null) {
new Thread(new Runnable() {
@Override
public void run() {
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(googleApiClient, nodeId, MOBILE_PATH, null).await();
googleApiClient.disconnect();
}
}).start();
}
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.v(LOG_TAG, "In onMessageReceived()");
if (messageEvent.getPath().equals("/wear")) {
Log.v(LOG_TAG, "Success!");
}
}
}
package org.thecosmicfrog.toastdroidmessageapitutorial;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import java.util.concurrent.TimeUnit;
public class ListenerService extends WearableListenerService {
private final String LOG_TAG = ListenerService.class.getSimpleName();
private static GoogleApiClient googleApiClient;
private static final long CONNECTION_TIME_OUT_MS = 100;
private static final String WEAR_PATH = "/wear";
private String nodeId;
@Override
public void onMessageReceived(MessageEvent messageEvent) {
if (messageEvent.getPath().equals("/mobile")) {
nodeId = messageEvent.getSourceNodeId();
Log.v(LOG_TAG, "Node ID of watch: " + nodeId);
showToast(messageEvent.getPath());
reply(WEAR_PATH);
}
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
private void reply(final String path) {
googleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addApi(Wearable.API)
.build();
Log.v(LOG_TAG, "In reply()");
Log.v(LOG_TAG, "Path: " + path);
if (googleApiClient != null && !(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(googleApiClient, nodeId, path, null).await();
googleApiClient.disconnect();
}
}
The Mobile MainActivity is pretty trivial so I've left it out for clarity.
You never call MessageApi.addListener() in your Wear activity so your MessageListener
is never registered to receive messages. You should also call MessageApi.removeListener() when your activity is being destroyed.
Note: both methods require a connected GoogleApiClient
. It may make logic easier if you leave a GoogleApiClient
open throughout the duration of your activity rather than try connecting/removeListener()
/disconnect in your onDestroy()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With