Select camera on android

CameraX: Learn how to use CameraController

CameraX currently provides CameraView , a View that displays a preview of the camera, while also providing methods to take pictures, control the camera, and query camera information. CameraView clearly takes on more responsibilities than a View should, as it participates in the View hierarchy and displays content, while also owning camera resources that exist outside the scope and lifecycle of the View hierarchy.

CameraView violates the separation of concerns principle, making it harder to guarantee its robustness in all corner cases. As a result, it will be marked as deprecated and removed before CameraX’s view artifact reaches Beta. It has been split up into two parts that you should use instead: PreviewView which handles its view-related tasks, and CameraController which handles the camera operations.

PreviewView has been available in CameraX’s view artifact for a while. CameraController , however, was introduced recently in version alpha19. It’s a high-level, all-in-one API that provides a way to easily access and manipulate core camera features, including displaying a camera preview, taking a picture, and analyzing camera frames. It does so while matching the output of its use cases to the viewfinder’s preview, thus providing a “What You See Is What You Get” (WYSIWYG) experience, a highly requested feature by developers that makes CameraX’s usage very intuitive. It also takes care of initializing the camera and adapting its output to device rotation.

To offload the burden of starting, stopping, and closing the camera, CameraX also introduced LifecycleCameraController , which offers all the convenience of CameraController with the added benefit of binding the camera’s lifecycle to that of a LifecycleOwner , typically the lifecycle of a Fragment or Activity . This allows the lifecycle’s state to control when the camera is opened, stopped, and closed.

Using PreviewView with CameraController is fairly simple, and can be done as follows:

The following sections list the mappings from CameraView to CameraController . You can use them to migrate from CameraView to PreviewView and CameraController .

Camera Initialization

Unlike CameraView , CameraController provides a ListenableFuture to monitor its initialization. It’s an asynchronous operation during which CameraController initializes CameraX and binds its use cases. The benefit of using this ListenableFuture is twofold:

  • Once it successfully completes, you can allow your users to start interacting with the camera, for example by taking pictures and zooming in and out of the viewfinder.
  • In case it fails, you can gracefully handle the error and communicate it to your users.

In case you aren’t familiar with ListenableFuture : it wraps an asynchronous operation and allows you to attach a listener that’s invoked on its completion. In case the operation has already finished, the future returns immediately.

Camera Lifecycle

Similar to CameraView , LifecycleCameraController ties control of the camera to a lifecycle. You must bind a valid LifecycleOwner to the controller for it to be operational.

LifecycleCameraController provides an additional unbind() method which allows you to prematurely close the camera before the lifecycle that it’s bound to comes to an end. This is useful in cases in which the camera isn’t integral to a screen and isn’t needed for its entire lifecycle. Alternatively, you can define your custom LifecycleOwner to control when to close the camera, but unbind() can be more convenient in some cases.

Camera Control

CameraController allows you to observe the camera’s zoom state via a LiveData instance. This state becomes available once the camera is open, and holds both static information, like the maximum and minimum zoom ratios, and dynamic information, like the current zoom ratio. You can verify whether zoom is supported using the maximum zoom ratio as follows:

Читайте также:  Не могу установить голосовой набор для андроид

CameraController additionally provides methods to get and set linear zoom, which can vary between 0 (minimum zoom) and 1 (maximum zoom).

Finally, like CameraView , CameraController allows you to enable or disable pinch-to-zoom. When enabled, CameraController handles pinch gestures on its attached PreviewView to zoom the camera in and out.

— Flash/Torch

CameraController provides similar methods as CameraView to set and query the image capture’s flash mode, but unlike CameraView , it allows observing changes in the camera’s torch state via a LiveData instance, which emits TorchState.OFF and TorchState.ON .

— Focus/Metering

While CameraView automatically acquires focus on any region of the viewfinder that is tapped, CameraController provides more flexibility by allowing you to enable or disable tap-to-focus functionality. When enabled, CameraController handles touch events on its attached PreviewView by focusing the camera on tapped regions.

Camera Selection

CameraController provides you with more control over which camera to use by allowing you to specify a CameraSelector to select the camera it uses. This allows you to rotate between various cameras when toggling cameras, instead of only the default front and back cameras, which was a limitation of CameraView.toggleCamera() . You can still implement this fairly easily, though, using CameraController as follows.

Camera Use Cases

CameraController supports all of CameraX’s use cases: Preview , ImageAnalysis , and ImageCapture , thus making it a more robust camera solution compared to CameraView . It also matches the output of ImageAnalysis and ImageCapture to the preview’s display, thereby providing a WYSIWYG experience.

CameraController ’s default state enables preview, image analysis, and image capture. The Preview use case is always enabled, so you can choose the remaining use cases to enable or disable depending on your camera usage needs.

— Preview

Unlike CameraView which wraps (and thus hides) a PreviewView instance and forwards method calls to it, CameraController is decoupled from PreviewView . This means you have more control over the viewfinder, and can access and manipulate it directly.

— ImageAnalysis

Unlike CameraView , CameraController supports the ImageAnalysis use case. You can set and clear its Analyzer , while also configuring its image-processing pipeline.

— ImageCapture

CameraController provides the same methods as CameraView to take a picture, specify the image save destination, and provide the image capture callbacks.

One thing to note is that CameraController mirrors an image captured with a front-facing camera, unless you disable this in the OutputFileOptions ’s metadata by calling Metadata.setReversedHorizontal(false) .

Conclusion

  • Because CameraView is handling the responsibilities of both a view and a controller in the MVC sense, CameraX is deprecating it and splitting it into PreviewView and the newly introduced CameraController .
  • CameraController handles camera initialization, as well as the creation and configuration of its use cases.
  • CameraController provides a WYSIWYG experience by matching the output of its use cases to PreviewView ’s display.
  • CameraController listens to the device’s motion sensor to correctly rotate the output of its use cases.
  • CameraController adds support for the ImageAnalysis use case, making it a more robust camera solution that provides easy access to all of CameraX’s use cases.
  • CameraController supports all of CameraView ’s features and more, such as enabling and disabling tap-to-focus, getting and setting linear zoom, and observing dynamic camera information like the zoom and torch states.
  • LifecycleCameraController is a CameraController that binds the camera’s lifecycle to that of a LifecycleOwner , typically the lifecycle of the UI.

Источник

Camera Enumeration on Android

Starting in Android P, logical multi-camera and USB camera support have been added. What does this mean for Android developers?

2019–05–22 Update: This blog post has been updated to include guidance about filtering out devices that do not have RGB output capabilities but are listed as a camera device; for example, depth sensors.

Читайте также:  Мобильные сканеры для андроид

Multiple cameras

Multiple cameras in a single device are nothing new but, until now, Android devices have been limited to at most two cameras: front and back. If you wanted to open the first camera, all you had to do was:

But those were simpler times. Today, multiple cameras can mean two or more cameras in the front and/or in the back. That’s a lot of lenses to choose from!

Camera2 API

For compatibility reasons, the above code still works even years after the old Camera API was deprecated. But, as the ecosystem evolved, there was a need for more advanced camera features. So Android introduced Camera2 with Android 5.0 (Lollipop), API level 21 and above. The equivalent code to open the first existing camera using the Camera2 API looks like this:

First is not always best

So far so good. If all we need is an app that opens the first existing camera, this will work on most Android phones. But consider the following scenarios:

  • If a device has no cameras, the app will crash. This may seem unlikely, until we realize that Android runs in many kinds of devices, including Android Things, Android Wear and Android TV, which add up to millions of users.
  • If a device has at least one back-facing camera, it will be mapped to the first camera in the list. But apps running on devices with no back cameras, such as PixelBooks and most other ChromeOS laptops, will open the single, front-facing camera.

What should we do? Check the camera list and camera characteristics:

The variable cameraLensFacing will be one of:

For more information about lens-facing configuration, take a look at the documentation.

The variable cameraCapabilities will tell us about miscellaneous capabilities, including whether this camera is able to produce standard frames as an output (as opposed to, for example, only depth sensor data). We should look for whether CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE is one of the camera’s listed capabilities, which is stored as a flag in cameraCompatible .

Sensible defaults

Depending on the use-case of the application, we may want to open a specific camera lens configuration by default (if it’s available). For example, a selfie app would most likely want to open the front-facing camera, while an augmented reality app should probably start with the back camera. We can wrap this logic into a function, which properly handles the cases mentioned above:

Switching cameras

So far, we have discussed how to select a default camera depending on what the application wants to do. Many camera applications also give users the option to switch between cameras:

To implement this feature it’s tempting to select the next camera from the list provided by CameraManager.getCameraIdList(), but this is not a good idea. The reason is that starting in Android P, we expect to see more devices with multiple cameras facing the same way, or even have external cameras connected via USB. If we want to provide the user with a UI that lets them switch between different facing cameras, the recommendation (as per the documentation) is to choose the first available camera for each possible lens-facing configuration.

Although there is no one-size-fits-all logic for selecting the next camera, the following code works for most use cases:

This may appear complicated, but we need to account for a large set of devices with many different configurations.

Compatibility behavior

For applications still using the deprecated Camera API, the number of cameras advertised by Camera.getNumberOfCameras() depends on OEM implementation. The documentation states:

If there is a logical multi-camera in the system, to maintain app backward compatibility, this method will only expose one camera for every logical camera and underlying physical cameras group. Use camera2 API to see all cameras.

Read the rest of the documentation closely for more details. In general, a similar advice applies: use the Camera.getCameraInfo() API to query all camera orientations, and expose only one camera for each available orientation to users that are switching between cameras.

Читайте также:  Airpods слишком тихие android

Best practices

Android runs on many different devices. You should not assume that your application will always run on a traditional handheld device with one or two cameras. Pick the most appropriate cameras for the application. If you don’t need a specific camera, select the first camera with the desired lens-facing configuration. If there are external cameras connected, it may be reasonable to assume that the user would prefer to see those first.

Источник

Работа с камерой в Android

Работа с камерой на телефоне всегда представляла для меня интерес. Как же это все устроено… И вот мне в руки попал телефон с Android’ом. Я не преминул возможностью попробовать разобраться в этом. Вот что получилось в итоге.

Рассмотрим небольшую программу, которая позволяет делать снимки.

Все операции проводятся с помощью класса Camera.
Необходимо завести переменную

и инициализировать ее

После завершения работы с камерой необходимо сделать

в противном случае камера останется заблокированной и недоступной для других приложений.

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

Обязательным условием при работе с камерой является создание окна предпросмотра (preview). Это окно должно являться объектом класса Surfaceи для отображения на экране подходит SurfaceView.
Объявим

Чтобы задать preview, необходимо вызвать метод setPreviewDisplay, параметром которого является объект класса SurfaceHolder.

Чтобы включить отображение preview, вызываем

Если этого не сделать, то камера не сможет делать снимки.

Собственно для того, чтобы сделать снимок, необходимо вызвать метод

С помощью параметров (кстати, любой из них может быть null) задаются обработчики разных событий:

  • shutter — вызывается в момент получения изображения с матрицы
  • raw — программе передаются для обработки raw данные (если поддерживается аппаратно)
  • postview — программе передаются полностью обработанные данные (если поддерживается аппаратно)
  • jpg — программе передается изображение в виде jpg. Здесь можно организовать запись изображения на карту памяти.

Вызов takePicture можно поместить непосредственно в обработчик onClick кнопки — в этом случае фотографирование произойдет сразу после нажатия на нее, но можно и воспользоваться предварительной автофокусировкой.
В этом случае задается обработчик Camera.AutoFocusCallback, в котором необходимо реализовать метод

Тогда после вызова в обработчике нажатия на кнопку camera.autoFocus(), однократно будет вызван обработчик, в котором мы уже и примем решение об удачной фокусировке и необходимости сделать снимок.

Для работы с SurfaceHolder можно задать SurfaceHolder.Callback
surfaceHolder.addCallback();

В этом случае необходимо реализовать методы

C помощью них приложению будет сообщаться о том, что Surface успешно создано, если оно изменено или то, что оно удалено.

Размер нашего preview можно менять в процессе выполнения программы:

Для приложения камеры удобнее всего сразу задать расположение экрана как
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
В противном случае нам придется, например, в surfaceCreated проверять расположение экрана и поворачивать preview с помощью, например, camera.setDisplayOrientation(0) .
Это не очень удобно, потому что поворот экрана занимает какое-то время. В этот момент происходит вызов onPause и onResume, пересоздается Surface.

Также имеется возможность объявить обработчик Camera.PreviewCallback, с помощью которого путем реализации метода

можно получать и обрабатывать каждый кадр, отображаемый в preview.

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

Чуть не забыл. В манифест необходимо добавить permission

MainScreen.java

main.xml

AndroidManifest.xml

Программа отлаживалась и тестировалась на телефоне LG Optimus One P500.

При написании использовались следующие источники информации:

Источник

Оцените статью