Как узнать количество шагов в Google Fit REST API, например в приложении Google Fit?
Я занимаюсь разработкой приложения PHP, которое работает с API Google Fit для сбора ежедневного количества шагов пользователя.
Я хочу получить количество шагов от "15 января 2015 00:00:00 GMT+0700" до "16 января 2015 00:00:00 GMT+0700". - Во-первых, я получаю все свои источники данных. - Затем с каждым источником данных, который имеет тип данных, равный "com.google.step_count.delta", я получаю наборы данных между указанными выше временными метками и добавляю возвращаемые значения вместе.
Мой код: https://gist.github.com/daitr-gu/472c4f18522172542cca
Мой результат: https://gist.github.com/daitr-gu/1a7e11eb483a657bdc8b
Я обнаружил, что существует много источников данных, и они возвращают разные значения. И значения слишком отличаются от того, что я вижу в приложении Google Fit на моем телефоне.
Вопросы:
1. Какой источник данных приложение Google Fit использует для подсчета количества шагов?
2. Почему существуют различия между значением источника данных и значением Google Fit?
3. Как я могу получить значение Google Fit?
3 ответа
Я думаю, что разница, которую вы видите, заключается в том, как Google использует History API и Sensors API. Если вы используете PHP, вы запрашиваете Google Fit Store через доступный фитнес-API, и это зависит от того, что приложение могло сохранять через API записи. Таким образом, вы можете не видеть все данные, имеющиеся на устройстве.
Я думаю, но не знаю наверняка, что приложение Fit использует датчики API. В приложении вы можете использовать API датчиков, как описано в API Google Docs Sensors, и управлять возвращенными данными по своему усмотрению.
Ниже показан простой способ получить шаги, используя TYPE_STEP_COUNT_CUMULATIVE и TYPE_RAW
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
// Can specify whether data type is raw or derived.
.setDataSourceTypes(DataSource.TYPE_RAW)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "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) {
Log.i(TAG, "Data source for TYPE_STEP_COUNT_CUMULATIVE found! Registering.");
registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
}
}
}
});
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
mListener = new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
Log.i(TAG, "Difference in steps: " + (val.asInt()-previousValue));
previousValue = val.asInt();
}
}
};
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(dataType) // Can't be omitted.
.setSamplingRate(10, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
}
Вы можете найти, что это дает вам более близкое значение, чем указано в Fit App. Однако это, очевидно, доступно только на устройстве, поэтому вам потребуется запустить фоновую службу, которая обновляет внешнюю базу данных, что и дают API-интерфейсы записи и истории.
Чтобы убедиться, что данные продолжают отправляться в Fitness Store, когда ваше приложение работает в фоновом режиме, вам необходимо использовать API записи, это также может изменить значения, которые вы видите.
ОБНОВИТЬ:
Написав выше, я подумал, что должен это проверить. Это было от утренней прогулки.
- Apple iPhone 6 HealthKit: 6,762
- Apple iPhone 6 My App: 6,762
- Android Nexus 6 Fit: 6,920
- Android Nexus 6 My App: 6,920 (используется HistoryAPI)
- Android Rest API приблизительно: 6 928
- Android Rest API merge_step_deltas: 6,911
Это из поста Google+ вы можете найти здесь
"merge_step_deltas дает вам объединенный поток всех ваших счетчиков шагов.timate_steps также учитывает активность и оценивает шаги, когда их нет"
Единственное, чего я еще не понял, - это датчики, использующие то, что я показываю выше, они дают мне всего 2548 шагов.
Другая незначительная любопытная вещь заключается в том, что через день Fit показывает мне, что я сделал 6 668 шагов, что ближе к результату Apple, но пересчет по сравнению с тем, что он первоначально показал мне после синхронизации данных. Мое приложение все еще показывает 6,920!
Время для синхронизации всего этого я не измерял.
- Какой источник данных использует приложение Google Fit для расчета количества шагов?
Google Fit App использует источник данных оценочных_шагов для расчета количества шагов. DataSourceId: производный:com.google.step_count.delta:com.google.android.gms: оценочный_ этапов
- Почему существуют различия между значением источника данных и значением Google Fit?
Каждый источник данных представляет свое устройство / источник. Я вижу, у вас есть смарт-часы Sony и HTC Desire, подключенные к Google Fit. Каждое из ваших устройств сообщает значения Fit, которые объединяются вместе. Merge_step_deltas дает вам объединенный поток всех ваших счетчиков шагов. Estimated_steps также учитывает активность и оценивает шаги, когда их нет.
- Как я могу получить значение Google Fit?
REST API может получить доступ только к данным, которые были синхронизированы с серверной частью. Чтобы получить те же значения, что и в Google Fit, прочитайте источник данных оценочных_шагов. Это должно быть то же, что вы видите на https://fit.google.com/. Устройство может иметь последние значения, которые еще не синхронизированы с сервером. Мы работаем над тем, чтобы сделать синхронизацию и кроссплатформенность более удобной.
- Инженер в Google Fit Team.
Шаги Google Fit получают через REST Api
Запрос активности пользователя при входе в систему через Google и сохранение токена авторизации пользователя
Добавить дополнительную область для примера в iOS =
GIDSignIn.sharedInstance()?.scopes.append("https://www.googleapis.com/auth/fitness.activity.read")
Таким же образом мы можем добавлять области на другом языке
Теперь вызовите api, чтобы получить шаги
Api Reference Link - https://developers.google.com/fit/scenarios/read-daily-step-total
Api URL - https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate
Api Method - POST
Headers - Authorization Access Token
API Request - {
"aggregateBy": [{
"dataTypeName": "com.google.step_count.delta",
"dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
}],
"bucketByTime": { "durationMillis": 86400000 }, //86400000 is 24 Hours in milli second
"startTimeMillis": 1582654903000, // Start time in milli second
"endTimeMillis": 1582741303000 // End time in milli second
}
Вот ответ от API GoogleFit Steps
{
"bucket": [
{
"startTimeMillis": "1582654903000",
"endTimeMillis": "1582741303000",
"dataset": [
{
"dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:aggregated",
"point": [
{
"startTimeNanos": "1582715420043664097",
"endTimeNanos": "1582721490164126971",
"dataTypeName": "com.google.step_count.delta",
"originDataSourceId": "raw:com.google.step_count.cumulative:Xiaomi:Mi A1:e96661ecb4ffb28d:Step Counter",
"value": [
{
"intVal": 683, // This is steps value
"mapVal": []
}]
}]
} ]
} ]
}
Мне больше всего повезло с derived:com.google.step_count.delta:com.google.android.gms:estimated_steps
Первоначально результат был выше, чем то, что читал мой телефон, и затем я отфильтровал данные по двум основным шаговым устройствам. select{|q| q["originDataSourceId"] =~ /360|Nexus/}
и это дало мне самый близкий результат.
Если я попробую другой диапазон дня позже, и это будет полностью за стеной, я вернусь и отмечу это здесь.