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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:46:03