基于Samsung Health SDK获取Galaxy Watch 4 Classic心率数据遇阻求助
三星Galaxy Watch 4 Classic心率传感器访问问题解决
问题背景
尝试在Android Studio中访问三星Galaxy Watch 4 Classic的心率传感器,并将数据显示在TextView中,使用Samsung Health SDK时始终无法正常连接,出现服务连接失败错误。
现有代码
Manifest配置
<uses-permission android:name="com.samsung.android.health.permission.read" /> <uses-permission android:name="android.permission.BODY_SENSORS" /> <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Activity代码
package com.example.test; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.FrameLayout; import com.example.test.databinding.ActivityVitalsBinding; import com.samsung.android.sdk.healthdata.HealthDataStore; import com.samsung.android.sdk.healthdata.HealthConstants; import com.samsung.android.sdk.healthdata.HealthDataResolver; import com.samsung.android.sdk.healthdata.HealthDataResolver.Filter; import com.samsung.android.sdk.healthdata.HealthPermissionManager; import com.samsung.android.sdk.healthdata.HealthResultHolder; import com.samsung.android.sdk.healthdata.HealthResultHolder.ResultListener; import java.util.Arrays; import java.util.HashSet; public class VitalsActivity extends Activity { private HealthDataStore healthDataStore; private ActivityVitalsBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityVitalsBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); healthDataStore = new HealthDataStore(this, new HealthDataStore.ConnectionListener() { @Override public void onConnected() { System.out.println("Connected successfully"); } @Override public void onConnectionFailed(HealthConnectionErrorResult healthConnectionErrorResult) { System.out.println("couldn't connect"); } @Override public void onDisconnected() { } }); healthDataStore.connectService(); } private void requestHeartRatePermission() { HealthPermissionManager.PermissionKey key = new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ); HealthPermissionManager permissionManager = new HealthPermissionManager(healthDataStore); permissionManager.requestPermissions(new HashSet<HealthPermissionManager.PermissionKey>(Arrays.asList(key))) .setResultListener(new ResultListener<HealthPermissionManager.PermissionResult>() { @Override public void onResult(HealthPermissionManager.PermissionResult result) { if (result.equals(true)) { readHeartRateData(); } else { System.out.println("access denied"); } } }); } private void readHeartRateData() { HealthDataResolver resolver = new HealthDataResolver(healthDataStore, null); HealthDataResolver.ReadRequest request = new HealthDataResolver.ReadRequest.Builder() .setDataType(HealthConstants.HeartRate.HEALTH_DATA_TYPE) .build(); resolver.read(request) .setResultListener(result -> { try (Cursor cursor = result.getResultCursor()) { if (cursor != null && cursor.moveToFirst()) { int heartRateIndex = cursor.getColumnIndex(HealthConstants.HeartRate.HEART_RATE); if (heartRateIndex != -1) { int heartRate = cursor.getInt(heartRateIndex); System.out.println("current heartrate: " + heartRate); } else { System.out.println("couldn't find heartrate-column"); } } } catch (Exception e) { System.out.println("error while reading heartrate-data"); } }); } }
错误日志
E/HealthDataStore: disconnectService: Context instance is invalid D/HealthDataStore: Trying to connect with Health Service fails (error code: 2) D/HealthDataStore: Check SupportedDevice D/HealthSDK-DeviceUtil: Server URL : https://hub.samsungapps.com/product/appCheck.as?appInfo=com.sec.android.app.shealth@0&deviceId=sdk_gwear_x86&mnc=260&csc=FAIL&openApi=30&mcc=310 D/HealthSDK-DeviceUtil: Downloading Samsung Health is unavailable (0)
解决方案
1. 切换实体设备测试
日志中deviceId=sdk_gwear_x86表明当前使用模拟器,Samsung Health SDK不支持模拟器运行。必须使用实体Galaxy Watch 4 Classic设备,且设备需安装最新版Samsung Health应用并完成登录。
2. 完善Manifest配置
添加健康数据类型声明的meta-data,同时确保权限申请完整:
<meta-data android:name="com.samsung.android.healthdata.health_data_types" android:value="com.samsung.health.heart_rate"/>
3. 修正连接与权限逻辑
- 在
onConnected回调中触发权限请求,当前代码未调用requestHeartRatePermission():
@Override public void onConnected() { Log.d("HealthStore", "Connected successfully"); requestHeartRatePermission(); }
- 修正权限结果判断逻辑,原代码
result.equals(true)判断错误,应检查授权集合:
@Override public void onResult(HealthPermissionManager.PermissionResult result) { HealthPermissionManager.PermissionKey key = new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ); if (result.getGrantedPermissions().contains(key)) { readHeartRateData(); } else { Log.e("Permission", "access denied"); } }
4. 实现实时心率监听(替代历史数据读取)
原代码仅读取历史数据,若要获取实时心率,需使用HealthDataObserver监听数据变化:
private HealthDataObserver heartRateObserver; private void registerHeartRateObserver() { heartRateObserver = new HealthDataObserver(null) { @Override public void onChange(String dataType) { readLatestHeartRateData(); } }; HealthDataObserver.addObserver(healthDataStore, HealthConstants.HeartRate.HEALTH_DATA_TYPE, heartRateObserver); } private void readLatestHeartRateData() { HealthDataResolver resolver = new HealthDataResolver(healthDataStore, null); HealthDataResolver.ReadRequest request = new HealthDataResolver.ReadRequest.Builder() .setDataType(HealthConstants.HeartRate.HEALTH_DATA_TYPE) .setSort(HealthConstants.HeartRate.CREATE_TIME, HealthDataResolver.Sort.DESC) .setLimit(1) .build(); resolver.read(request).setResultListener(result -> { try (Cursor cursor = result.getResultCursor()) { if (cursor != null && cursor.moveToFirst()) { int heartRate = cursor.getInt(cursor.getColumnIndex(HealthConstants.HeartRate.HEART_RATE)); runOnUiThread(() -> binding.yourTextViewId.setText(String.valueOf(heartRate))); Log.d("HeartRate", "Current heart rate: " + heartRate); } } catch (Exception e) { Log.e("HeartRate", "Read error", e); } }); } // 在onDestroy中移除观察者 @Override protected void onDestroy() { super.onDestroy(); if (heartRateObserver != null) { HealthDataObserver.removeObserver(healthDataStore, heartRateObserver); } if (healthDataStore != null) { healthDataStore.disconnectService(); } }
记得在权限授予成功后调用registerHeartRateObserver()。
5. 验证应用签名
Samsung Health SDK要求应用使用三星开发者后台注册的签名进行签名,调试签名无法通过服务验证。确保应用签名与开发者后台配置一致。
内容的提问来源于stack exchange,提问作者Cptain_Whitebeard
相关产品推荐
相关产品推荐

