0

My problem: I want to get the HeartRate from the sensor on my Android Wear device to be sent to the Android Phone Application using the Google Fit API`s.

I have a Huawei Watch 2 (Wearable) and Samsung Galaxy S7 (Phone), which are connected trough the WearOS application and paired via bluetooth.

It is almost the same as the question asked here, but it does not have a usefull answer in my case. Plus it sounds obvious.

What i have tried so far:

  1. Run the code on the Google Fit Sensors Page here on the Phone. Result: only the integrated HR sensor at the back of the phone shows.
  2. Run the code on the Google Fit Sensors Page here on the Wearable. Result: E/GoogleFitSensor: failed com.google.android.gms.common.api.ApiException: 17: API: Fitness.SENSORS_CLIENT is not available on this device.
  3. Create a Sofware Sensor using the code described here, the Fitness.SensorClient on the phone cant find the service on the wearable. Looking at logcat of the wearable the service is never created. My suspicion is that intents do not work across devices.

The Google Fit Sensors page states that is can list the data sources on the device AND on companion devices. Which is supported by the following picture.: Google Fit On Android

I looked at these questions but cant find a suitable answer.

Code:

public class GoogleFitSensor {

    private Activity mActivity;
    private DataType mRequestedDatatype;
    private int mRequestedDataSource;
    private static final String LOG_TAG = "GoogleFitSensor";
    private static final int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 1123;
    private OnSensorResultInterface mOnSensorResultInterface;

    /**
     * Object that handles the connection with google fit devices.
     * @param mActivity The activity from which the requests are called.
     * @param requestedDatatype The requested Datatype (ex. DataType.TYPE_HEART_RATE_BPM)
     * @param requestedDataSource The requested Data Source (ex. DataSource.TYPE_RAW)
     */
    public GoogleFitSensor(Activity mActivity, DataType requestedDatatype, int requestedDataSource, @Nullable OnSensorResultInterface onSensorResultInterface ) {
        this.mActivity = mActivity;
        this.mRequestedDatatype = requestedDatatype;
        this.mOnSensorResultInterface = onSensorResultInterface;
        this.mRequestedDataSource = requestedDataSource;
    }


    public void connectToGoogleFit(){
        FitnessOptions fitnessOptions = FitnessOptions.builder()
                .addDataType(DataType.TYPE_HEART_RATE_BPM)
                .build();

        if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(mActivity), fitnessOptions)) {
            GoogleSignIn.requestPermissions(
                    mActivity, // your mActivity
                    GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
                    GoogleSignIn.getLastSignedInAccount(mActivity),
                    fitnessOptions);
        } else {
            Dexter.withActivity(mActivity).withPermission("android.permission.BODY_SENSORS").withListener(new PermissionListener() {
                @Override
                public void onPermissionGranted(PermissionGrantedResponse response) {
                    findSensorAndAddListener(mRequestedDatatype, mRequestedDataSource);
                }

                @Override
                public void onPermissionDenied(PermissionDeniedResponse response) {
                    Log.d(LOG_TAG, "Permission Denied.");
                }

                @Override
                public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
                    Log.d(LOG_TAG, "Permission Denied, rationale should be shown.");
                    token.continuePermissionRequest();
                }
            }).check();
        }
    }

    private void findSensorAndAddListener(final DataType dataType, int dataSource) {
        Fitness.getSensorsClient(mActivity, GoogleSignIn.getLastSignedInAccount(mActivity))
                .findDataSources(
                        new DataSourcesRequest.Builder()
                                .setDataTypes(dataType)
                                .setDataSourceTypes(dataSource)
                                .build())
                .addOnSuccessListener(
                        new OnSuccessListener<List<DataSource>>() {
                            @Override
                            public void onSuccess(List<DataSource> dataSources) {
                                for (DataSource dataSource : dataSources) {
                                    Log.i(LOG_TAG, "Data source found: " + dataSource.toString());
                                    Log.i(LOG_TAG, "Data Source type: " + dataSource.getDataType().getName());

                                    // Let's register a listener to receive Activity data!
                                    if (dataSource.getDataType().equals(dataType)) {

                                        Log.i(LOG_TAG, "Data source for HEART RATE found!  Registering.");
                                        registerFitnessDataListener(dataSource, dataType);
                                    }
                                }
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Log.e(LOG_TAG, "failed", e);
                            }
                        });
    }

    private void registerFitnessDataListener(DataSource dataSource, DataType type) {
        Fitness.getSensorsClient(mActivity, GoogleSignIn.getLastSignedInAccount(mActivity))
                .add(
                        new SensorRequest.Builder()
                                .setDataSource(dataSource) // Optional but recommended for custom data sets.
                                .setDataType(type) // Can't be omitted.
                                .setSamplingRate(1, TimeUnit.SECONDS)
                                .build(),
                        new OnDataPointListener() {
                            @Override
                            public void onDataPoint(DataPoint dataPoint) {
                                for (Field field : dataPoint.getDataType().getFields()) {
                                    if (mOnSensorResultInterface != null){
                                        mOnSensorResultInterface.onNewResult(dataPoint.getValue(field));
                                    }
                                    Value val = dataPoint.getValue(field);
                                    Log.i(LOG_TAG, "Detected DataPoint field: " + field.getName());
                                    Log.i(LOG_TAG, "Detected DataPoint value: " + val);
                                }
                            }
                        })
                .addOnCompleteListener(
                        new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                if (task.isSuccessful()) {
                                    Log.i(LOG_TAG, "Listener registered!");
                                } else {
                                    Log.e(LOG_TAG, "Listener not registered.", task.getException());
                                }
                            }
                        });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) {
                findSensorAndAddListener(mRequestedDatatype, mRequestedDataSource);
                }
            }
        }
}

What am i missing? Thanks in advance!

genie137
  • 23
  • 1
  • 8
  • Having the same issue. Still figuring out how to solve it but I think here is the key - you need to connect to Sensors Client - https://developers.google.com/android/reference/com/google/android/gms/fitness/SensorsClient – Георги Ангелов Apr 09 '18 at 20:48
  • @ГеоргиАнгелов I do use the SensorsClient by invoking Fitness.getSensorsClient() in my findSensorsAndAddListener method. Still no luck. – genie137 Apr 10 '18 at 08:58
  • Ever find the solution for this? – Ben De La Haye Jun 07 '18 at 09:47
  • No unfortunately I have not. I ended up using the Data/Message Clients of the wearable API and collecting the info trough the Sensor Manager. I still want to know if/how this works though – genie137 Jun 08 '18 at 12:59

0 Answers0