我的问题:我想从我的 Android Wear 设备上的传感器获取心率,以使用 Google Fit API 发送到 Android 手机应用程序。
我有一个华为手表 2(可穿戴)和三星 Galaxy S7(手机),它们通过 WearOS 应用程序连接并通过蓝牙配对。
这与这里提出的问题几乎相同,但在我的情况下它没有有用的答案。另外,这听起来很明显。
到目前为止我已经尝试过:
- 在手机上运行 Google Fit Sensors Page上的代码。结果:仅显示手机背面的集成 HR 传感器。
- 在可穿戴设备上运行 Google Fit Sensors Page 上的代码。结果:E/GoogleFitSensor: failed com.google.android.gms.common.api.ApiException: 17: API: Fitness.SENSORS_CLIENT 在此设备上不可用。
- 使用此处描述的代码创建软件传感器,手机上的 Fitness.SensorClient 无法在可穿戴设备上找到该服务。查看可穿戴设备的 logcat,该服务永远不会创建。我怀疑意图不能跨设备工作。
Google Fit Sensors 页面指出可以列出设备和配套设备上的数据源。下图支持: Google Fit On Android
我查看了这些问题,但找不到合适的答案。
- 使用 Google fit 从 Android Wear 获取心率
- 如何在 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);
}
}
}
}
我错过了什么?提前致谢!