Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Fit API: ApiException 17 (Fitness.CLIENT is not available on this device)

The Google Play documentation claims this is an API_NOT_CONNECTED code, however I have done everything I (think I) have to do in order to access the Google Fit API.

Attempting to use Fit API on an Android Wear watch. I have a Main Activity, which handles Auth, and a Service which attempts to access the API.

I have added the relevant debug key in the Google API console and enabled Google Fit - my success callbacks for permissions are called - implying this is not activally a permissions issue

build.gradle:

dependencies {
    //...
    compile 'com.google.android.gms:play-services-fitness:11.8.0'
    compile 'com.google.android.gms:play-services-auth:11.8.0'
    //...
}

Android Manifest:

//...
<application ...>
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
//...

MainActivity Snippet:

//This method is called if the user chooses to enable Google Fit
private void GFitRegister(){
    FitnessOptions options = FitnessOptions.builder()
            .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_WRITE)
            .addDataType(DataType.TYPE_ACTIVITY_SAMPLES, FitnessOptions.ACCESS_WRITE)
            .addDataType(DataType.TYPE_ACTIVITY_SEGMENT, FitnessOptions.ACCESS_WRITE)
            .build();

    if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(mService), options)) {
        GoogleSignIn.requestPermissions(
                this, // your activity
                GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
                GoogleSignIn.getLastSignedInAccount(mService),
                options);
    } else {
        accessGoogleFit(); //Sets some fields to true
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) {
            accessGoogleFit();
            //mUseFit = true;
        }
    }
}

Service snippets (run from within an asynctask):

if(mPreferences.getBoolean("googlefit_use", false)){
    //Insert heart rate data if it exists
    if(data.hasHRData()) {
        DataSource source = new DataSource.Builder()
                .setAppPackageName(TrackerService.this)
                .setDataType(DataType.TYPE_HEART_RATE_BPM)
                .setStreamName(TAG + " - heart rate")
                .setType(DataSource.TYPE_RAW)
                .build();

                DataSet FitData = DataSet.create(source);

                for(int i = 1; i < data.getDataLength(); i++){
                    long time = (long) data.getTimeAt(i-1);
                    double current = data.getHRAt(i);

                    com.google.android.gms.fitness.data.DataPoint d = FitData.createDataPoint()
                        .setTimeInterval(time + 1, time + SleepData.STEPMILLIS, TimeUnit.MILLISECONDS);
                    d.getValue(Field.FIELD_BPM).setFloat((float) current);

                    FitData.add(d);
                }

                Task response = Fitness.getHistoryClient(TrackerService.this,
                    GoogleSignIn.getLastSignedInAccount(TrackerService.this))
                        .insertData(FitData).addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                if(task.isSuccessful()) {
                                    Log.d(TAG, "HR data added to google fit");
                                }else{
/* This is logged, with the error in the title */
                                    Log.d(TAG, "HR data unsucessful: ", task.getException());
                                }
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Log.d(TAG, "Error: "+e.getMessage());
                            }
                        });
            }
        }

I apologise for the poor formatting, is there no way to properly edit code in SO?

Exception printed out by annotated line:

          com.google.android.gms.common.api.ApiException: 17: API: Fitness.CLIENT is not available on this device.
              at com.google.android.gms.common.internal.zzb.zzy(Unknown Source)
              at com.google.android.gms.common.internal.zzbk.zzz(Unknown Source)
              at com.google.android.gms.common.internal.zzbl.zzr(Unknown Source)
              at com.google.android.gms.common.api.internal.BasePendingResult.zzc(Unknown Source)
              at com.google.android.gms.common.api.internal.BasePendingResult.setResult(Unknown Source)
              at com.google.android.gms.common.api.internal.zzm.zzu(Unknown Source)
              at com.google.android.gms.common.api.internal.zzc.zzs(Unknown Source)
              at com.google.android.gms.common.api.internal.zzbo.zzw(Unknown Source)
              at com.google.android.gms.common.api.internal.zzbo.onConnectionFailed(Unknown Source)
              at com.google.android.gms.common.internal.zzad.onConnectionFailed(Unknown Source)
              at com.google.android.gms.common.internal.zzn.zzj(Unknown Source)
              at com.google.android.gms.common.internal.zze.zzw(Unknown Source)
              at com.google.android.gms.common.internal.zzi.zzaks(Unknown Source)
              at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source)
              at android.os.Handler.dispatchMessage(Handler.java:102)
              at android.os.Looper.loop(Looper.java:154)
              at android.os.HandlerThread.run(HandlerThread.java:61)
like image 842
drnessie Avatar asked Jan 08 '18 15:01

drnessie


1 Answers

Do you use the latest version of Google Play Services?

You can check it by invoking the next code:

private void checkForUpdates() {
    GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
    int resultCode = availability.isGooglePlayServicesAvailable(this);
    if (resultCode == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
        availability.getErrorDialog(this, resultCode, REQUEST_CODE).show();
    }
}
like image 184
Alexey Denysenko Avatar answered Nov 17 '22 02:11

Alexey Denysenko