0

I started working on Android devices recently and I'd like to collect sensor data from an Android Watch.

I succeeded in using Message API but the Data API didn't work for me. I have checked:

https://stackoverflow.com/a/34175410/2487227

OnDataChanged is never called

Android Wear onDataChanged isn't called

But none of them worked for me.

My code on watch:

@Override
public void onCreate() {
    super.onCreate();
    // sensor registration
    // ......
    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    googleApiClient.connect();
    Log.i(this.getClass().toString(), "Google API Client connected");
}

private void sendSensorResult(SensorEvent event) {
    if (!googleApiClient.isConnected())
        googleApiClient.connect();

    PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(DATA_API_PATH);

    putDataMapRequest.getDataMap().putLong("UNIX_TIME", System.currentTimeMillis());
    putDataMapRequest.getDataMap().putInt("TYPE", event.sensor.getType());
    // nanosecond
    putDataMapRequest.getDataMap().putLong("TIME", event.timestamp);
    putDataMapRequest.getDataMap().putFloatArray("DATA", event.values);

    PutDataRequest request = putDataMapRequest.asPutDataRequest().setUrgent();
    Wearable.DataApi.putDataItem(googleApiClient, request)
            .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                @Override
                public void onResult(@NonNull DataApi.DataItemResult dataItemResult) {
                    if (dataItemResult.getStatus().isSuccess()) {
                        Log.i(this.getClass().toString(), "Sent: " + event.toString());
                    } else {
                        Log.i(this.getClass().toString(), "FAILED TO SEND: " + event.toString());
                    }
                }
            });
}

On phone:

public void onDataChanged(DataEventBuffer dataEvents) {
    Log.i(this.getClass().toString(), "Got data at " + System.currentTimeMillis());
    for (DataEvent dataEvent : dataEvents) {
        Log.i(this.getClass().toString(), "Got event: " + dataEvent.toString());
        if (dataEvent.getType() == DataEvent.TYPE_CHANGED) {
            DataMap dataMap = DataMapItem.fromDataItem(dataEvent.getDataItem()).getDataMap();
            String path = dataEvent.getDataItem().getUri().getPath();
            if (path.equals(DATA_API_PATH)) {
                int type = dataMap.getInt("TYPE");
                long time = dataMap.getLong("TIME");
                float[] data = dataMap.getFloatArray("DATA");
                String message = String.format(Locale.UK, "TYPE: %d, TIME: %d, DATA: %s",
                        type,
                        time,
                        Arrays.toString(data));

                showSensorResult(message);
            }
        }
    }
}

Phone AndroidManifest.xml:

<service
        android:name=".WearableSensorListener"
        android:enabled="true"
        android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED"/>
        <data android:host="*"
              android:scheme="wear"
              android:pathPrefix="/wearable-sensor"/>
    </intent-filter>
</service>

I can see the logs from watch but nothing shows up from phone.

The applicationIds of wearable and phone are the same.

Do I need any additional permissions to utilize Data API?

Community
  • 1
  • 1
Frederick Zhang
  • 3,593
  • 4
  • 32
  • 54
  • Which describes the question clearer: https://stackoverflow.com/questions/42932872/how-to-correctly-register-data-changed-data-api-event-after-crash-forcibly-stop – Frederick Zhang Mar 21 '17 at 16:27

1 Answers1

1

Use GooglePlayServices version as much earlier as you can use.

Open .\Sdk\extras\google\m2repository\com\google\android\gms\play-services-wearable\ and use, e.g., 8.3.0. Look at your wear device's GooglePlayServices version. Its number have to be greater than you use.

I think you have got incorrect implementation. This is wrong.

private void sendSensorResult(SensorEvent event) {
    if (!googleApiClient.isConnected())
        googleApiClient.connect();
///....
Wearable.DataApi.putDataItem(googleApiClient, request)

I mean you have to wait connection. So, use putDataItem only after onConnected callback.

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
  • Both my watch and phone are using `Google Play Services 10.2.98`. And changing it back to either `10.0.1` or `8.3.0` makes the app fail to launch. – Frederick Zhang Mar 21 '17 at 11:05
  • @FrederickZhang , may you post your failture log ? – Vyacheslav Mar 21 '17 at 11:06
  • Using `8.3.0`. Phone: https://paste.kde.org/p6eugmv1o . Watch: Just shows "Unfortunately, HelloWear has stopped" without any logs. – Frederick Zhang Mar 21 '17 at 11:12
  • can you post gradle file? @FrederickZhang – Vyacheslav Mar 21 '17 at 11:17
  • @FrederickZhang , it seems you have incorreclty implemented this lib version. try to clean/build the project – Vyacheslav Mar 21 '17 at 11:18
  • I used `compile 'com.google.android.gms:play-services:8.3.0'` for phone and `compile 'com.google.android.gms:play-services-wearable:8.3.0'` for watch. Now I changed it back to `10.2.0` however the problem remains lol... What the heck. Let me try clearing the build cache... – Frederick Zhang Mar 21 '17 at 11:21
  • I found this example: https://github.com/googlesamples/android-DataLayer/blob/master/Wearable/src/main/java/com/example/android/wearable/datalayer/DataLayerListenerService.java . Do we need to explicitly send the RPC manually? – Frederick Zhang Mar 21 '17 at 11:34
  • @FrederickZhang , I you want to responce the request, yes. In this example, the programmer wanna say: wearable received your data, what's ok! But in common case this is not needed , imho. – Vyacheslav Mar 21 '17 at 11:44
  • I restarted both phone and watch and it worked... Any clues? – Frederick Zhang Mar 21 '17 at 12:11
  • @FrederickZhang , bad cache inside both devices and android studio, imo. – Vyacheslav Mar 21 '17 at 12:18
  • Hmmm.... Actually it's really unstable. Forcibly closing & launching the app usually breaks it. Rebooting doesn't always work, either. – Frederick Zhang Mar 21 '17 at 12:26
  • @FrederickZhang , one more though. look at my updated post. – Vyacheslav Mar 21 '17 at 12:34