如何在安卓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实时监测场景。
实现步骤
- 先在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' }
- 主页面实现代码:
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
相关产品推荐
相关产品推荐

