如何实现Wear OS向移动设备实时传输传感器数据?
实现Android Wear实时心率数据传输(无需按键触发)
核心思路
实时流传输的关键是订阅传感器数据+自动触发传输:用Health Services API持续监听心率变化,每次拿到新数据就通过Wearable的消息/数据组件发送到手机。
步骤1:配置依赖与权限
依赖配置(手表+手机端Module级build.gradle)
添加Health Services和Wearable核心库的依赖:
dependencies { // Health Services API implementation "com.google.android.gms:play-services-health-services:16.0.0" // Wearable跨设备通信库 implementation "com.google.android.gms:play-services-wearable:20.1.0" }
权限配置(手表端AndroidManifest.xml)
添加心率传感器权限:
<uses-permission android:name="android.permission.BODY_SENSORS" />
注意:BODY_SENSORS是危险权限,需要在手表端启动时动态申请。
步骤2:手表端实时监听心率+发送数据
方式1:用Message Client(推荐,低延迟实时流)
Message Client适合单次、低延迟的实时数据传输,每次心率更新就主动发送消息到手机。
代码实现(Java)
import com.google.android.gms.health.HealthServices; import com.google.android.gms.health.HealthServicesClient; import com.google.android.gms.health.heartrate.HeartRateClient; import com.google.android.gms.health.heartrate.HeartRateMeasurementRequest; import com.google.android.gms.health.heartrate.HeartRateUpdate; import com.google.android.gms.health.heartrate.HeartRateUpdateCallback; import com.google.android.gms.wearable.Node; import com.google.android.gms.wearable.Wearable; import java.nio.charset.StandardCharsets; import java.util.concurrent.Executors; public class WatchHeartRateService extends Service { private HealthServicesClient healthServicesClient; private HeartRateClient heartRateClient; @Override public void onCreate() { super.onCreate(); healthServicesClient = HealthServices.getClient(this); // 检查心率支持并开始订阅 checkHeartRateCapabilityAndSubscribe(); } // 检查设备是否支持心率测量 private void checkHeartRateCapabilityAndSubscribe() { healthServicesClient.getCapabilities(com.google.android.gms.health.CapabilitiesClient.CAPABILITY_HEART_RATE) .addOnSuccessListener(capabilities -> { if (capabilities.getSupportedDataTypes().contains(com.google.android.gms.health.data.HeartRateRecord.HEART_RATE_BPM)) { subscribeToHeartRate(); } }); } // 订阅心率数据 private void subscribeToHeartRate() { HeartRateMeasurementRequest request = new HeartRateMeasurementRequest.Builder() .setSensorLocation(com.google.android.gms.health.data.SensorLocation.WRIST) .build(); heartRateClient = healthServicesClient.getHeartRateClient(); heartRateClient.subscribe(request) .addOnSuccessListener(unused -> registerHeartRateCallback()); } // 注册心率更新回调,拿到数据就发送到手机 private void registerHeartRateCallback() { heartRateClient.registerHeartRateCallback( Executors.newSingleThreadExecutor(), new HeartRateUpdateCallback() { @Override public void onHeartRateUpdated(HeartRateUpdate update) { double bpm = update.getHeartRateBpm(); sendHeartRateToPhone(bpm); } }); } // 发送心率数据到已连接的手机 private void sendHeartRateToPhone(double bpm) { Wearable.getMessageClient(this).getConnectedNodes() .addOnSuccessListener(nodes -> { for (Node node : nodes) { byte[] data = String.valueOf(bpm).getBytes(StandardCharsets.UTF_8); // 自定义消息路径,手机端要对应 Wearable.getMessageClient(this).sendMessage(node.getId(), "/heart-rate", data); } }); } @Override public void onDestroy() { super.onDestroy(); if (heartRateClient != null) { heartRateClient.unsubscribe(); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
方式2:用DataItems(适合状态同步)
如果需要同步心率的历史状态或者自动冲突处理,可以用DataItems。每次心率更新时更新DataItem,手机端监听DataItem变化。
手表端更新DataItem代码
private void updateHeartRateDataItem(double bpm) { com.google.android.gms.wearable.PutDataMapRequest putDataMapReq = com.google.android.gms.wearable.PutDataMapRequest.create("/heart-rate-data"); putDataMapReq.getDataMap().putDouble("bpm", bpm); putDataMapReq.setUrgent(); // 开启紧急同步,降低延迟 com.google.android.gms.wearable.PutDataRequest putDataReq = putDataMapReq.asPutDataRequest(); Wearable.getDataClient(this).putDataItem(putDataReq) .addOnSuccessListener(dataItem -> { // DataItem更新成功 }); }
步骤3:手机端接收数据
方式1:接收Message Client的消息
import com.google.android.gms.wearable.MessageClient; import com.google.android.gms.wearable.MessageEvent; import com.google.android.gms.wearable.Wearable; import java.nio.charset.StandardCharsets; public class PhoneHeartRateActivity extends AppCompatActivity { private TextView heartRateTextView; private MessageClient.OnMessageReceivedListener messageListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_heart_rate); heartRateTextView = findViewById(R.id.heart_rate_text); // 注册消息监听 messageListener = this::onMessageReceived; Wearable.getMessageClient(this).addListener(messageListener); } private void onMessageReceived(MessageEvent messageEvent) { if ("/heart-rate".equals(messageEvent.getPath())) { // 解析心率数据 String bpmStr = new String(messageEvent.getData(), StandardCharsets.UTF_8); double bpm = Double.parseDouble(bpmStr); // 切换到主线程更新UI runOnUiThread(() -> { heartRateTextView.setText(String.format("当前心率: %.1f BPM", bpm)); }); } } @Override protected void onDestroy() { super.onDestroy(); // 移除监听 Wearable.getMessageClient(this).removeListener(messageListener); } }
方式2:监听DataItem变化
import com.google.android.gms.wearable.DataClient; import com.google.android.gms.wearable.DataEvent; import com.google.android.gms.wearable.DataEventBuffer; import com.google.android.gms.wearable.DataMapItem; import com.google.android.gms.wearable.Wearable; public class PhoneHeartRateActivity extends AppCompatActivity { private TextView heartRateTextView; private DataClient.OnDataChangedListener dataListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_heart_rate); heartRateTextView = findViewById(R.id.heart_rate_text); // 注册DataItem监听 dataListener = this::onDataChanged; Wearable.getDataClient(this).addListener(dataListener); } private void onDataChanged(DataEventBuffer dataEventBuffer) { for (DataEvent event : dataEventBuffer) { if (event.getType() == DataEvent.TYPE_CHANGED) { com.google.android.gms.wearable.DataItem item = event.getDataItem(); if ("/heart-rate-data".equals(item.getUri().getPath())) { DataMapItem dataMapItem = DataMapItem.fromDataItem(item); double bpm = dataMapItem.getDataMap().getDouble("bpm"); // 更新UI runOnUiThread(() -> { heartRateTextView.setText(String.format("当前心率: %.1f BPM", bpm)); }); } } } dataEventBuffer.close(); } @Override protected void onDestroy() { super.onDestroy(); Wearable.getDataClient(this).removeListener(dataListener); } }
关键注意事项
- 动态权限:手表端必须动态申请
BODY_SENSORS权限,否则无法读取心率数据。 - 线程处理:Health Services和Wearable的回调都在后台线程,更新UI必须切换到主线程。
- 设备连接:确保手表与手机已配对且处于连接状态,Message Client只会发送给已连接的节点。
内容的提问来源于stack exchange,提问作者Luis Barba
相关产品推荐
相关产品推荐

