2

I am trying to use the DataApi but I am not receiving the data on the wearable side. Here is my code :

Mobile side :

public class Moto360Service implements GoogleApiClient.ConnectionCallbacks, MessageApi.MessageListener {
    private static final String TAG = Moto360Service.class.getSimpleName();

    private static Moto360Service moto360ServiceInstance = null;


    private GoogleApiClient mApiClient;

        public Moto360Service() {
        Log.v(TAG, "Moto360Service instance Created");
        //Favourites
        mSelectionOrangeContent = new ArrayList<WatchData>();
        mMyRadiosContent = new ArrayList<WatchData>();
        mMyPodcastsContent = new ArrayList<WatchData>();

        //
        initGoogleApiClient();

    }

    public static Moto360Service getInstance() {
        synchronized (TAG) {
            if (moto360ServiceInstance == null) {
                moto360ServiceInstance = new Moto360Service();
            }
        }
        return moto360ServiceInstance;
    }

    private void initGoogleApiClient() {
        mApiClient = new GoogleApiClient.Builder(OrangeradioApplication.getInstance().getApplicationContext())
                .addApi( Wearable.API )
                .build();

        mApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "connect to watch");
        String[] data = {"c","d","e" + + System.currentTimeMillis()};
        new DataTask (data).execute();
    }

class DataTask extends AsyncTask<Node, Void, Void> {

    private final String[] content;

    public DataTask (String [] content) {
        this.content = content;
    }

    @Override
    protected Void doInBackground(Node... nodes) {

        PutDataMapRequest dataMap = PutDataMapRequest.create ("/watch/data");
        dataMap.getDataMap().putStringArray("content", content);

        PutDataRequest request = dataMap.asPutDataRequest();

      PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(mApiClient, request);
        pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult> () {
            @Override
            public void onResult(DataApi.DataItemResult dataItemResult) {
                // something
                Log.d(TAG, "SOMETHING");
                Log.d(TAG, "dataItemResult : " + dataItemResult.getDataItem());
                if (dataItemResult.getStatus().isSuccess()) {
                    Log.d(TAG, "message successfully sent");
                } else if (dataItemResult.getStatus().isInterrupted()) {
                    Log.e(TAG, "couldn't send data to watch (interrupted)");

                } else if (dataItemResult.getStatus().isCanceled()) {
                    Log.e(TAG, "couldn't send data to watch (canceled)");

                }
            }
        } );

        Log.d(TAG, "sending data");
        return null;
    }
}

Wear side :

public class MainActivity extends Activity implements MessageApi.MessageListener, GoogleApiClient.ConnectionCallbacks,DataApi.DataListener, WearableListView.ClickListener {

private GoogleApiClient mApiClient;
private SimpleListAdapter mAdapter;
private static final String TAG = MainActivity.class.getSimpleName();

private ArrayList<String> list = new ArrayList<>();
private WearableListView mListView;

private ProgressDialog dialog;
private String showReceived;
private Float showSize;
private Context mContext;

private Handler myHandler = new Handler();
private int progressValue = 0;


@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    ...

    initGoogleApiClient();
}

private void initGoogleApiClient() {
    mApiClient = new GoogleApiClient.Builder( this )
            .addApi( Wearable.API )
            .addConnectionCallbacks( this )
            .build();

    if( mApiClient != null && !( mApiClient.isConnected() || mApiClient.isConnecting() ) )
        mApiClient.connect();
}

@Override
public void onConnected(Bundle bundle) {
    Log.d(TAG, "connected");
    Wearable.DataApi.addListener(mApiClient, this);
    Wearable.MessageApi.addListener(mApiClient, this);
}

@Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
    Log.d(TAG, "data changed");
}
}

The message isn't received on the wearable side, but the message is sent from the mobile.

private void sendMessage(final String path, final String text) {
    new Thread( new Runnable() {
        @Override
        public void run() {
            NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes( mApiClient ).await();
            for (Node node : nodes.getNodes()) {
                Log.d(TAG, "name : " + node.getDisplayName() + "id : " + node.getId());
                Log.d(TAG, "mApiClient : " + mApiClient);
                Log.d(TAG, "sending message");
                Wearable.MessageApi.sendMessage(mApiClient, node.getId(), path, text.getBytes());
            }
        }
    }).start();
}

In the logs, I see that the node is found :

D/Moto360Service﹕ name : Moto 360 E109id : ca292f00

Wear manifest : http://pastebin.com/C5BuXWx8

EDIT :

I tried the following (to make a change at each request) :

String[] data = {"a","b","c" + System.currentTimeMillis()};
new DataTask (data).execute();

But it didn't change anything.

krakig
  • 1,515
  • 1
  • 19
  • 33
  • Did you figure out a solution meanwhile? I have the same or at least a similar problem and realized, that the data api needs sometimes up to 10 minutes to deliver even a short string. Maybe it is just really slow or it checks for data updates just every few minutes. – Chris Dec 03 '15 at 09:35
  • Update: The docs say, it can even take up to 30 min to deliver data. But you can set the PutDataMapRequest with setUrgent() so it's delivered faster. That solved it at least for me... https://developers.google.com/android/reference/com/google/android/gms/wearable/PutDataRequest#setUrgent%28%29 – Chris Dec 03 '15 at 09:47
  • Yes I did but I'll have to find my code back, I'll try to update you! It shouldn't take that much time to deliver simple strings, usually it took me 5-10 mns to deliver 100Mo media data, but for simple strings it should take a few milliseconds/ seconds – krakig Dec 03 '15 at 09:48
  • I figured out what the problem was but you are not facing the same issue if you receive a message : I didn't have the same package names on both sides, so I wasn't receiving any message. – krakig Dec 07 '15 at 13:56
  • yes, for me it was just the synchronisation delay which was solved by the setUrgent() then. Thanks anyways – Chris Dec 07 '15 at 14:02
  • Are you getting normal delays then? Because I am not using setUrgent() and my messages go pretty fast, or I should say at a normal speed – krakig Dec 07 '15 at 14:03
  • No, without the urgent flag it took sometimes for sure 10 minutes or more. With the flag there is no noticeable delay anymore. – Chris Dec 07 '15 at 14:05

1 Answers1

2

onDataChanged() is called only if a new data is added, so if you add the same data (i.e. data items with the same content and path), it won't trigger that method. One way to see if that is the case is to add a timestamp to your data and see if that triggers the callback.

Ali Naddaf
  • 16,951
  • 2
  • 21
  • 28
  • Edited my question, I tried that but it doesn't work either – krakig Sep 15 '15 at 15:27
  • In that case, a number of things can be causing that; you need to provide more of your code. For one, make sure the package names of the wearable and the phone apps are identical. Also, show us how you are setting up the Google Api Clients on both sides, how are you registering to listen for data changes. Also, grab the result of your putDataItem() to see if it is successful or not. – Ali Naddaf Sep 15 '15 at 15:32
  • 1
    I updated the code, but the possible problem might be the package names – krakig Sep 15 '15 at 19:59
  • I caught the status and the message is successfully sent, but I do not catch it on the other side – krakig Sep 16 '15 at 07:52
  • Please show us your complete manifests on both ends. Do you see "connected" on the wear side in the logs? On the phone side, I don't see you setting any connection callbacks, so how is your "onConnected()" called on the sender side? – Ali Naddaf Sep 16 '15 at 13:58
  • yes you are right, I don't see the connected listener being called on the phone side, but It's called on the wear side! (that's a bit weird, no?). I added the connection to the API on the mobile side – krakig Sep 16 '15 at 15:40
  • The wear node is detected though – krakig Sep 17 '15 at 08:03
  • I am not sure what you mean by "the wear node is detected", how did you determine that? It is also not clear what your current code looks like (complete code) so you may want to post the whole project somewhere for people to take a look; without that, it is very hard to see what you have done, what changes you have made, etc. – Ali Naddaf Sep 17 '15 at 16:01
  • I could see the watch in the connected node (paired). Where can I upload my project? Don't really want to do it on github and share with everybody, I just need an angel man to find what I'm doing wrong! – krakig Sep 17 '15 at 16:38
  • I wrote a smaller code of what I am doing on my big project but this one works -_- : github.com/ifig/android.git. I am pretty sure the problem is coming from the gradle files (but my packages have the same applicationId) – krakig Sep 18 '15 at 09:32
  • @krakig, I had the same problem and it took me days until I noticed that I had added the keystore only to the mobile app. Since the apps were not being signed with the same key, it was like if they had different package names. – JP Ventura Mar 26 '16 at 01:09