Когда закрыта «потребительская сторона» TextureView?

Один из официальных образцов Google для API Camera2, страдающих от того же BufferQueue has been abandoned проблемой, как это видно из:

  • Что делать, если BufferQueue был оставлен?
  • Android LogCat показывает BufferQueueProcedure

В частности, пример приложения вызывает метод closeCamera() из onPause() фрагмента, где closeCamera() вызывает close() на CameraCaptureSession , затем close() на CameraCaptureSession , а затем close() на ImageReader (используется для фактического фотосъемки). После close() на CameraDevice , когда в BufferQueue has been abandoned появилось несколько вхождений вышеупомянутого сообщения BufferQueue, хотя я получаю сообщение только на некоторых устройствах Android 5.1 (Nexus 4 и Nexus 7 2013), а не на других (Nexus 5 и Nexus 6).

Комментарий fadden по этому поводу:

Если клиентская сторона закрыта перед вводом onPause (), сообщения ожидаются.

Когда будет TextureView «потребительская сторона» TextureView и почему?

Образец кода Google не проактивно ничего не делает, чтобы закрыть TextureView который я вижу. И поскольку TextureView все еще может быть видимым при паузе, я бы ожидал, что «потребительская сторона» не будет затронута во время onPause() , но, возможно, позже в onStop() .

Хотя я понимаю, что это сообщение (несмотря на то, что это ошибка) является доброкачественным, я пытаюсь понять, как избавиться от него, если не по какой-либо другой причине, чем для того, чтобы не дать мне снова и снова спрашивать, почему мой код регистрирует этот ошибка. Я надеюсь, что, понимая больше об этой «стороне потребителя», я могу понять, как лучше подбирать вещи, когда пользователь выходит из действия или фрагмента, использующего Camera2, и избегает этой ошибки.

Ожидаете ли вы вызов метода обратного вызова onClosed для камеры, прежде чем выйти из onPause?

Пока этот обратный вызов не срабатывает, камера все еще может выполнять отложенную работу, а определение close () – завершить все ожидающие запросы на захват перед выключением устройства. Это можно ускорить, вызвав abortCapture () перед вызовом функции close ().

Некоторые устройства (например, N5 и N6) в настоящий момент блокируют вызов close (), поэтому, когда он возвращается, выполняется все ожидающие работы, но это детализация реализации, которые, как я думаю, наша выборка неосторожно полагается на сегодня.

Однако мы обычно хотим разрешить приложениям называть close () и немедленно оставить onPause (), чтобы избежать зависания потока пользовательского интерфейса при ожидании закрытия аппаратного обеспечения камеры. Но сегодня это еще не реальность.

Другими словами, close () должен быть асинхронным и не на всех устройствах. Но мы хотели бы, чтобы вы могли стрелять и забывать об этом, поэтому эти сообщения об ошибках должны быть адресованы на стороне устройства камеры (а не спам в журнале, когда цель повторного запроса уходит в середине операции).

Другая причина, по которой просто вызов функции close () и выхода из onPause () не рекомендуется сегодня, заключается в том, что она не позволит другим приложениям открывать камеру в своих вызовах onResume (), что может вызвать ложные ошибки при переключении между приложениями камеры.

Итак, чтобы подвести итог:

Пока: Подождите, пока CameraDevice.StateCallback # onClosed будет вызываться перед выходом из onPause () после вызова CameraDevice # close ().

В какой-то следующий момент: будет безопасно просто вызвать close () и выйти onPause; Структура будет правильно разрешать подключению следующего приложения, а не спаму вашего журнала. Извините, сегодня это не состояние!

Что касается фактического вопроса – «когда« Сторона »TextureView« закрыта », я не знаю точное время, но это, безусловно, после возвращения onPause.

Грубо говоря, TextureView содержит поверхность GL, и после того, как пользовательский интерфейс для активности больше не виден, эти ресурсы срываются. Как только это произойдет, SurfaceTexture, выданный TextureView, уже недействителен, и все существующие пользователи этой SurfaceTexture (или Surface from made) начнут получать эти ошибки. Метод TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed должен вызываться TextureView прямо перед этим.

Таким образом, в качестве альтернативы вы можете вернуть false из onSurfaceTextureDestroyed, чтобы избежать его освобождения при разрыве пользовательского интерфейса, а вместо этого ждать, когда onClosed будет запущен, а затем в onClosed выпустить SurfaceTexture TextureView самостоятельно. Тем не менее, я недостаточно хорошо знаком с UI / View стороной вещей, чтобы точно знать, что это сработает, и поскольку некоторые из основных нативных поверхностей выпущены в любом случае, вы все равно можете увидеть заброшенные ошибки с этим подходом.

Если вам интересно, верхние уровни соответствующего кода находятся в TextureView , особенно метод destroySurface, хотя вам нужно будет понять всю систему Android UI, чтобы разобраться, когда именно вызывается метод destroySurface, и Каковы его последствия.