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

Android多Activity间onData方法复用异常及ServiceConnection泄漏问题

解决EMDK红外扫描跨Activity回调异常与ServiceConnection泄漏问题

看起来你遇到的两个问题本质上是同一个原因:旧Activity的EMDK资源没有彻底释放,导致服务连接和回调监听器仍然绑定在已销毁的Activity实例上。我来帮你拆解问题并给出具体的修复方案:

问题根源分析

  1. 新Activity调用旧Activity的onData:
    旧Activity虽然通过finish()销毁了,但你在onPause里的资源释放不彻底——BarcodeManager可能还持有旧Activity的ConnectionListener引用,当扫描触发时,EMDK服务仍然会把回调发送给这个已失效的实例。

  2. ServiceConnection泄漏错误:
    EMDK的服务连接(EMDKServiceConnection)是绑定在旧Activity上的,如果Activity销毁时没有正确解绑并释放EMDKManager,系统会检测到这个连接被已销毁的Activity持有,从而抛出泄漏警告。

修复方案:完善资源释放逻辑

你需要在Activity的**onDestroy方法**中做彻底的资源清理(而不是只在onPause里处理),因为onPause只是Activity失去焦点时的回调,不一定会触发销毁;而onDestroy是Activity生命周期的最后一步,在这里释放资源能确保所有绑定都被清理。

修改后的代码示例

首先补充onDestroy方法,同时调整onPause里的逻辑(避免重复释放或释放不彻底):

// 先完善onDestroy方法,做彻底的资源清理
@Override
protected void onDestroy() {
    super.onDestroy();
    // 1. 停止并销毁扫描器
    if (scanner != null) {
        try {
            // 先取消当前的扫描读取
            scanner.cancelRead();
            // 销毁扫描器实例
            scanner.destroy();
        } catch (ScannerException e) {
            e.printStackTrace();
        }
        scanner = null;
    }

    // 2. 移除BarcodeManager的监听器并置空
    if (barcodeManager != null) {
        barcodeManager.removeConnectionListener(this);
        barcodeManager = null;
    }

    // 3. 释放EMDKManager的BARCODE特性并置空
    if (emdkManager != null) {
        emdkManager.release(EMDKManager.FEATURE_TYPE.BARCODE);
        emdkManager = null;
    }
}

// 调整onPause方法,只处理暂停时的必要操作(比如停止扫描)
@Override
protected void onPause() {
    super.onPause();
    // 暂停时停止扫描即可,不要在这里释放EMDKManager
    if (scanner != null) {
        try {
            scanner.cancelRead();
        } catch (ScannerException e) {
            e.printStackTrace();
        }
    }
    deInitScanner();
}

// 保留原有的onResume逻辑,确保新Activity初始化时独立绑定EMDK
@Override
protected void onResume() {
    super.onResume();
    if (emdkManager != null) {
        barcodeManager = (BarcodeManager) emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE);
        if (barcodeManager != null) {
            barcodeManager.addConnectionListener(this);
        }
        enumerateScannerDevices();
        spinnerScannerDevices.setSelection(scannerIndex);
        try {
            initScanner();
        } catch (ScannerException e) {
            e.printStackTrace();
        }
        scanner.triggerType = Scanner.TriggerType.HARD;
    }
}

关键注意事项

  • 释放顺序不能乱:必须先处理扫描器(停止→销毁),再移除BarcodeManager监听器,最后释放EMDKManager,这样能确保所有引用链被彻底切断。
  • 每个Activity独立管理EMDK资源:两个Activity的EMDK实例不要共享,各自在onResume初始化,onDestroy释放,保证生命周期完全独立。
  • 避免在onPause中释放核心资源:如果只是切换到后台(比如按Home键),onPause后Activity还会存在,此时释放EMDKManager会导致再次进入时需要重新绑定,反而容易出问题。

这样修改后,旧Activity销毁时会彻底清理所有EMDK相关的绑定和资源,新Activity的onData回调就不会再触发旧实例的方法,ServiceConnection泄漏的问题也会解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:43:15