Android实现蓝牙持续扫描的方法

  • Post author:
  • Post category:其他







前言

随着BLE蓝牙技术的发展,利用蓝牙进行数据信息交互变得越来越常见。但是Android的蓝牙扫描默认只是一次性的短时间扫描。为了实现持续扫描的效果,我们需要自定义扫描逻辑。

蓝牙是一种让设备在短距离内进行无线通信的技术。在Android系统上,我们可以通过蓝牙API以编程方式扫描附近的蓝牙设备。

默认情况下,蓝牙扫描只会执行一次并返回发现的设备列表。但是,我们通常需要持续一段时间扫描蓝牙设备。这样可以检测到初始扫描时可能关闭或不在范围内的设备。



那么我们该如何实现蓝牙持续扫描的方法呢?接下来让我们一起来看看吧!

最近项目开发中,对于蓝牙血糖仪测量模块在实际应用中,需要让蓝牙持续扫描,根据mac地址可以指定连接到设备之后,进行测量等其他操作。

项目中应用的低功耗蓝牙血糖仪,这里和大家提一嘴。不论传统蓝牙,还是低功耗的,其实对于持续扫描蓝牙这个功能,根据不同的用户场景处理都是一样的。



持续蓝牙扫描

持续蓝牙扫描意思是:

让蓝牙一直处于扫描状态,需要注意的是扫描会消耗更多电量,可以根据需要适当调整扫码周期。


1、

通过注册BroadcastReceiver的形式来监听蓝牙扫描状态。


2、

为了让扫描一直持续,可以在一个后台Service里进行扫描,并不断调用startLeScan()重新启动扫描。另外可以在扫描到设备后继续扫描而不是停止。


3、

在一个while(true)循环里持续调用startLeScan()重新扫描, 获取到扫描结果后可以选择连接或过滤处理。



实际应用

这里举例

两种形式

,来

实现蓝牙持续扫描功能


方式一:

通过

注册BroadcastReceiver的形式

来实现此功能。

  1. 定义BroadcastReceiver用于接收扫描结果
private BroadcastReceiver scanReceiver = new BroadcastReceiver() {

  @Override
  public void onReceive(Context context, Intent intent) {
    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    // 获取扫描到的设备并处理
  }

};
  1. 在onCreate中初始化
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(scanReceiver, filter);
  1. 开一个线程持续扫描
new Thread(new Runnable() {
  @Override
  public void run() {
    while(true) {
      adapter.startLeScan(leScanCallback);
      try {
        Thread.sleep(10000); // 间隔10秒后继续扫描 
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      adapter.stopLeScan(leScanCallback); 
    }
  }
}).start();
  1. 在onDestroy中注销receiver
@Override
protected void onDestroy() {
  unregisterReceiver(scanReceiver);
  super.onDestroy();
}


方式二:



一个while(true)循环里持续调用startLeScan()重新扫描

, 获取到扫描结果后可以选择连接或过滤处理。

在开一个线程持续扫描蓝牙的情况下,如果想在退出Activity时停止扫描线程,可以通过如下几种方式:

  1. 设置一个标志位来控制线程的运行状态:
private boolean scanning = true;

// 在线程中
while(scanning) {
  // 扫描逻辑
}

// 在onDestroy中
scanning = false;
  1. 使用线程的interrupt()方法中断线程:
Thread scanThread;

// 在onCreate中
scanThread = new Thread() {
  @Override 
  public void run() {
    while(true) {
      // 扫描逻辑 
    }
  }
};
scanThread.start();

// 在onDestroy中
scanThread.interrupt();
  1. 使用Handler发消息通知线程停止:
Handler handler;

// 在线程中
public void run() {
  while(true) {
    if(handler.hasMessages(MSG_STOP)) {
      break;
    }
    // 扫描逻辑
  }
}

// 在onDestroy中 
handler.sendEmptyMessage(MSG_STOP);
  1. 使用ExecutorService执行线程,在onDestroy中调用shutdownNow():
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(scanTask);

// 在onDestroy中
executor.shutdownNow(); 
  1. 在扫描循环加入退出条件:
boolean stop = false;
while(!stop) {
  // 扫描逻辑
}

// 在onDestroy中
stop = true;

对于如上第二种方式中,我自己应用的是(1)中的形式,

设置一个标志位来控制线程的运行状态,具体执行如下:

private boolean scanning = true;

// 开启一个线程
new Thread(new Runnable() {
    @Override
    public void run() {
       while (scanning) {
          initBle();
          LogUtils.e("开始执行扫描handler >>>", "startScan");
          try {
              Thread.sleep(10000); // 间隔10秒后继续扫描
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          BleManager.getInstance().cancelScan();
          LogUtils.e("开始执行扫描handler >>>", "取消扫描");
       }
    }
  }).start();

// 在onDestroy中
@Override
protected void onDestroy() {  
	scanning = false;
    super.onDestroy();
}



最后

到这里,实现蓝牙持续扫描的功能,就已经完成了,欢迎各位质检,点击关注❤️,留言探讨!

这里有一个重点,有的开辟线程之后,没有关闭扫描,

每隔10秒都会执行扫描

。每当退出蓝牙连接界面后,它会一直扫描。因此在当前活动页销毁的时候,记得添加标识位,且销毁蓝牙连接。

还有需要注意的是

扫描会消耗更多电量,可以根据需要适当调整扫码周期



版权声明:本文为chen_md原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。