Подтвердить что ты не робот

Камера на Android-примере

Я хочу написать действие, которое:

  • Показывает предварительный просмотр камеры (видоискатель) и имеет кнопку захвата.
  • Когда нажата кнопка "захват", выполняется съемка и возвращается к вызывающей активности (setResult() и finish()).

Есть ли полный пример, который работает на каждом устройстве? Идеальным ответом будет ссылка на простое приложение с открытым исходным кодом, которое делает снимки.


Мои исследования:

Это распространенный сценарий, и на нем есть много вопросов и руководств.

Существуют два основных подхода:

Подход 1 был бы идеальным, но проблема в том, что намерение реализовано по-разному на каждом устройстве. На некоторых устройствах он работает хорошо. Однако на некоторых устройствах вы можете сделать снимок, но он никогда не возвращается в ваше приложение. На некоторых устройствах ничего не происходит, когда вы запускаете намерение. Обычно он также сохраняет изображение на SD-карте и требует наличия SD-карты. Пользовательское взаимодействие также отличается на каждом устройстве.

С подходом 2 проблемы - это стабильность. Я попробовал несколько примеров, но мне удалось остановить работу камеры (до перезапуска) на некоторых устройствах и полностью заморозить другое устройство. На другом устройстве захват работал, но предварительный просмотр остался черным.

Я бы использовал ZXing в качестве примера приложения (я много работаю с ним), но он использует только предварительный просмотр (видоискатель) и не делает никаких снимков. Я также обнаружил, что на некоторых устройствах ZXing автоматически не корректировал баланс белого при изменении условий освещения, в то время как приложение для родной камеры делало это правильно (не уверен, что это можно исправить).


Update:

Некоторое время я напрямую использовал API-интерфейс камеры. Это дает больше контроля (пользовательский интерфейс и т.д.), Но я бы никому не рекомендовал. Я бы работал на 90% устройств, но время от времени новое устройство было выпущено с другой проблемой.

Некоторые из проблем, с которыми я столкнулся:

  • Работа с автофокусом
  • Работа со вспышкой
  • Вспомогательные устройства с фронтальной камерой, задней камерой или обоими
  • Каждое устройство имеет разную комбинацию разрешения экрана, разрешения предварительного просмотра (не всегда соответствует разрешению экрана) и разрешения изображения.

Итак, в общем, я бы не стал рекомендовать этот маршрут вообще, если нет другого пути. Через два года я сбросил пользовательский код и переключился на подход, основанный на Intent. С тех пор у меня было гораздо меньше проблем. Проблемы, которые у меня были с подходом, основанным на намерениях, в прошлом были, вероятно, только моей собственной некомпетентностью.

Если вам действительно нужно пройти этот маршрут, я слышал об этом гораздо проще, если вы поддерживаете только устройства с Android 4.0 +.

4b9b3361

Ответ 1

С подходом 2 проблемы - это стабильность. Я попробовал несколько примеров, но мне удалось остановить работу камеры (до перезапуска) на некоторых устройствах и полностью заморозить другое устройство. На другом устройстве захват работал, но предварительный просмотр остался черным.

Есть либо ошибка в примерах, либо проблема с совместимостью с устройствами.

Ответ 2

Пример, который CommonsWare дал хорошо. Пример работает при использовании as-is, но вот те проблемы, с которыми я столкнулся, когда изменяем его для моего варианта использования:

  • Никогда не делайте второй снимок перед завершением первого снимка, другими словами PictureCallback.onPictureTaken() был вызван. Для этой цели в CommonsWare используется флаг inPreview.
  • Убедитесь, что ваш SurfaceView является полноэкранным. Если вам нужен небольшой предварительный просмотр, вам может потребоваться изменить логику выбора размера предварительного просмотра, в противном случае предварительный просмотр может не вписываться в SurfaceView на некоторых устройствах. Некоторые устройства поддерживают только полноэкранный размер предварительного просмотра, поэтому сохранение его в полноэкранном режиме является самым простым решением.

Чтобы добавить дополнительные компоненты в экран предварительного просмотра, FrameLayout хорошо работает в моем опыте. Я начал с использования LinearLayout, чтобы добавить текст выше предварительного просмотра, но это нарушило правило №2. При использовании FrameLayout для добавления компонентов поверх предварительного просмотра у вас нет проблем с разрешением предварительного просмотра.

Я также разместил незначительную проблему, относящуюся к Camera.open() на GitHub.

Ответ 3

"рекомендуемый способ доступа к камере - открыть камеру в отдельной теме" . В противном случае Camera.open() может занять некоторое время и может испортить поток пользовательского интерфейса.

"Обратные вызовы будут вызваны в поток событий, открытый (int) был вызван из" . Поэтому для достижения наилучшей производительности с помощью обратных вызовов предварительного просмотра камеры (например, для их кодирования в видео с низкой задержкой для живого общения) я рекомендую открыть камеру в новом HandlerThread, как показано здесь.