简体   繁体   中英

Not cheatable Google fit step counter

i have a question to Google Fit. I am creating a step counter (oh wonder g ). This i have already done so far and it not really hard. But now we come to my problem. I am only reading the steps with the Sensor API. The issue is, i can add new data via for example the Google Fit app and it will be counted in my app too. This introduces cheating and i do not want this.

So i need to have a way to only read "device created" data and not manually added data. Is there a nice way to to this? From the SDK documentation it is not really clear how to proceed here.

So i need to have a way to only read "device created" data and not manually added data. Is there a nice way to to this?

You will want to use Private Custom Data Types to achieve that. Read about the different types of Fitness data you can upload to Google Fit here .

1. Public data types

Standard data types provided by the platform, like com.google.step_count.delta. Any app can read and write data of these types. For more information, see Public Data Types.

2. Private custom data types

Custom data types defined by an specific app. Only the app that defines the data type can read and write data of this type. For more information, see Custom Data Types.

3. Shareable data types

Custom data types submitted to the platform by an app developer. Once approved, any app can read data of a shareable type, but only whitelisted apps as specified by the developer can write data of that shareable type. For more information, see Shareable Data Types.

I was able to do this with the help of this alogrithm. But remember due to Android fragmentation this code still removes some of the user's data and count it as penalty

private String dumpDataSet(DataSet dataSet, int x) {
    List<String> days = new ArrayList<>();
    days.add("Monday");
    days.add("Tuesday");
    days.add("Wednesday");
    days.add("Thursday");
    days.add("Friday");
    days.add("Saturday");
    days.add("Sunday");

    String day = days.get(Math.round(x / 24));
    Log.d(TAG, "\tDay: " + day);
    Log.i(TAG, "Data returned for Data type: " + dataSet.getDataType().getName());
    DateFormat dateFormat = getTimeInstance();

    String text = "";
    try {
        for (DataPoint dp : dataSet.getDataPoints()) {
            Log.i(TAG, "\tStepCount getStreamName: " + dp.getOriginalDataSource().getStreamName());
            Log.i(TAG, "\tStepCount getStreamIdentifier: " + dp.getOriginalDataSource().getStreamIdentifier());
            Log.i(TAG, "\tStepCount App Type: " + dp.getDataType().getName());
            Log.i(TAG, "\tStepCount Type: " + dp.getOriginalDataSource().getType());

            for (Field field : dp.getDataType().getFields()) {
                Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
                text += dp.getValue(field);
                String si[] = dp.getOriginalDataSource().getStreamIdentifier().toLowerCase().split(":");
                if ((((si[si.length - 1].contains("soft")) || (si[si.length - 1].contains("step"))) && si[si.length - 1].contains("counter"))) {
                    totalSteps += Integer.parseInt(dp.getValue(field).toString());
                    Log.d(TAG, "\tStepCount" + " Added Steps -> " + dp.getValue(field) + " steps");
                    text += "\n\n";
                } else {
                    Log.e(TAG, "\tStepCount PENALTY ---------------------------------------------------------------");
                    Log.e(TAG, "\tDay = " + day + " | Hour Number = " + x + " | StepCount" + " PENALTY DEDUCTED -> " + dp.getValue(field) + " steps");
                    Log.e(TAG, "\tStepCount PENALTY getStreamIdentifier: " + dp.getOriginalDataSource().getStreamIdentifier());
                    Log.e(TAG, "\tStepCount PENALTY getStreamName: " + dp.getOriginalDataSource().getStreamName());
                    Log.e(TAG, "\tStepCount PENALTY App Type: " + dp.getDataType().getName());
                    Log.e(TAG, "\tStepCount PENALTY Type: " + dp.getOriginalDataSource().getType());
                    Log.e(TAG, "\tStepCount PENALTY ---------------------------------------------------------------");
                }
            }
        }

    } catch (Exception ex) {
        ex.getStackTrace();
    }

    return text;
}

----- UPDATE -----

You can also call

DataPoint.getOriginalDataSource().getAppPackageName()

to filter out smartwatches and other apps.

I tried as suggested by Ali Shah lakhani but

DataPoint.getOriginalDataSource().getAppPackageName();

/*I also tried but could not achieve what I wanted*/

DataPoint.getOriginalDataSource().getStreamName();
DataPoint.getOriginalDataSource().getStreamIdentifier();

did not work at least for me while retrieving data. I ended up using readDailyTotalFromLocalDevice() as shown below in order to capture steps captured by device only.

Fitness.HistoryApi.readDailyTotalFromLocalDevice(mApiClient, DataType.TYPE_STEP_COUNT_DELTA).await(1, TimeUnit.MINUTES)

I cross checked the same with some of the apps that avoids manual entries in their app and the count provided by the function above is exactly the same.

Note: If a user is having multiple devices and is using the app on all of them, readDailyTotalFromLocalDevice() will have different value for each and every device since the function is responsible for returning device specific data only.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM