You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 21:17:18