Search code examples
androidandroid-permissionsgoogle-fit

Android App breaks down when trying to access Fitness.getHistoryClient of the Google Fit API


I am trying to get access to step count data via a HistoryClient of the Google Fit API, but I receive the following error message:

    E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.fittesting, PID: 26199
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fittesting/com.example.fittesting.MainActivity}: java.lang.NullPointerException: null reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6944)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
     Caused by: java.lang.NullPointerException: null reference
        at com.google.android.gms.common.internal.Preconditions.checkNotNull(com.google.android.gms:play-services-basement@@17.1.1:2)
        at com.google.android.gms.fitness.Fitness.getHistoryClient(com.google.android.gms:play-services-fitness@@20.0.0:14)
        at com.example.fittesting.MainActivity.accessGoogleFit(MainActivity.java:99)
        at com.example.fittesting.MainActivity.onCreate(MainActivity.java:70)
        at android.app.Activity.performCreate(Activity.java:7183)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2910)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6944) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

The code leading to this error is the following:

    public class MainActivity extends AppCompatActivity {
    public static final int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 42;

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FitnessOptions fitnessOptions = FitnessOptions.builder()
                .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
                .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
                .build();

        GoogleSignInAccount account = GoogleSignIn.getAccountForExtension(this, fitnessOptions);

        if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
            Log.d(TAG, "requesting permissions...");
            GoogleSignIn.requestPermissions(
                    this,
                    GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
                    account,
                    fitnessOptions
            );

        } 

        accessGoogleFit();

    }

    private void accessGoogleFit() {
        Log.d(TAG, "Access Google Fit");

        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        long endTime = cal.getTimeInMillis();
        cal.add(Calendar.YEAR, -1);
        long startTime = cal.getTimeInMillis();

        DataReadRequest readRequest = new DataReadRequest.Builder()
                .read(DataType.TYPE_STEP_COUNT_CUMULATIVE)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                .build();

        Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
                .readData(readRequest)
                .addOnSuccessListener(new OnSuccessListener<DataReadResponse>() {
                    @Override
                    public void onSuccess(DataReadResponse dataReadResponse) {
                        Log.d(TAG, "HistoryClient.readData: onSuccess()");
                        DataSet dataSet;

                        List<DataSet> dataSets = dataReadResponse.getDataSets();
                        Log.d(TAG, "# of DataSets: " + dataSets.size());
                        dataSet = dataReadResponse.getDataSet(DataType.TYPE_STEP_COUNT_CUMULATIVE);
                        Log.d(TAG, "DataSet: " + dataSet);
                        Log.d(TAG, "DataSource: " + dataSet.getDataSource());
                        Log.d(TAG, "DataType: " + dataSet.getDataType());

                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "HistoryClient.readData: onFailure()", e);
                    }
                });
    }
}

I assume that the error could be caused by some missing or wrong android-permissions, but I wasn't able to extract the source of the error.

I would be very happy if someone has an idea why this happens.

Also if some necessary information is missing I will be glad to deliver it in addition.

Thanks a lot in advance!


Solution

  • As mentioned in the comment of @Andy Turner, the error was caused by the GoogleSignIn.getLastSignedInAccount(this) call that returned 'null'.

    The reason for this was a mismatch between SHA1 Certificate Fingerprints in the OAuth configuration in the google cloud console and the one used to sign the app by Android Studio. This was caused by compiling the app in two different installations of Android Studio.

    The issue was solved by adding a second OAuth 2.0-Client-ID with the certificate of the second Android Studio installation.