适配Android12/13时AltBeacon库BluetoothMedic崩溃问题求助
Android 12(Target SDK 31)下AltBeacon库蓝牙权限崩溃问题解决
已完成的适配操作
- 修复清单文件报错:将
org.altbeacon.android-beacon-library升级至2.19.4版本,解决库中接收器未设置android:exported属性的问题。 - 配置蓝牙权限:
添加Android 12+专属蓝牙权限:
限制旧蓝牙权限仅在Android 11及以下生效:<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
声明蓝牙硬件特性(非强制依赖):<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /><uses-feature android:name="android.hardware.bluetooth" android:required="false"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/> - 动态请求权限:针对Android 12及以上版本,在代码中检查并请求蓝牙权限:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { FirebaseCrashlytics.getInstance().log("requesting permissions."); ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_ADVERTISE, }, 22); }
崩溃现象
- 崩溃类型:触发
java.lang.SecurityException,提示缺少BLUETOOTH_ADVERTISE或BLUETOOTH_SCAN权限,典型崩溃栈如下:Fatal Exception: java.lang.SecurityException: Need android.permission.BLUETOOTH_ADVERTISE permission for android.content.AttributionSource@881430fb: GattService startAdvertisingSet at com.android.bluetooth.Utils.checkPermissionForDataDelivery(Utils.java:482) at com.android.bluetooth.Utils.checkAdvertisePermissionForDataDelivery(Utils.java:570) at com.android.bluetooth.gatt.GattService.startAdvertisingSet(GattService.java:3252) at com.android.bluetooth.gatt.GattService$BluetoothGattBinder.startAdvertisingSet(GattService.java:1392) at com.android.bluetooth.gatt.GattService$BluetoothGattBinder.startAdvertisingSet(GattService.java:1376) at android.bluetooth.IBluetoothGatt$Stub.onTransact(IBluetoothGatt.java:362) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1244) - 附加特征:
- 崩溃集中在应用启动后1-5秒内;
- 未生成FirebaseCrashlytics相关日志,推测崩溃发生在权限请求执行前的库初始化阶段;
- 99%的崩溃案例出现在三星设备;
- 非三星Android 12设备测试正常:关闭“附近设备”权限后重启会重新发起权限请求,拒绝后无蓝牙功能但应用可正常运行。
解决方案
1. 延迟AltBeacon库初始化,确保权限请求完成后再启动
崩溃核心原因是库在权限未授予时就提前调用蓝牙API,三星设备对权限检查的时机管控更严格。调整逻辑:
- 在权限请求回调
onRequestPermissionsResult中,确认所有蓝牙权限授予后再初始化AltBeacon服务; - 用户拒绝权限时,跳过蓝牙相关功能的初始化流程。
示例代码:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 22) { boolean allPermissionsGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (allPermissionsGranted) { // 权限全部授予,初始化AltBeacon服务 initializeBeaconManager(); } else { // 权限被拒绝,处理无蓝牙功能的场景 handleBluetoothUnavailable(); } } }
2. 针对三星设备的特殊适配
三星Android 12可能存在权限检查提前触发的问题,可在Application的onCreate中先校验权限状态,未授予则延迟初始化:
@Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { boolean hasScanPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED; boolean hasAdvertisePerm = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADVERTISE) == PackageManager.PERMISSION_GRANTED; boolean hasConnectPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED; if (hasScanPerm && hasAdvertisePerm && hasConnectPerm) { initializeBeaconManager(); } else { // 延迟到权限请求完成后初始化,可通过EventBus或广播通知 } } else { // Android 11及以下直接初始化 initializeBeaconManager(); } }
3. 捕获库中的权限异常
尽管AltBeacon库本身会处理权限逻辑,但三星设备可能存在特殊场景,可在初始化或启动扫描的代码外层添加异常捕获:
try { beaconManager.startRangingBeaconsInRegion(region); } catch (SecurityException e) { FirebaseCrashlytics.getInstance().recordException(e); // 处理无权限场景,比如提示用户开启权限 }
4. 优化权限声明
如果BLUETOOTH_SCAN仅用于扫描非BLE设备,可添加android:usesPermissionFlags="neverForLocation"属性,避免与位置权限关联导致的权限校验问题:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
内容的提问来源于stack exchange,提问作者RobertT
相关产品推荐
相关产品推荐

