package com.narutohuo.xindazhou.ble.util import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.bluetooth.le.BluetoothLeScanner import android.bluetooth.le.ScanCallback import android.bluetooth.le.ScanFilter import android.bluetooth.le.ScanResult import android.bluetooth.le.ScanSettings import android.content.Context import android.os.Handler import android.os.Looper import com.narutohuo.xindazhou.core.log.ILog /** * BLE扫描器 * * 负责 BLE 设备的扫描,返回符合过滤条件的 BluetoothDevice 列表 * 使用 Android 12+ 推荐的 BluetoothLeScanner API */ class BleScanner( private val context: Context, private val onDeviceFound: (BluetoothDevice) -> Unit, private val onScanFinished: () -> Unit ) { private val tag = "BleScanner" private val bluetoothAdapter: BluetoothAdapter by lazy { val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager manager.adapter } private var scanner: BluetoothLeScanner? = null private var scanning = false private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { result.device?.let { onDeviceFound(it) stopScan() } } override fun onBatchScanResults(results: List) { results.forEach { it.device?.let { device -> onDeviceFound(device) stopScan() } } } override fun onScanFailed(errorCode: Int) { ILog.e(tag, "BLE scan failed, error=$errorCode") stopScan() } } /** * 开始扫描(默认 10 秒后自动停止) */ @android.annotation.SuppressLint("MissingPermission") fun startScan(filterNamePrefix: String? = null, timeoutMs: Long = 10_000L) { if (scanning) return scanner = bluetoothAdapter.bluetoothLeScanner val settings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build() val filters = mutableListOf() filterNamePrefix?.let { filters.add(ScanFilter.Builder().setDeviceName(it).build()) } try { scanner?.startScan(filters, settings, scanCallback) scanning = true ILog.d(tag, "开始扫描BLE设备,过滤前缀: $filterNamePrefix") // 超时自动停止 Handler(Looper.getMainLooper()).postDelayed({ stopScan() }, timeoutMs) } catch (e: SecurityException) { ILog.e(tag, "扫描权限不足", e) scanning = false } catch (e: Exception) { ILog.e(tag, "启动扫描失败", e) scanning = false } } /** * 停止扫描 */ @android.annotation.SuppressLint("MissingPermission") fun stopScan() { if (!scanning) return try { scanner?.stopScan(scanCallback) scanning = false ILog.d(tag, "停止扫描") onScanFinished() } catch (e: SecurityException) { ILog.e(tag, "停止扫描权限不足", e) } catch (e: Exception) { ILog.e(tag, "停止扫描失败", e) } } }