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>