Когда объект TextureView "Потребительская сторона" закрыт?
Один из официальных образцов Google для Camera2 API имеет та же самая проблема BufferQueue has been abandoned
, как показано в:
В частности, пример приложения вызывает метод closeCamera()
из onPause()
фрагмента, где closeCamera()
вызывает close()
на CameraCaptureSession
, затем close()
на CameraDevice
, затем close()
на ImageReader
(используется для фактической съемки). После close()
on CameraDevice
, когда в LogCat появляется несколько вхождений вышеупомянутого сообщения BufferQueue has been abandoned
, хотя я получаю сообщение только на некоторых устройствах Android 5.1 (Nexus 4 и Nexus 7 2013), а не на других (Nexus 5 и Nexus 6).
Комментарий fadden:
Если пользовательская сторона закрыта перед вводом onPause(), сообщения ожидаются.
Когда TextureView
"сторона потребителя" будет закрыта, и почему тогда?
Код примера Google не проактивно ничего не делает, чтобы закрыть TextureView
, который я вижу. И, поскольку TextureView
все еще может быть видимым при паузе, я ожидал, что "потребительская сторона" не будет затронута во время onPause()
, но, возможно, позже в onStop()
.
Хотя я понимаю, что это сообщение (несмотря на ошибку) является доброкачественным, я пытаюсь понять, как избавиться от него, если не по какой-либо другой причине, чем для того, чтобы не дать мне снова и снова спрашивать, почему мой код регистрирует эту ошибку. Я надеюсь, что, понимая больше об этой "стороне потребителя", я могу понять, как лучше убирать вещи, когда пользователь выходит из действия или фрагмента, использующего Camera2, и избегает этой ошибки.
Ответы
Ответ 1
Ожидаете ли вы вызывать метод обратного вызова камеры с закрытым состоянием, прежде чем выйти из режима onPause?
Пока этот обратный вызов не срабатывает, камера все еще может выполнять незавершенную работу, а определение close() - завершить все ожидающие запросы захвата до выключения устройства. Это можно ускорить, вызвав abortCapture() перед вызовом функции close().
Некоторые устройства (например, N5 и N6) в настоящее время блокируют вызов close(), чтобы при возврате все ожидающие работы выполнялись, но это детализация реализации, которые, как я думаю, наша выборка неосторожно полагается на сегодняшний день.
Однако мы обычно хотим, чтобы приложения вызывали close() и сразу же оставили onPause(), чтобы избежать зависания потока пользовательского интерфейса при ожидании закрытия аппаратного обеспечения камеры. Но сегодня это еще не реальность.
Другими словами, close() предполагается асинхронным и не на всех устройствах. Но мы хотели бы, чтобы вы могли запускать и забывать об этом, поэтому эти сообщения об ошибках должны быть адресованы на стороне устройства камеры (не спам журнала, когда цель повторного запроса уходит в середине операции).
Другая причина, почему вызов close() и exit onPause() не рекомендуется сегодня, заключается в том, что это предотвратит открытие другими приложениями
камера в своих вызовах onResume(), что вызовет ложные ошибки при переключении между приложениями камеры.
Итак, суммируем:
Пока: Подождите CameraDevice.StateCallback # onClosed для вызова перед выходом onPause() после вызова CameraDevice # close().
В какой-то будущий момент: будет безопасно просто вызвать close() и выйти onPause; структура будет правильно разрешать подключению следующего приложения, а не спаму вашего журнала. Извините, что сегодня это не состояние!
Ответ 2
Что касается фактического вопроса - "когда" TextureView "потребительская сторона" закрыта ", я не знаю точное время, но это, безусловно, после возвращения onPause.
Грубо, TextureView содержит поверхность GL, и как только пользовательский интерфейс для активности больше не виден, эти ресурсы срываются. Как только это произойдет, SurfaceTexture, выданный TextureView, уже недействителен, и все существующие пользователи этой SurfaceTexture (или Surfaces, сделанные из него) начнут получать эти ошибки. Метод TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed должен быть вызван TextureView прямо перед этим.
Итак, в качестве альтернативы вы можете вернуть false из onSurfaceTextureDestroyed, чтобы избежать его освобождения во время разрыва интерфейса, а вместо этого ждать, когда onClosed будет запущен, а затем в onClosed выпустить TextureView SurfaceTexture самостоятельно. Тем не менее, я недостаточно хорошо знаком с интерфейсом UI/View, чтобы точно знать, что это сработает, и поскольку некоторые из лежащих в основе нативных поверхностей выпущены в любом случае, вы все равно можете увидеть заброшенные ошибки с этим подходом.
Если вам интересно, верхние уровни соответствующего кода находятся в TextureView, особенно destroySurface, хотя вам нужно будет понять всю систему Android UI, чтобы разобраться, когда именно вызывается метод destroySurface и каковы его эффекты.