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

如何在安卓ECG监测应用中获取Ubidots实时更新的变量数据

安卓端Ubidots变量实时更新实现方案

问题本质

你当前的实现仅在Activity启动时执行了一次AsyncTask拉取数据,没有建立持续的更新监听机制,因此只能拿到启动时的最新值。下面提供两种可行实现方案:

方案1:短轮询(改动最小,快速适配)

通过定时任务重复拉取变量最新值,比对上一次缓存值判断是否有更新,有变更则同步到UI。

实现代码

public class MainActivity extends Activity {
    private TextView ecgLevel;
    String lastVariableValue = "";
    private ScheduledExecutorService scheduler;
    // 填写自己的Ubidots凭证
    private final String API_KEY = "你的API_KEY";
    private final String VARIABLE_ID = "你的变量ID";
    // 轮询间隔单位毫秒,可根据ECG更新频率调整,建议最低1000ms以上避免被接口限流
    private final long POLL_INTERVAL = 2000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ecgLevel = findViewById(R.id.ecg);
        // 初始化定时线程池
        scheduler = Executors.newSingleThreadScheduledExecutor();
        // 启动轮询任务,延迟0s开始,每隔POLL_INTERVAL执行一次
        scheduler.scheduleAtFixedRate(pollTask, 0, POLL_INTERVAL, TimeUnit.MILLISECONDS);
    }

    // 轮询任务
    private final Runnable pollTask = new Runnable() {
        @Override
        public void run() {
            ApiClient apiClient = new ApiClient(API_KEY);
            Variable ecgVariable = apiClient.getVariable(VARIABLE_ID);
            Value[] variableValues = ecgVariable.getValues();
            if (variableValues != null && variableValues.length > 0) {
                double currentValue = variableValues[0].getValue();
                String currentStr = String.valueOf(currentValue);
                // 仅值变更时更新UI,UI操作要切回主线程
                if (!currentStr.equals(lastVariableValue)) {
                    lastVariableValue = currentStr;
                    runOnUiThread(() -> ecgLevel.setText(currentStr));
                }
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 页面销毁时停止轮询,避免内存泄漏和无效请求
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
        }
    }
}

注意事项

  • 轮询间隔不要设置过短,否则会增加功耗、消耗流量,还可能触发Ubidots的接口限流规则
  • 仅适合ECG更新频率不高的测试场景,生产环境推荐用方案2

方案2:MQTT订阅(生产级推荐,低延迟低功耗)

Ubidots原生支持MQTT协议的变量更新推送,不需要主动轮询,变量更新时服务器会主动下发最新值,延迟更低、资源消耗更小,完全适配ECG实时监测场景。

实现步骤

  1. 先在build.gradle(Module级)添加MQTT依赖:
dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
  1. 主页面实现代码:
public class MainActivity extends Activity {
    private TextView ecgLevel;
    private MqttAndroidClient mqttClient;
    // 填写自己的Ubidots凭证
    private final String API_KEY = "你的API_KEY";
    private final String VARIABLE_ID = "你的变量ID";
    private final String DEVICE_LABEL = "你的设备Label";
    private final String MQTT_BROKER = "tcp://industrial.api.ubidots.com:1883";
    // 订阅topic格式固定为 /v2.0/devices/{设备label}/{变量label}
    private final String SUBSCRIBE_TOPIC = "/v2.0/devices/" + DEVICE_LABEL + "/ecg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ecgLevel = findViewById(R.id.ecg);
        initMqttClient();
    }

    private void initMqttClient() {
        String clientId = MqttClient.generateClientId();
        mqttClient = new MqttAndroidClient(getApplicationContext(), MQTT_BROKER, clientId);
        MqttConnectOptions options = new MqttConnectOptions();
        // Ubidots MQTT连接用户名固定为API_KEY,密码留空即可
        options.setUserName(API_KEY);
        options.setAutomaticReconnect(true);
        options.setCleanSession(true);

        try {
            mqttClient.connect(options, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    // 连接成功后订阅变量更新topic
                    subscribeToVariable();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    // 连接失败可自行添加重试逻辑
                }
            });

            // 设置消息接收回调
            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {}

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    // 收到变量更新消息,解析后更新UI
                    String payload = new String(message.getPayload());
                    // 这里可根据Ubidots返回的JSON格式解析出value值
                    JSONObject jsonObject = new JSONObject(payload);
                    double ecgValue = jsonObject.getDouble("value");
                    runOnUiThread(() -> ecgLevel.setText(String.valueOf(ecgValue)));
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {}
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void subscribeToVariable() {
        try {
            mqttClient.subscribe(SUBSCRIBE_TOPIC, 0);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 销毁时断开MQTT连接
        try {
            if (mqttClient != null && mqttClient.isConnected()) {
                mqttClient.disconnect();
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  • 需要提前在AndroidManifest.xml添加网络权限、MQTT服务声明
  • MQTT的QoS等级可根据需求调整,0级即可满足大部分ECG监测场景

内容的提问来源于stack exchange,提问作者Jyoti Prakash Uprety

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:18:03