Android(Kotlin)实现BLE设备选中后自动连接方案求助
解决方案
1. 自动启用蓝牙(无需手动开关)
首先在AndroidManifest.xml中声明必要的蓝牙权限:
<!-- Android 11及以下 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
在Activity/Fragment初始化时自动检查蓝牙状态,未开启则请求用户启用:
private val bluetoothAdapter: BluetoothAdapter? by lazy { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 先请求必要权限,再处理蓝牙逻辑 requestPermissions() } private fun checkBluetoothAndStartScan() { bluetoothAdapter?.let { adapter -> if (!adapter.isEnabled) { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) } else { startBleScan() } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) { startBleScan() } } companion object { private const val REQUEST_ENABLE_BT = 1 private const val REQUEST_PERMISSIONS = 2 }
2. 自动启动BLE扫描(无需手动点击扫描按钮)
将扫描逻辑绑定到蓝牙启用后的回调,无需扫描按钮触发:
private var bleScanner: BluetoothLeScanner? = null private val deviceList = mutableListOf<BluetoothDevice>() private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { super.onScanResult(callbackType, result) val device = result.device // 避免重复添加设备 if (!deviceList.any { it.address == device.address }) { deviceList.add(device) deviceAdapter.notifyDataSetChanged() } } override fun onScanFailed(errorCode: Int) { super.onScanFailed(errorCode) Toast.makeText(this@MainActivity, "扫描失败,错误码:$errorCode", Toast.LENGTH_SHORT).show() } } private fun startBleScan() { bleScanner = bluetoothAdapter?.bluetoothLeScanner val scanSettings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build() bleScanner?.startScan(emptyList(), scanSettings, scanCallback) } // 生命周期中停止扫描,避免资源浪费 override fun onPause() { super.onPause() bleScanner?.stopScan(scanCallback) }
3. 选中设备后自动连接(无需手动点击连接按钮)
修改设备列表的点击事件,直接触发连接逻辑,移除单独的连接按钮:
// 假设用RecyclerView展示设备列表 private val deviceAdapter = object : RecyclerView.Adapter<DeviceViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeviceViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_device, parent, false) return DeviceViewHolder(view) } override fun getItemCount() = deviceList.size override fun onBindViewHolder(holder: DeviceViewHolder, position: Int) { val device = deviceList[position] holder.tvName.text = device.name ?: "未知设备" holder.tvAddress.text = device.address // 点击列表项直接连接 holder.itemView.setOnClickListener { bleScanner?.stopScan(scanCallback) connectToDevice(device) } } } class DeviceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvName: TextView = itemView.findViewById(R.id.tv_device_name) val tvAddress: TextView = itemView.findViewById(R.id.tv_device_address) } // BLE连接核心逻辑 private var gatt: BluetoothGatt? = null private fun connectToDevice(device: BluetoothDevice) { gatt = device.connectGatt(this, false, gattCallback) } private val gattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { super.onConnectionStateChange(gatt, status, newState) runOnUiThread { when (newState) { BluetoothProfile.STATE_CONNECTED -> { Toast.makeText(this@MainActivity, "已连接到${gatt.device.name}", Toast.LENGTH_SHORT).show() gatt.discoverServices() } BluetoothProfile.STATE_DISCONNECTED -> { Toast.makeText(this@MainActivity, "连接断开", Toast.LENGTH_SHORT).show() gatt.close() } } } } override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { super.onServicesDiscovered(gatt, status) if (status == BluetoothGatt.GATT_SUCCESS) { // 服务发现成功,可进行特征读写操作 val services = gatt.services // 这里处理你的业务逻辑,比如读取特征值 } } } // 销毁时关闭Gatt连接 override fun onDestroy() { super.onDestroy() gatt?.close() }
权限补充处理
Android 6.0+需要动态申请权限,添加以下代码:
private fun requestPermissions() { val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT) } else { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_ADMIN) } ActivityCompat.requestPermissions(this, permissions, REQUEST_PERMISSIONS) } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_PERMISSIONS && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { checkBluetoothAndStartScan() } else { Toast.makeText(this, "需要授予权限才能使用BLE功能", Toast.LENGTH_SHORT).show() } }
内容的提问来源于stack exchange,提问作者박종준
相关产品推荐
相关产品推荐

