Android BLE开发:如何在图像展示页读取新的BLE数值
嘿,这个需求其实挺典型的——就是要让图像展示页不用跳来跳去,直接就能重新读取BLE数据并更新图表对吧?结合你现有的BluetoothLeService,我给你梳理一套落地的实现方案:
核心实现思路
关键就是保持图像展示页与BLE服务的持续绑定,让页面能主动发起读取请求,同时服务能把新采集的20组数据推送给页面更新图像。
1. 让图像展示页持续绑定BluetoothLeService
你之前可能只在初始页面绑定服务,跳转后就解绑了。现在要让图像页也绑定服务,并且保持绑定状态(除非退出应用):
public class ChartDisplayActivity extends AppCompatActivity { private BluetoothLeService mBluetoothLeService; private boolean mServiceBound = false; // 服务连接回调 private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { BluetoothLeService.LocalBinder binder = (BluetoothLeService.LocalBinder) service; mBluetoothLeService = binder.getService(); mServiceBound = true; // 这里可以初始化数据监听逻辑 } @Override public void onServiceDisconnected(ComponentName arg0) { mBluetoothLeService = null; mServiceBound = false; } }; @Override protected void onStart() { super.onStart(); // 绑定BLE服务,保持连接 Intent serviceIntent = new Intent(this, BluetoothLeService.class); bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); // 只有页面销毁时才解绑服务 if (mServiceBound) { unbindService(mServiceConnection); mServiceBound = false; } } }
2. 在BluetoothLeService中封装可重复调用的读取方法
把原来的一次性读取逻辑拆成可复用的公共方法,让图像页能随时触发新的20组数据采集:
public class BluetoothLeService extends Service { private int mValueCount = 0; private List<Float> mCurrentValueList = new ArrayList<>(); // 替换成你实际的服务和特征UUID private static final String SERVICE_UUID = "你的BLE服务UUID"; private static final String CHARACTERISTIC_UUID = "你的特征值UUID"; // 新增:触发新一轮20组数据读取的方法 public void startNewValueCollection() { mValueCount = 0; mCurrentValueList.clear(); // 发起第一次特征值读取 if (mBluetoothGatt != null) { BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString(SERVICE_UUID)); if (service != null) { BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID)); mBluetoothGatt.readCharacteristic(characteristic); } } } // 重写onCharacteristicRead,完成数据收集后通知页面 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // 读取当前特征值(这里假设是Float类型,根据你的实际数据格式调整) float value = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_FLOAT, 0); mCurrentValueList.add(value); mValueCount++; if (mValueCount >= 20) { // 收集满20组,通知图像页更新 notifyChartPageWithNewData(mCurrentValueList); } else { // 继续读取下一个数值 gatt.readCharacteristic(characteristic); } } } }
3. 实现服务到图像页的数据推送
有两种常用方式把数据推送给图像页,选一种适合你的:
方式一:使用本地广播(简单易实现)
在BluetoothLeService的notifyChartPageWithNewData方法里发送广播:
private void notifyChartPageWithNewData(List<Float> values) { Intent broadcastIntent = new Intent("com.yourapp.action.BLE_NEW_VALUES"); broadcastIntent.putParcelableArrayListExtra("ble_values", new ArrayList<>(values)); LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent); }
然后在图像页注册广播接收器,接收数据并更新图像:
public class ChartDisplayActivity extends AppCompatActivity { private final BroadcastReceiver mValuesReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if ("com.yourapp.action.BLE_NEW_VALUES".equals(intent.getAction())) { List<Float> newValues = intent.getParcelableArrayListExtra("ble_values"); // 调用你的图像更新方法 updateChart(newValues); } } }; @Override protected void onResume() { super.onResume(); // 注册广播接收器 LocalBroadcastManager.getInstance(this).registerReceiver(mValuesReceiver, new IntentFilter("com.yourapp.action.BLE_NEW_VALUES")); } @Override protected void onPause() { super.onPause(); // 注销广播接收器,避免内存泄漏 LocalBroadcastManager.getInstance(this).unregisterReceiver(mValuesReceiver); } // 你的图像更新方法 private void updateChart(List<Float> values) { // 这里写生成/更新图像的逻辑 } }
方式二:使用接口回调(更直接的双向通信)
先定义一个回调接口:
public interface OnBleValuesCollectedListener { void onValuesCollected(List<Float> values); }
在BluetoothLeService中添加监听设置方法:
public class BluetoothLeService extends Service { private OnBleValuesCollectedListener mValuesListener; public void setOnBleValuesCollectedListener(OnBleValuesCollectedListener listener) { mValuesListener = listener; } private void notifyChartPageWithNewData(List<Float> values) { if (mValuesListener != null) { mValuesListener.onValuesCollected(values); } } }
然后在图像页的服务连接回调中设置监听:
@Override public void onServiceConnected(ComponentName className, IBinder service) { BluetoothLeService.LocalBinder binder = (BluetoothLeService.LocalBinder) service; mBluetoothLeService = binder.getService(); mServiceBound = true; // 设置数据回调监听 mBluetoothLeService.setOnBleValuesCollectedListener(newValues -> { // 直接更新图像 updateChart(newValues); }); }
4. 在图像页添加触发读取的入口
比如加个“重新读取”按钮,点击时调用服务的读取方法:
Button refreshBtn = findViewById(R.id.btn_refresh_data); refreshBtn.setOnClickListener(v -> { if (mServiceBound && mBluetoothLeService != null) { mBluetoothLeService.startNewValueCollection(); } });
注意事项
- 确保BLE设备连接状态稳定:可以在服务中添加连接状态的监听,一旦断开及时通知页面处理。
- 控制读取频率:BLE操作有频率限制,避免短时间内重复发起读取请求导致GATT错误。
- 内存泄漏防护:使用接口回调时,在图像页销毁前记得调用
mBluetoothLeService.setOnBleValuesCollectedListener(null);广播要及时注销。
内容的提问来源于stack exchange,提问作者Panos Panteleon
相关产品推荐
相关产品推荐

