You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

适配Android12/13时AltBeacon库BluetoothMedic崩溃问题求助

Android 12(Target SDK 31)下AltBeacon库蓝牙权限崩溃问题解决

已完成的适配操作

  • 修复清单文件报错:将org.altbeacon.android-beacon-library升级至2.19.4版本,解决库中接收器未设置android:exported属性的问题。
  • 配置蓝牙权限:
    添加Android 12+专属蓝牙权限:
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    
    限制旧蓝牙权限仅在Android 11及以下生效:
    <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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:25:28