yogesh Mishrikotkar
yogesh Mishrikotkar

Reputation: 11

Unable to get the step count using google fit android

I am working on step count implementation and for that i am using the google fit api of android.

Below is my code.

public class GoogleFitDemoActivity extends AppCompatActivity {
    public static final String TAG = "BasicSensorsApi";
    private GoogleApiClient mClient = null;
    private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
    private OnDataPointListener mListener;
    private TextView stepsCountTextView;
    ProgressDialog progressDialog;

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

        setContentView(R.layout.google_fit_main);
        progressDialog = new ProgressDialog(this);

        if (!checkPermissions()) {
            requestPermissions();
            Debug.displayToast(this, "Requesting for permisstion ");
        }

        stepsCountTextView = (TextView) findViewById(R.id.sample_logview);
    }

    /**
     * Return the current state of the permissions needed.
     */
    private boolean checkPermissions() {
        int permissionState = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);
        return permissionState == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * Unregister the listener with the Sensors API.
     */
    private void unregisterFitnessDataListener() {
        if (mListener == null) {
            return;
        }
        Fitness.SensorsApi.remove(
                mClient,
                mListener)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Debug.print(TAG, "Listener was removed!");
                        } else {
                            Debug.print(TAG, "Listener was not removed.");
                        }
                    }
                });
    }

    private void buildFitnessClient() {
        if (progressDialog == null) {
            return;
        }

        progressDialog.setMessage("Wait.....");
        progressDialog.show();
        if (mClient == null && checkPermissions()) {
            mClient = new GoogleApiClient.Builder(this)
                    .addApi(Fitness.SENSORS_API)
                    .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
                    .addConnectionCallbacks(
                            new GoogleApiClient.ConnectionCallbacks() {
                                @Override
                                public void onConnected(Bundle bundle) {
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            progressDialog.setMessage("Client Connected waiting for fit register");

                                        }
                                    });
                                    Debug.print(TAG, "Connected!!!");
                                    findFitnessDataSources();
                                }

                                @Override
                                public void onConnectionSuspended(int i) {
                                    // If your connection to the sensor gets lost at some point,
                                    // you'll be able to determine the reason and react to it here.
                                    if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
                                        Debug.print(TAG, "Connection lost.  Cause: Network Lost.");
                                    } else if (i
                                            == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                                        Debug.print(TAG,
                                                "Connection lost.  Reason: Service Disconnected");
                                    }
                                }
                            }
                    )
                    .enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult result) {
                            Debug.print(TAG, "Google Play services connection failed. Cause: " +
                                    result.toString());
                            Snackbar.make(
                                    GoogleFitDemoActivity.this.findViewById(R.id.main_activity_view),
                                    "Exception while connecting to Google Play services: " +
                                            result.getErrorMessage(),
                                    Snackbar.LENGTH_INDEFINITE).show();
                        }
                    })
                    .build();
        }
    }

    private void findFitnessDataSources() {
        Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
                .setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
                .setDataSourceTypes(DataSource.TYPE_DERIVED)
                .build())
                .setResultCallback(new ResultCallback<DataSourcesResult>() {
                    @Override
                    public void onResult(DataSourcesResult dataSourcesResult) {
                        progressDialog.dismiss();
                        Debug.print(TAG, "Result: " + dataSourcesResult.getStatus().toString());
                        for (DataSource dataSource : dataSourcesResult.getDataSources()) {
                            Debug.print(TAG, "Data source found: " + dataSource.toString());
                            Debug.print(TAG, DataType.TYPE_STEP_COUNT_CUMULATIVE + "  Data Source type: " + dataSource.getDataType().getName());

                            //Let's register a listener to receive Activity data!
                            if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE)
                                    && mListener == null) {
                                Debug.print(TAG, "Data source for LOCATION_SAMPLE found!  Registering.");
                                registerFitnessDataListener(dataSource,
                                        DataType.TYPE_STEP_COUNT_CUMULATIVE);
                            }
                        }
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        buildFitnessClient();
    }

    private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
        mListener = new OnDataPointListener() {
            @Override
            public void onDataPoint(DataPoint dataPoint) {
                for (Field field : dataPoint.getDataType().getFields()) {
                    final Value val = dataPoint.getValue(field);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            stepsCountTextView.setText("Steps count is " + val);
                        }
                    });

                    Debug.print(TAG, "Detected DataPoint field: " + field.getName());
                    Debug.print(TAG, "Detected DataPoint value: " + val);
                }
            }
        };

        Fitness.SensorsApi.add(
                mClient,
                new SensorRequest.Builder()
                        .setDataSource(dataSource) // Optional but recommended for custom data sets.
                        .setDataType(dataType) // Can't be omitted.
                        .setSamplingRate(1, TimeUnit.SECONDS)
                        .build(),
                mListener)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Debug.print(TAG, "Listener registered!");
                        } else {
                            Debug.print(TAG, "Listener not registered.");
                        }
                    }
                });
    }


    private void requestPermissions() {
        boolean shouldProvideRationale =
                ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.ACCESS_FINE_LOCATION);

        if (shouldProvideRationale) {
            Debug.print(TAG, "Displaying permission rationale to provide additional context.");
            Snackbar.make(
                    findViewById(R.id.main_activity_view),
                    R.string.permission_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            // Request permission
                            ActivityCompat.requestPermissions(GoogleFitDemoActivity.this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                    REQUEST_PERMISSIONS_REQUEST_CODE);
                        }
                    })
                    .show();
        } else {
            Debug.print(TAG, "Requesting permission");
            ActivityCompat.requestPermissions(GoogleFitDemoActivity.this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_PERMISSIONS_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        Debug.print(TAG, "onRequestPermissionResult");
        if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
            if (grantResults.length <= 0) {
                Debug.print(TAG, "User interaction was cancelled.");
            } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                buildFitnessClient();
            } else {
                Snackbar.make(
                        findViewById(R.id.main_activity_view),
                        R.string.permission_denied_explanation,
                        Snackbar.LENGTH_INDEFINITE)
                        .setAction(R.string.settings, new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                // Build intent that displays the App settings screen.
                                Intent intent = new Intent();
                                intent.setAction(
                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package",
                                        BuildConfig.APPLICATION_ID, null);
                                intent.setData(uri);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                            }
                        })
                        .show();
            }
        }
    }
}

Below are issue in this code which i am facing.

(Let suppose I have started walking and steps count is 10 and I kill my all and again start app once my onConnected() is called I register for getting data point and I get the dataPoint value 10 while it should give 0 to start from first

1 The step value does not reset to 0 and continues to increment.

2 Every-time I run the code the steps value doesn't reset to 0, so it is taking in some past values.

3 Not getting the steps count update as frequently it is taking time to update.(when i walk for 5 min then it gives first step count)

4 Even after killing app and again relaunching app get the previous steps count,steps count not start form 0 start from old.(As I am not storing any values in preference or database. How I am getting the previous step count like 10)

Please see the result log

Detected DataPoint value: 1 >>>>>>>>>> at this it should be start from 0

Detected DataPoint field: steps Detected DataPoint value: 1

Detected DataPoint field: steps Detected DataPoint value: 6

Detected DataPoint field: steps Detected DataPoint value: 6

Detected DataPoint field: steps Detected DataPoint value: 7

Detected DataPoint field: steps Detected DataPoint value: 7

Detected DataPoint field: steps Detected DataPoint value: 2

Please help where i am making the mistake.

Upvotes: 1

Views: 2407

Answers (1)

Dastin
Dastin

Reputation: 4507

There are 2 ways to get step value from Google Fit through their API, I think:

1) History API: we only need subscribe with GG Fit what kind of value we want to get and GG Fit will save info by itself (somehow it can detect your step by utilize sensor, machine learning,... (not by GPS - you can find out it easily on Google)). Then, if we want to get value what GG Fit saved, just revoke History API with a time range.

2) Sensor API: we will use Sensor API with some fantastic algorithm to communicate with our own sensor in device to get directly step value (not saving by GG Fit on their server and getting it later). However, this method will use temporary memory of sensor in your device to save step value; and this value keeps increasing, only if your device is rebooted, then it's reset :( => So, you can do some small trick to get the real value. (For example, save first value, then keep subtracting for the later. Suppose at first we got 1990, then saved it, then got 1995, then subtract it 1995 - 1190 = 5 steps) However, I don't know what if the value saved in sensor's memory becomes too big, and overflows. :(

** My experience: shouldn't use type DELTA. It could bring up a wrong value due to the time range; For example, from 17:30:00 to 17:31:00 it has value step 15, but if we revoke time range from 17:30:00 to 17:30:10 it has no value and time range from 17:30:10 to 17:31:00, it has value step 10. And sometime, it miss value when your screen device is sleeping, GG Fit will invoke their API underground but not recording time. More over, sometime I got negative values @@. God knows what they're are doing!

Finally, I think GG Fit app use some trick somehow to display the step value in real time (maybe sensor API, and most of time, I use Sensor API with step accumulate (not delta) which gives the best result similar to GG Fit app). Then, when I reactive app, awake device's screen (if you develop in Android, it means your activity calls onResume() method), I revoke History API with time range from the beginning to the current time I rewake my app and get the latest value.

https://developers.google.com/fit/android --> this link to show you what kind of API GG Fit support for Android.

https://developer.android.com/reference/android/hardware/Sensor.html#TYPE_STEP_COUNTER --> this link is the description for TYPE_STEP from sensor, it's said it will keep increasing until the device reboot.

Upvotes: 1

Related Questions