2015-08-11 4 views
5

Я нашел утечку памяти в Android 5.x Camera2 API, который также reported. Проблема в том, что вы используете устройство Android Lollipop, которое имеет API Camera2, реализованный в режиме LEGACY. На таких устройствах, вызывающий context.getSystemService(Context.CAMERA_SERVICE), вызывает context, чтобы он не собирался мусором.Как избежать утечки памяти в контексте.getSystemService (Context.CAMERA_SERVICE)?

Если это context - это ваша деятельность, которая запускается несколько раз, вы можете в конечном итоге повесить ссылки на десятки экземпляров вашей деятельности, которые никогда не собираются с мусором.

Проблема, как представляется, происходит только на Lollipop устройств, которые имеют Camera2 API реализованы в LEGACY режиме (например, HTC One M8, Samsung Galaxy S4), в то время как это не происходит на Samsung Galaxy S6, который реализует Camera2 API в режиме FULL.

Чтобы продемонстрировать проблему, я создал small demo app. Приложение содержит два действия: сначала содержит кнопку, которая вызывает второе действие. Второе действие получает CameraManager и запрашивает уровень поддержки Camera2 API для первой обратной камеры и возвращает результат для первой активности. Если запустить приложение на устройстве, которое реализует Camera2 API в режиме LEGACY, после нажатия на кнопку 98 раз, в результате чего GC и затем сбрасывая HPROF вы увидите ровно 98 живых экземпляров из Main2Activity, как этот http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png

Если вы делаете то же самое на устройстве, которое реализует Camera2 API в режиме FULL, вы увидите 0 текущих экземпляров Main2Activity, вот так http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png

Есть ли способ обхода этой утечки?

Можно спросить, почему я это делаю? В нашей компании мы разрабатываем barcode and OCR scanning solutions, а также знаменитый PhotoMath app. Таким образом, у нас есть активность сканирования, которая контролирует процесс камеры и сканирования. При запуске, активность проверяет, поддерживает ли устройство Camera2 API в или LIMITED, и пытается использовать его для повышения производительности, тогда как если Camera2 API находится в режиме LEGACY, то мы предпочитаем использовать управление камерой с использованием старого API-интерфейса камеры, как мы это делаем до-Lollipop устройств.

Из-за упомянутой утечки памяти, когда клиент, который интегрировал наш SDK в свое приложение, запускает операцию сканирования, выполняет сканирование и получает результат, один экземпляр активности сканирования будет просачиваться из-за ошибки. Если клиент сканирует много, это может съесть более 20 МБ памяти - серьезная проблема!

Так что если кто-то знает, как сделать обходной путь для этой проблемы, я буду бесконечно благодарен!

ответ

5

Есть ли способ обхода этой утечки?

Вы можете позвонить по телефону getSystemService() по телефону Application. Таким образом, вместо того, чтобы:

getSystemService(CAMERA_SERVICE) 

вы будете использовать:

getApplicationContext().getSystemService(CAMERA_SERVICE) 

Если ваша оценка верна, то это вызовет те дополнительные ссылки, чтобы быть к существующему Application одноплодной, который всегда вокруг в вашем обработать. Это эффективно «предварительно утечка», и вы не можете просачиваться дальше, имея больше ссылок на него.

+0

Я собирался опубликовать тот же ответ :) –

+0

Отличная идея! Работает как шарм :-) – DoDo

1

Это ошибка Android, которая была исправлена ​​в L MR1.

В основном, CameraManager сохранил ссылку на контекст, в котором он был создан, а затем подключен к службе камеры. Это соединение сохраняло экземпляр диспетчера камеры на неопределенное время, и поэтому также сохраняло Контекст на неопределенное время.

Это было исправлено в L MR1, чтобы правильно разрешить объекты CameraManager восстанавливаться, когда больше не ссылаются.

Смежные вопросы