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

应用因系统或异常崩溃时能否调用方法?如何终止BLE会话及对象?

应用崩溃时终止BLE会话及相关对象的解决方案

全局异常捕获与清理入口

实现自定义UncaughtExceptionHandler替换系统默认处理器,在应用崩溃触发异常时优先执行BLE资源清理逻辑:

public class AppCrashHandler implements Thread.UncaughtExceptionHandler {
    private final Thread.UncaughtExceptionHandler defaultHandler;
    private final BleManager bleManager;

    public AppCrashHandler(BleManager manager) {
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        bleManager = manager;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 优先执行BLE全量清理
        bleManager.cleanupAllSessions();
        // 交回系统默认崩溃处理流程
        if (defaultHandler != null) {
            defaultHandler.uncaughtException(t, e);
        }
    }
}

在Application的onCreate中注册该处理器:

@Override
public void onCreate() {
    super.onCreate();
    Thread.setDefaultUncaughtExceptionHandler(
        new AppCrashHandler(BleManager.getInstance())
    );
}

统一BLE会话集中管理

避免在零散类中独立持有BLE对象,用全局单例BleManager统一管理所有Gatt实例、会话回调:

public class BleManager {
    private static volatile BleManager instance;
    private final Map<String, BluetoothGatt> gattMap = new HashMap<>();
    private final Map<String, BluetoothGattCallback> callbackMap = new HashMap<>();

    public static BleManager getInstance() {
        if (instance == null) {
            synchronized (BleManager.class) {
                if (instance == null) {
                    instance = new BleManager();
                }
            }
        }
        return instance;
    }

    // 注册BLE会话
    public void registerSession(String deviceAddr, BluetoothGatt gatt, BluetoothGattCallback callback) {
        gattMap.put(deviceAddr, gatt);
        callbackMap.put(deviceAddr, callback);
    }

    // 全量清理BLE会话
    public void cleanupAllSessions() {
        for (Map.Entry<String, BluetoothGatt> entry : gattMap.entrySet()) {
            BluetoothGatt gatt = entry.getValue();
            // 移除回调避免内存泄漏
            BluetoothGattCallback callback = callbackMap.get(entry.getKey());
            if (callback != null) {
                gatt.setCallback(null);
            }
            // 断开并关闭Gatt连接
            gatt.disconnect();
            gatt.close();
        }
        // 清空资源集合
        gattMap.clear();
        callbackMap.clear();
    }
}

所有类创建BLE会话时,必须通过BleManager.registerSession()注册,确保崩溃时能被统一清理。

零散BLE对象的补充清理

针对无法纳入全局管理的零散BLE操作类,定义统一的资源释放接口,在崩溃时遍历执行释放:

// 定义资源释放接口
public interface BleResourceReleasable {
    void releaseBleResources();
}

在BLE操作类中实现该接口:

public class CustomBleTask implements BleResourceReleasable {
    private BluetoothGatt gatt;

    @Override
    public void releaseBleResources() {
        if (gatt != null) {
            gatt.disconnect();
            gatt.close();
            gatt = null;
        }
    }
}

修改AppCrashHandler,维护可释放对象列表:

public class AppCrashHandler implements Thread.UncaughtExceptionHandler {
    // ... 原有代码
    private final List<BleResourceReleasable> releasableList = new ArrayList<>();

    // 对外提供注册入口
    public void registerReleasable(BleResourceReleasable obj) {
        releasableList.add(obj);
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 先清理零散BLE对象
        for (BleResourceReleasable obj : releasableList) {
            obj.releaseBleResources();
        }
        releasableList.clear();
        // 再执行全局BLE会话清理
        bleManager.cleanupAllSessions();
        // ... 系统默认处理
    }
}

关键注意事项

  • 崩溃清理逻辑必须极简,避免在清理过程中再次抛出异常,覆盖原始崩溃信息;
  • Android中BLE断开为异步操作,清理时无需等待回调确认,直接执行disconnect()+close()即可确保资源释放;
  • 测试时可主动抛出异常(如throw new RuntimeException("Crash Test"))验证清理逻辑有效性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:45:52