Android 7.0 BLE scan 问题:程序无错但扫描不到BLE设备

本文分享了作者在实现Android蓝牙低功耗(BLE)扫描功能时遇到的问题及解决过程。文章详细介绍了如何通过正确配置Android应用的权限,确保BLE扫描能够正常工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做毕设,需要几周内从头学起Android及BLE开发,遇到了N个坑。

最近好不容易看懂了各路BLE例程东拼西凑出了一个自己的版本,仅有Scan及显示BLE设备的功能,编译一切正常,然而按下scan之后直到timeout,listview里都没有扫描结果,debug后发现根本就没有callback,为此懵逼了一下午......

google上各种搜,大部分说是7.0使用BLE还需要添加位置权限,需要在manifest文件中添加以下两行代码(之一)

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

然而二货如我觉得添加了这两行就完事儿了,结果一运行还是没动静.......

后来晃过神来,设置里的位置权限是不是没打开?

果然.......打开app对应的位置权限,成功运行!.......

所以在此把这个问题的解决方案说清楚(对就是我怕自己太二结果忘了所以在这里记录一下):

1. manifest里添加上面两行代码!

2. 手动在手机/平板的设置里把所开发App的位置权限开启(有什么权限开什么权限得了,省的后面又进坑......)!

<think>嗯,用户想了解Android BLE开发的详细流程步骤,而且要求最新的。首先,我需要回忆一下Android BLE的基本知识,然后看看最近有没有什么更新。记得Android从不同版本开始对BLE的支持有变化,特别是Android 12和13可能有一些权限方面的调整。 首先,应该从权限开始讲起。Android BLE需要蓝牙相关的权限,比如BLUETOOTH和BLUETOOTH_ADMIN,还有位置权限,因为扫描BLE设备需要ACCESS_FINE_LOCATION或者ACCESS_COARSE_LOCATION,不过可能从Android 12开始,位置权限的要求有变化,或者可能需要动态申请。这一点需要确认,避免过时的信息。 然后,检查蓝牙是否支持,是否开启。这部分流程应该没有太大变化,还是通过BluetoothManager获取BluetoothAdapter,然后检查是否可用,如果没开的话提示用户打开。 接下来是设备扫描,这里可能需要使用BluetoothLeScanner,并且要注意Android 5.0以上的扫描API,还有Android 6.0以上的动态权限申请。扫描时可能需要使用ScanCallback,设置扫描过滤条件和扫描设置,比如低延迟模式或者低功耗模式。 连接设备的部分,需要建立Gatt连接,使用BluetoothDevice的connectGatt方法,传入Context、autoConnect参数和BluetoothGattCallback。这里要注意不同的Android版本可能对自动连接的处理方式不同,以及可能需要在主线程执行。 连接成功后,发现服务,也就是discoverServices(),然后在回调中处理服务发现完成的情况,获取BluetoothGattService,再找到对应的特征值Characteristic。这里可能需要处理不同的服务和特征UUID,用户可能需要自己根据设备的文档来替换。 读写操作需要确保特征的可写性,比如是否有WRITE属性,或者是否需要启用通知。对于通知,需要设置特征的通知,写入Descriptor,然后监听onCharacteristicChanged回调。这部分要注意线程安全,可能需要用Handler来处理回调到主线程。 错误处理也很重要,比如连接失败、服务发现失败、读写超时等,需要适当的重试机制或者用户提示。此外,Android BLE有连接数量限制,超过的话可能会出现问题,需要提醒用户。 资源释放方面,记得在不需要的时候关闭Gatt连接,释放相关资源,避免内存泄漏。还有,Android版本差异,比如Android 7.0限制了扫描次数,或者后台扫描的限制,这些可能需要特别处理。 最新的变化可能包括Android 12(API 31)引入的BLUETOOTH_SCAN、BLUETOOTH_CONNECT和BLUETOOTH_ADVERTISE权限,这些在targetSdkVersion 31及以上时需要处理,可能需要检查是否需要NEARBY_DEVICES权限,以及是否需要声明neverForLocation属性,如果应用不需要位置信息的话。这样可以避免必须请求位置权限。 可能用户在实际开发中遇到的问题,比如扫描不到设备,连接不稳定,读写失败等,应该在步骤中提到注意事项,比如确保设备在范围内,权限正确,还有正确的UUID配置。此外,Android Studio的BLE调试工具和日志的重要性也需要提及,帮助用户调试。 总结一下,需要分步骤讲解权限、初始化、扫描、连接、服务发现、数据读写、通知设置、错误处理和资源管理,同时涵盖最新的权限变化和最佳实践。确保用户按照步骤操作能够顺利进行BLE开发,避免常见的坑。</think>以下为Android BLE开发的最新流程(基于Android 13及最新API): --- ### 一、环境准备 1. **硬件要求** - 手机支持BLE 4.0+(Android 4.3+) - 目标BLE设备处于广播状态 2. **Gradle配置** ```groovy android { compileSdk 34 buildFeatures { dataBinding true } } dependencies { implementation 'androidx.core:core-ktx:1.12.0' } ``` --- ### 二、权限声明 ```xml <!-- Android 12+ 需要新权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <!-- 若不需定位 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 11及以下 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> ``` --- ### 三、核心开发流程 #### 1. 检查BLE支持 ```kotlin val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager if (!packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { showToast("设备不支持BLE") } val bluetoothAdapter = bluetoothManager.adapter ``` #### 2. 动态权限申请(Android 12+) ```kotlin 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, Manifest.permission.BLUETOOTH_ADMIN ) } ActivityResultContracts.RequestMultiplePermissions().launch(permissions) ``` #### 3. 扫描BLE设备 ```kotlin val scanner = bluetoothAdapter.bluetoothLeScanner val settings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build() val filter = ScanFilter.Builder() .setServiceUuid(ParcelUuid(SERVICE_UUID)) .build() scanner.startScan(listOf(filter), settings, scanCallback) private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { // 处理扫描结果 } } ``` #### 4. 连接设备 ```kotlin val device = bluetoothAdapter.getRemoteDevice(deviceAddress) val gatt = device.connectGatt(context, false, gattCallback) private val gattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { if (newState == BluetoothProfile.STATE_CONNECTED) { gatt.discoverServices() // 关键步骤! } } } ``` #### 5. 发现服务与特征值 ```kotlin override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { val service = gatt.getService(SERVICE_UUID) val characteristic = service.getCharacteristic(CHARACTERISTIC_UUID) // 启用通知 gatt.setCharacteristicNotification(characteristic, true) val descriptor = characteristic.getDescriptor(CCC_DESCRIPTOR_UUID) descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE gatt.writeDescriptor(descriptor) } ``` #### 6. 数据读写 ```kotlin // 写入数据 characteristic.value = byteArrayOf(0x01, 0x02) gatt.writeCharacteristic(characteristic) // 读取数据 gatt.readCharacteristic(characteristic) // 接收数据(在回调中) override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { val data = characteristic.value } ``` --- ### 四、注意事项 1. **线程安全**:所有BLE操作应在主线程执行 2. **连接限制**:Android设备最多同时连接7BLE设备 3. **超时处理**:建议添加5-10秒的连接超时机制 4. **资源释放**: ```kotlin fun disconnect() { gatt?.disconnect() gatt?.close() } ``` 5. **后台限制**:Android 10+限制后台扫描频率,需使用前台服务 --- ### 五、最新特性支持 1. **Phy Update**(Android 8.0+) ```kotlin gatt.readPhy() gatt.setPreferredPhy(BluetoothDevice.PHY_LE_2M, ...) ``` 2. **Periodic Advertising**(Android 10+) 3. **Direction Finding**(Android 12+需硬件支持) 建议使用最新版Android BLE库:`androidx.bluetooth:bluetooth:1.0.1` 以获得更好的API支持。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值