Android onLeScan参数如何正确配置使用?

99ANYc3cd6
预计阅读时长 26 分钟
位置: 首页 参数 正文

onLeScan 是一个非常重要的回调方法,主要用于在 API 21 (Android 5.0, Lollipop) 之前 的版本中进行蓝牙低功耗设备的扫描,从 API 21 开始,Google 推荐使用新的 BluetoothLeScanner API,它功能更强大、更灵活。

android onlescan 参数
(图片来源网络,侵删)

onLeScan 的基本概念

onLeScanBluetoothAdapter.LeScanCallback 接口中的一个方法,当你调用 BluetoothAdapter.startLeScan(BluetoothAdapter.LeScanCallback) 方法时,系统会开始扫描周围的 BLE 设备,每当发现一个新的设备时,就会回调 onLeScan 方法,并将发现到的设备信息作为参数传递给你。

这个方法就是“发现 BLE 设备时的通知员”。


方法签名和参数详解

onLeScan 方法的签名如下:

/**
 * 当发现新的 BLE 设备时调用。
 *
 * @param device 被发现的蓝牙设备。
 * @param rssi   接收信号强度指示器,表示设备与手机之间的信号强度,单位是 dBm。
 * @param scanRecord 设备的广告数据。
 */
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);

下面我们逐一解析这三个核心参数:

android onlescan 参数
(图片来源网络,侵删)

BluetoothDevice device

  • 类型: BluetoothDevice
  • 含义: 代表被发现的蓝牙低功耗设备本身。
  • 作用: 这是获取设备信息的核心对象,你可以通过它来获取设备的:
    • MAC 地址: device.getAddress(),这是唯一标识一个蓝牙设备的地址。
    • 设备名称: device.getName(),注意,这个名称可能为 null,因为设备不一定会在广播数据中包含其名称。
    • Bonding State (绑定状态): device.getBondState(),可以判断设备是否已经与手机配对。

示例用法:

BluetoothDevice foundDevice = device;
String macAddress = foundDevice.getAddress();
String deviceName = foundDevice.getName(); // 可能是 null
Log.d("BLE", "发现设备: " + (deviceName != null ? deviceName : "未知") + " @ " + macAddress);

int rssi

  • 类型: int
  • 含义: 接收信号强度指示器
  • 作用: 它是一个负值(-55, -89),表示设备广播信号被你的手机接收时的强度,单位是 dBm (decibel-milliwatts)
  • 实际应用:
    • 估算距离: RSSI 值越大(即数值越接近 0),表示设备离手机越近,RSSI 值越小(即数值越小,越负),表示设备离手机越远,你可以通过经验公式或查表来估算大致的距离。
    • 筛选设备: 你可以根据 RSSI 值来过滤掉距离太远的设备,只处理 RSSI 大于 -70 dBm 的设备,这样可以减少噪音干扰,专注于附近的设备。
    • 信号质量指示: 在用户界面中,可以用 RSSI 值来显示信号的强弱(用信号格数表示)。

示例用法:

// RSSI 值越大,信号越强
if (rssi > -70) {
    Log.d("BLE", "设备信号强: " + rssi + " dBm");
} else {
    Log.d("BLE", "设备信号弱: " + rssi + " dBm");
}

byte[] scanRecord

  • 类型: byte[]
  • 含义: 设备的 广告数据扫描响应数据
  • 作用: 这是 BLE 设备向外界广播的“名片”,包含了设备希望被其他设备知道的各种信息,解析这个 byte[] 数组是 BLE 开发的核心和难点之一。
  • 广告数据中常见的内容:
    • 设备名称: 设备的本地名称。
    • 服务 UUID 列表: 设备提供的服务列表,这是最重要的信息之一,通过它可以判断设备是否是你需要连接的目标设备。
    • 服务数据: 与特定服务相关的数据。
    • 制造商特定数据: 由制造商定义的数据,通常包含一些私有信息,如设备型号、固件版本等。

如何解析 scanRecord: 直接手动解析这个字节数组非常复杂且容易出错,强烈建议使用 Google 提供的 com.android.bluetooth.le.ScanRecord 类(注意,这是 Android 框架内部的类,在官方 SDK 中没有,但通常可用)或者第三方库。

示例用法 (使用 ScanRecord 解析):

android onlescan 参数
(图片来源网络,侵删)
// 注意:ScanRecord 是 Android 框架内部的类,使用时需注意兼容性
// 通常通过反射或将其作为依赖项引入
// ScanRecord record = ScanRecord.parseFromBytes(scanRecord);
// if (record != null) {
//     String localName = record.getDeviceName();
//     List<UUID> serviceUuids = record.getServiceUuids();
//     Map<ParcelUuid, byte[]> serviceData = record.getServiceData();
//     int manufacturerId = record.getManufacturerSpecificData() != null ? 
//             record.getManufacturerSpecificData().keyAt(0) : -1;
//
//     Log.d("BLE", "设备名称: " + localName);
//     Log.d("BLE", "服务UUIDs: " + serviceUuids);
//     Log.d("BLE", "制造商ID: " + manufacturerId);
// }

完整使用示例

下面是一个在旧版 Android 上使用 onLeScan 进行扫描的完整流程。

public class BleScannerActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;
    private LeScanCallback mLeScanCallback;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble_scanner);
        // 1. 检查蓝牙是否支持并获取 BluetoothAdapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            // 设备不支持蓝牙
            Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        // 2. 检查蓝牙是否开启
        if (!mBluetoothAdapter.isEnabled()) {
            // 蓝牙未开启,可以提示用户开启
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
        // 3. 创建 LeScanCallback 实例
        mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
            @Override
            public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
                // 在主线程中更新UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 解析广播数据
                        // ... 使用 ScanRecord 或其他工具解析 ...
                        Log.d("BLE_Scanner", "发现设备: " + device.getName() + 
                              ", MAC: " + device.getAddress() + 
                              ", RSSI: " + rssi + " dBm");
                        // 在这里可以更新UI列表,将发现的设备展示给用户
                    }
                });
            }
        };
    }
    // 开始扫描
    private void startScan() {
        // 参数可以指定要扫描的 UUID,null 表示扫描所有设备
        // UUID targetUuid = ...; // 你的目标服务 UUID
        boolean success = mBluetoothAdapter.startLeScan(mLeScanCallback); // 可以传入 UUID
        if (success) {
            Log.d("BLE_Scanner", "开始扫描 BLE 设备...");
        } else {
            Log.e("BLE_Scanner", "启动扫描失败");
        }
    }
    // 停止扫描
    private void stopScan() {
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        Log.d("BLE_Scanner", "停止扫描 BLE 设备");
    }
    @Override
    protected void onResume() {
        super.onResume();
        // 在 Activity 可见时开始扫描
        startScan();
    }
    @Override
    protected void onPause() {
        super.onPause();
        // 在 Activity 不可见时停止扫描,以节省电量
        stopScan();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 确保在销毁时停止扫描
        stopScan();
    }
}

重要注意事项

  1. API 版本限制:

    • onLeScanAPI 21 (Android 5.0) 中被废弃。
    • 从 API 21 开始,必须使用新的 BluetoothLeScanner API。
    • 如果你的应用需要兼容低于 API 21 的版本,你必须使用 onLeScan,如果只支持 API 21+,则应使用新 API。
  2. 电量消耗:

    • 扫描 BLE 设备是持续消耗电量的操作,一旦找到目标设备或者不再需要扫描,务必调用 stopLeScan() 来停止扫描,否则会严重影响设备续航。
  3. 运行线程:

    • onLeScan 回调是在一个 后台线程 中执行的,如果你需要更新 UI(将设备添加到 ListViewRecyclerView),你必须使用 runOnUiThread()Handler 将操作切换到主线程。
  4. 广播数据解析:

    • 手动解析 scanRecord 是复杂的,对于新项目,应优先考虑使用 BluetoothLeScanner,并结合 ScanResultScanRecord 类,它们提供了更友好的 API 来解析广播数据。

onLeScan vs. BluetoothLeScanner (新 API)

特性 onLeScan (旧 API) BluetoothLeScanner (新 API, API 21+)
可用版本 API 3 - 20 (已废弃) API 21+
回调方式 BluetoothAdapter.LeScanCallback ScanCallback
回调方法 onLeScan(device, rssi, scanRecord) onScanResult(callbackType, result)onBatchScanResults(results)
参数对象 直接传递 BluetoothDevice, rssi, byte[] 传递 ScanResult 对象,其中包含 device, rssi, getScanRecord()
功能 基础扫描功能 强大得多:支持设置扫描模式、回调类型、过滤条件(UUID, 设备名称, MAC地址, 制造商数据等)
功耗控制 功能单一 提供低功耗、平衡、低延迟等多种扫描模式,更省电
推荐度 仅用于兼容旧版本 强烈推荐 用于所有新项目

onLeScan 的三个参数 device, rssi, scanRecord 分别代表了 “发现谁”“离多远”“它有什么信息”,理解这三个参数的含义和使用方法是进行 BLE 设备发现和连接的第一步,虽然它已被新 API 取代,但在处理 Android 生态的向后兼容性时,它仍然是一个不可或缺的知识点。

-- 展开阅读全文 --
头像
索尼Xperia ZX Premium参数有哪些亮点?
« 上一篇 12-01
iPad Pro 12.9(2025)拆解,内部有哪些升级?
下一篇 » 12-01

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]