如何在context.getSystemService(Context.CAMERA_SERVICE)中避免内存泄漏?

时间:2015-08-11 13:44:37

标签: android memory-leaks garbage-collection android-camera

我在Android 5.x Camera2 API中发现内存泄漏,我也reported。问题是当您使用具有在LEGACY模式下实施的Camera2 API的Android Lollipop设备时。在此类设备上,调用context.getSystemService(Context.CAMERA_SERVICE)会导致context被保留,因此无法进行垃圾回收。

如果此context是您多次启动的活动,则最终可能会挂起对您的活动的几十个实例的引用,这些实例从不被垃圾回收。

这个问题似乎只发生在以LEGACY模式实现Camera2 API的Lollipop设备上(例如HTC One M8,三星Galaxy S4),而在三星Galaxy S6上却没有发生,它实现了{2}中的Camera2 API {1}}模式。

为了证明这个问题,我创建了一个small demo app。该应用程序包含两个活动:首先包含一个调用第二个活动的按钮。第二个活动获取FULL并查询第一个后向摄像头的Camera2 API支持级别,并将结果返回给第一个活动。如果您在CameraManager模式下实施Camera2 API的设备上运行应用程序,在点击按钮98次,导致GC然后转储HPROF后,您将看到LEGACY的98个实时实例,如此{{ 3}}

如果您在Main2Activity模式下实施Camera2 API的设备上执行相同操作,您将看到FULL的0个实时实例,如此http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png

有没有办法解决这个漏洞?

有人可能会问为什么我这样做?在我们公司,我们正在开发http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png以及着名的barcode and OCR scanning solutions。因此,我们有扫描活动来控制相机和扫描过程。在启动时,活动会检查设备是否支持Main2ActivityFULL模式下的Camera2 API并尝试使用它以获得更好的性能,而如果Camera2 API处于LIMITED模式,那么我们更喜欢使用旧相机API使用相机管理,就像我们在Lollipop前设备上所做的那样。

由于提到的内存泄漏,每当将SDK集成到其应用程序中的客户端启动扫描活动,执行扫描并获得结果时,由于该错误,一个扫描活动实例将被泄露。如果客户端扫描很多,这可能会占用超过20 MB的内存 - 这是一个严重的问题!

因此,如果有人知道如何为此问题制定解决方法,我将永远感激不尽!

2 个答案:

答案 0 :(得分:6)

  

有没有办法解决这个漏洞?

您可以在getSystemService()单身人士上致电Application。所以,而不是:

getSystemService(CAMERA_SERVICE)
你会用:

getApplicationContext().getSystemService(CAMERA_SERVICE)

如果您的评估是正确的,那么这将导致这些额外的引用属于现有的Application单例,这在您的过程中始终存在。它是有效的"预先泄露的",你不能通过更多的参考来泄漏它。

答案 1 :(得分:1)

这是在L MR1中修复的Android错误。

基本上,CameraManager保留了对其创建的上下文的引用,然后连接到相机服务。此连接使摄像机管理器实例无限期地保持活动状态,因此也使Context保持无限期。

这已在L MR1中修复,以便在不再引用时正确地允许回收CameraManager对象。