Получите информацию о датчике сердечного ритма от WearOS (android wear) на мобильный через Google Fit
Моя проблема: я хочу получить HeartRate от датчика на моем устройстве Android Wear для отправки в приложение Android Phone с помощью API Google Fit.
У меня есть Huawei Watch 2 (носимые) и Samsung Galaxy S7 (телефон), которые подключены через приложение WearOS и соединены через Bluetooth.
Это почти то же самое, что и вопрос, заданный здесь, но в моем случае он не дает полезного ответа. Плюс это звучит очевидно.
Что я пробовал до сих пор:
- Запустите код на странице Google Fit Sensors здесь, на телефоне. Результат: отображается только встроенный датчик ЧСС на задней панели телефона.
- Запустите код на странице датчиков Google Fit здесь, на носимых устройствах. Результат: E/GoogleFitSensor: ошибка com.google.android.gms.common.api.ApiException: 17: API: Fitness.SENSORS_CLIENT недоступно на этом устройстве.
- Создайте датчик программного обеспечения, используя код, описанный здесь. Fitness.SensorClient на телефоне не может найти услугу на носимом устройстве. Глядя на LogCat носимых, сервис никогда не создается. Я подозреваю, что намерения не работают на разных устройствах.
На странице Google Fit Sensors указывается, что она может перечислять источники данных на устройстве И на сопутствующих устройствах. Что подтверждается следующей картинкой: Google Fit On Android
Я посмотрел на эти вопросы, но не могу найти подходящий ответ.
- Получить ЧСС от Android Wear с помощью Google fit
- Как получить доступ к датчику сердечного ритма в Android Wearable?
- Получите частоту пульса от Android Wear
- Android: как получить данные Google Fit с носимого устройства?
- Android Fitness API не читает данные с носимых датчиков
Код:
public class GoogleFitSensor {
private Activity mActivity;
private DataType mRequestedDatatype;
private int mRequestedDataSource;
private static final String LOG_TAG = "GoogleFitSensor";
private static final int GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 1123;
private OnSensorResultInterface mOnSensorResultInterface;
/**
* Object that handles the connection with google fit devices.
* @param mActivity The activity from which the requests are called.
* @param requestedDatatype The requested Datatype (ex. DataType.TYPE_HEART_RATE_BPM)
* @param requestedDataSource The requested Data Source (ex. DataSource.TYPE_RAW)
*/
public GoogleFitSensor(Activity mActivity, DataType requestedDatatype, int requestedDataSource, @Nullable OnSensorResultInterface onSensorResultInterface ) {
this.mActivity = mActivity;
this.mRequestedDatatype = requestedDatatype;
this.mOnSensorResultInterface = onSensorResultInterface;
this.mRequestedDataSource = requestedDataSource;
}
public void connectToGoogleFit(){
FitnessOptions fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_HEART_RATE_BPM)
.build();
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(mActivity), fitnessOptions)) {
GoogleSignIn.requestPermissions(
mActivity, // your mActivity
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(mActivity),
fitnessOptions);
} else {
Dexter.withActivity(mActivity).withPermission("android.permission.BODY_SENSORS").withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
findSensorAndAddListener(mRequestedDatatype, mRequestedDataSource);
}
@Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Log.d(LOG_TAG, "Permission Denied.");
}
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
Log.d(LOG_TAG, "Permission Denied, rationale should be shown.");
token.continuePermissionRequest();
}
}).check();
}
}
private void findSensorAndAddListener(final DataType dataType, int dataSource) {
Fitness.getSensorsClient(mActivity, GoogleSignIn.getLastSignedInAccount(mActivity))
.findDataSources(
new DataSourcesRequest.Builder()
.setDataTypes(dataType)
.setDataSourceTypes(dataSource)
.build())
.addOnSuccessListener(
new OnSuccessListener<List<DataSource>>() {
@Override
public void onSuccess(List<DataSource> dataSources) {
for (DataSource dataSource : dataSources) {
Log.i(LOG_TAG, "Data source found: " + dataSource.toString());
Log.i(LOG_TAG, "Data Source type: " + dataSource.getDataType().getName());
// Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(dataType)) {
Log.i(LOG_TAG, "Data source for HEART RATE found! Registering.");
registerFitnessDataListener(dataSource, dataType);
}
}
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(LOG_TAG, "failed", e);
}
});
}
private void registerFitnessDataListener(DataSource dataSource, DataType type) {
Fitness.getSensorsClient(mActivity, GoogleSignIn.getLastSignedInAccount(mActivity))
.add(
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(type) // Can't be omitted.
.setSamplingRate(1, TimeUnit.SECONDS)
.build(),
new OnDataPointListener() {
@Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
if (mOnSensorResultInterface != null){
mOnSensorResultInterface.onNewResult(dataPoint.getValue(field));
}
Value val = dataPoint.getValue(field);
Log.i(LOG_TAG, "Detected DataPoint field: " + field.getName());
Log.i(LOG_TAG, "Detected DataPoint value: " + val);
}
}
})
.addOnCompleteListener(
new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.i(LOG_TAG, "Listener registered!");
} else {
Log.e(LOG_TAG, "Listener not registered.", task.getException());
}
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == GOOGLE_FIT_PERMISSIONS_REQUEST_CODE) {
findSensorAndAddListener(mRequestedDatatype, mRequestedDataSource);
}
}
}
}
Что мне не хватает? Заранее спасибо!