I have set up a connection between my wear and mobile devices by following this post. I am sending an asset from the wearable to he handheld. However, the onDataChanged method is not being called, even though the devices are connected and the dataitem is being successfully sent. I have tried most other solutions, including making sure my build.gradles have the same appId, the same wearable version numbers. I have added a timestamp to the datamap, and yet it is still not working. Has anyone else ran into this problem or have any other ideas as to why it might not be getting called? Thanks.
Here's my wearable code which is doing the sending:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_wear);
mContainerView = (BoxInsetLayout) findViewById(R.id.container);
//...
// Build a new GoogleApiClient for the Wearable
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onStart() {
super.onStart();
if(!googleClient.isConnected()) {
googleClient.connect();
}
}
public void sendToPhone(View view){
// Send audio
if(audioAsset != null){
new SendToDataLayer().start();
}
}
private class SendToDataLayer extends Thread{
public void run(){
// Sending audio
// Get connected wearable nodes
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for(Node node : nodes.getNodes()){
// Send the audio
PutDataMapRequest request = PutDataMapRequest.create("/audio");
DataMap map = request.getDataMap();
map.putLong("time", new Date().getTime());
map.putAsset("audioAsset", audioAsset);
Wearable.DataApi.putDataItem(googleClient, request.asPutDataRequest());
Log.d("PUTDAT", "Data put on data item, for node: " + node.getDisplayName());
}
}
}
Using the log.d call I can see that the device is connected and that the data is being sent, or at least appears to be.
My code for the handheld receiving end:
public class MainHandheldActivity extends AppCompatActivity implements DataApi.DataListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
GoogleApiClient googleClient;
MessageReceiver messageReceiver;
IntentFilter messageFilter;
byte[] audioBytes;
private final Handler handler = new Handler();
private String nodeId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_handheld);
audioBytes = null;
// Build a new GoogleApiClient
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
retrieveDeviceNodes();
// Register the local broadcast receiver
messageFilter = new IntentFilter(Intent.ACTION_SEND);
messageReceiver = new MessageReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}
private void retrieveDeviceNodes(){
new Thread(new Runnable() {
@Override
public void run() {
googleClient.blockingConnect(3000, TimeUnit.MILLISECONDS);
NodeApi.GetConnectedNodesResult result =
Wearable.NodeApi.getConnectedNodes(googleClient).await();
List<Node> nodes = result.getNodes();
if (nodes.size() > 0) {
nodeId = nodes.get(0).getId();
}
googleClient.disconnect();
}
}).start();
}
@Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
Toast.makeText(this, "Data Changed!", Toast.LENGTH_LONG).show();
for (DataEvent event : dataEventBuffer) {
Log.d(TAG, "Data received: " + event.getDataItem().getUri());
if (event.getType() == DataEvent.TYPE_CHANGED &&
event.getDataItem().getUri().getPath().equals("/audio")) {
DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
Asset audioAsset = dataMapItem.getDataMap().getAsset("audioAsset");
audioBytes = loadBytesFromAsset(audioAsset);
}
// Enable player
handler.post(onNewAudio());
}
}
public byte[] loadBytesFromAsset(Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Asset must be non-null");
}
ConnectionResult result = googleClient.blockingConnect(3000, TimeUnit.MILLISECONDS);
if(!result.isSuccess()){
return null;
}
// Convert asset into a file descriptor and block until it's ready
InputStream assetInputStream = Wearable.DataApi.getFdForAsset(googleClient, asset).await().getInputStream();
if (assetInputStream == null) {
Log.w(TAG, "Requested an unknown Asset.");
return null;
}
// Decode the stream into a byte[]
return getBytesFromInputStream(assetInputStream);
}
private Runnable onNewAudio() {
return new Runnable() {
@Override
public void run() {
// Enable player
}
};
}
@Override
public void onConnected(Bundle bundle) {
Wearable.DataApi.addListener(googleClient, this);
Toast.makeText(this, "AddedListener!", Toast.LENGTH_LONG).show();
}
@Override
protected void onStart() {
super.onStart();
if(!googleClient.isConnected()) {
googleClient.connect();
}
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, messageFilter);
}
}
The Toast in onDataChanged() never gets shown, nor does the log call. Also, here is my handheld manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="glasgow.comsTest"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<service
android:name=".ListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER"/>
</intent-filter>
</service>
<activity android:name=".MainHandheldActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>