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 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!
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:
cameraLensFacing will be one of:
For more information about lens-facing configuration, take a look at the documentation.
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
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:
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.
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.
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.