KeyguardManager内存泄漏

时间:2020-03-01 16:20:09

标签: android leakcanary

活动完成后,我正在使用此代码来DismissKeyguard,LeakCanary在消息下方显示。如何防止这些泄漏。

keyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);

if(Build.VERSION.SDK_INT >= 27) {

    setShowWhenLocked(true);
    setTurnScreenOn(true);

    if (keyguardManager != null) {
        keyguardManager.requestDismissKeyguard(this, null);
    }
}

LeakCanary显示

GC Root: Global variable in native code
    │
    ├─ android.app.KeyguardManager$1 instance
    │    Leaking: UNKNOWN
    │    Anonymous subclass of com.android.internal.policy.IKeyguardDismissCallback$Stub
    │    ↓ KeyguardManager$1.val$activity
    │                        ~~~~~~~~~~~~
    ╰→ com.example.myapplication.MainActivity instance
    ​     Leaking: YES (ObjectWatcher was watching this because com.example.myapplication.MainActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
    ​     

2 个答案:

答案 0 :(得分:4)

泄漏跟踪指示本机代码中存在一个全局变量,该变量保留对实现KeyguardManager$1的{​​{1}}实例的引用,而com.android.internal.policy.IKeyguardDismissCallback$Stub本身持有对活动的引用。

可在以下位置找到KeyguardManager#requestDismissKeyguard的实现源:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/KeyguardManager.java#574

KeyguardManager$1

这是对ActivityTaskManager服务进程的进程间调用。设置为在ActivityTaskManager服务进程回调时接收结果的存根包含对该活动的引用。不幸的是,本机存根在内存中的保存时间往往比预期的长,因为它们依赖于在其他进程中运行的GC。

这显然是Android框架中的错误。您应该向Android框架提交错误,并提供一个可重现该错误的示例应用。

答案 1 :(得分:1)

为了尽量减少泄漏,您可以在执行isKeyguardLocked()之前检查requestDismissKeyguard(),只有在确实需要时才解锁:

if ( (keyguardManager != null) && keyguardManager.isKeyguardLocked()) {
    keyguardManager.requestDismissKeyguard(this, null);
}