0

I am trying to connect to the data layer on the wearable device using an Activity that implements DataApi.DataListener. In onStart() the device connects to the Google API Client, and onConnected() is called. From onConnected() I call another method that sends a message to the handheld to update the data, and starts a new AsyncTask to get the data from the data layer. This is my Activity:

public class DataLayerActivity extends Activity implements DataApi.Listener,
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private ArrayList<myObject> mObjects = new ArrayList<>();

    private GoogleApiClient mGoogleApiClient;

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

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
    }

    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onStop() {
        if(null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
            Wearable.DataApi.removeListener(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        } super.onStop();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Wearable.DataApi.addListener(mGoogleApiClient, this);
        requestUpdate();
    }

    @Override
    public void onConnectionSuspended(int cause) {
        Timber.d("Connection Suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Timber.d("Connection Failed with result: " + result);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
    }

    private void requestUpdate() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
                for(Node node : nodes.getNodes()) {
                    Wearable.MessageApi.sendMessage(getGoogleApiClient(), node.getId(), "/path", null).setResultCallback(onMessageResult());
                }
            }
        }).start();

        try {
            Uri uri = Uri.parse("/path");
            mObjects = new FetchDataTask(this).execute(uri).get();
        } catch(InterruptedException | ExecutionException exception) {
            Timber.e(exception, "Fetch Data Failed");
        }
    }

    protected ResultCallback<MessageApi.SendMessageResult> onMessageResult() {
        if(!result.getStatus().isSuccess()) {
            Timber.d("Failed to Connect with status " + result.getStatus());
        }
    }
}

And this is the FetchDataTask:

public class FetchDataTask extends AsyncTask<Uri, Void, ArrayList<myObject>> {

    private Context mContext;

    private ArrayList<myObject> mObjects = new ArrayList<>();

    public FetchDataTask(Context context) {
        mContext = context;
    }

    @Override
    protected ArrayList<myObject> doInBackground(Uri... params) {
        GoogleApiClient googleApiClient = new GoogleApiClient
                .Builder(mContext).addApi(WearableAPI).build();

        ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
        if(!connectionResult.isSuccess() || !googleApiClient.isConnected()) {
            Timber.e("Failed to Connect with error code: " + connectionResult.getErrorCode());
            return null;
        }

        ...

        return mObjects;
    }
}

The connection result always returns with error code 14, which is a connection timeout. So I tried passing the already connected GoogleApiClient from DataLayerActivity as a parameter to FetchDataTask, and using that for the processes. But when I make a call to Wearable.DataApi.getDataItem().await() or Werable.NodeApi.getLocalNode().await() within doInBackground(), await() never finishes, and my app stalls. But I never get any error messages from onConnectionSuspended() or onConnectionFailed(). I cannot figure out why the connection to the data layer times out in my AsyncTask. I know this can be done, as it is done this way in the AttractionsActivity in the XYZTouristAttractions sample application.

Bryan
  • 14,756
  • 10
  • 70
  • 125

1 Answers1

0

Quickly looking at your code, I can see a few issues:

  • In the FetchDataTask, in doInBackground, you build a googleApiClient but you never called connect()to establish a connection
  • In the requestUpdate(), it seems there are unmatched braces, etc. Also, for the thread that you built there, I don't see you ever call "start()" on it.
  • Whenever you call await() on any of the asynchronous calls, make sure you specify a timeout so that it doesn't get stuck forever and after that, check to make sure the call was successful before using the result.
Ali Naddaf
  • 16,951
  • 2
  • 21
  • 28
  • I did not notice that I never called `connect()`, that would seem to cause a problem. But I added `googleApiClient.connect()` to `doInBackground()`, and I still get the same timeout error code. `AsyncTask` does not have a `start()` method, I believe `execute()` functions similarly. As for `await()`, this was really just for testing purposes, I plan on adding timeout callbacks in the finished code. – Bryan Oct 30 '15 at 19:53
  • Also, I just looked into it further, it looks like `googleApiClient.blockingConnect(30, TimeUnit.SECONDS)` acts as `connect()` call. Documented here: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html – Bryan Oct 30 '15 at 20:02
  • You are right about the mismatched braces and the `start()` call, I thought you meant the `AsyncTask`. When I copied the code over it got a little jumbled, I must have missed that when I tried to fix it. It was correct in the original code, I just fixed it in the question. – Bryan Oct 30 '15 at 20:07