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

Android调用ScanResult.getScanRecord()触发空指针异常如何解决

问题根因

从抛出的异常栈可以直接定位:崩溃触发点是调用ScanResult.getScanRecord()方法时,mScanResult实例本身为null。原有代码的判空逻辑只覆盖了getServiceData()的空场景,完全没有对上层的mScanResult、getScanRecord()返回值做非空校验,加上BLE扫描流程本身存在大量返回空值的场景,直接链式调用必然触发空指针。
从异常信息里的Unable to start activity可以进一步确认:崩溃发生在Second页面启动阶段,此时大概率蓝牙扫描还未返回有效结果,mScanResult还停留在初始null状态就被调用了方法。

排查步骤
  • 核对mScanResult赋值时机:检查mScanResult的赋值逻辑是否在页面启动(onCreate/onStart生命周期)前完成,是否存在页面已经加载、扫描回调还没触发就提前读取扫描结果的问题
  • 校验蓝牙相关权限:Android 12及以上版本需要BLUETOOTH_SCAN运行时权限,Android 11及以下版本需要精确定位权限,权限未授予时扫描结果会直接返回null,不会正常回调有效ScanResult
  • 检查扫描流程状态:确认BLE扫描是否正常启动,蓝牙开关是否打开,是否存在扫描未初始化、扫描被系统中断的情况,导致onScanResult回调从未触发,mScanResult一直是初始null值
  • 兼容厂商ROM差异:部分国产定制ROM对BLE扫描做了限制,即使权限、流程都正常,也可能返回null的ScanResult或者null的ScanRecord,不能默认系统返回的对象一定非空
修复方案
  1. 替换原有长链式调用,做逐层非空校验,避免某一层返回null直接崩溃,修复后的代码如下:
// 从最外层对象开始逐层判空,每一步都确认对象非空再调用下一层方法
if (this.mScanResult != null) {
    ScanRecord scanRecord = this.mScanResult.getScanRecord();
    if (scanRecord != null) {
        SparseArray<byte[]> serviceData = scanRecord.getServiceData();
        if (serviceData != null && serviceData.size() > 0) {
            advertisementData = advertisementData + "Service Data: " + serviceData.toString().replace('{', ' ').replace('}', ' ') + "\n";
        }
    }
}
  1. 补充流程层面的防护:
  • 不要在页面刚启动的生命周期方法里直接读取mScanResult内容,把读取、解析扫描结果的逻辑放到onScanResult回调成功、mScanResult完成有效赋值之后再触发
  • 给mScanResult赋值时先做非空校验,null的无效结果直接丢弃,避免脏数据触发后续崩溃
  • 启动BLE扫描前先校验蓝牙开关状态、相关权限是否已授予,不满足前置条件时不要启动扫描,同时给用户对应的开启提示
  • 如果是通过页面跳转传递扫描结果,不要直接把ScanResult对象通过Intent序列化传递,部分ROM下跨进程序列化会失败导致取到null,建议提取需要的业务字段(比如服务数据、设备MAC、信号强度)转成基础数据类型后再传递

内容的提问来源于stack exchange,提问作者Agram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:27:26