ProcessCameraProvider


class ProcessCameraProvider : CameraProvider


A singleton which can be used to bind the lifecycle of cameras to any LifecycleOwner within an application's process.

Only a single process camera provider can exist within a process, and it can be retrieved with getInstance.

Heavyweight resources, such as open and running camera devices, will be scoped to the lifecycle provided to bindToLifecycle. Other lightweight resources, such as static camera characteristics, may be retrieved and cached upon first retrieval of this provider with getInstance, and will persist for the lifetime of the process.

This is the standard provider for applications to use.

Summary

Nested types

Public companion functions

Unit

Perform one-time configuration of the ProcessCameraProvider singleton with the given CameraXConfig.

ListenableFuture<ProcessCameraProvider>
getInstance(context: Context)

Retrieves the ProcessCameraProvider associated with the current process.

Public functions

open ConcurrentCamera

Binds list of SingleCameraConfigs to LifecycleOwner.

open Camera
@MainThread
bindToLifecycle(
    lifecycleOwner: LifecycleOwner,
    cameraSelector: CameraSelector,
    useCaseGroup: UseCaseGroup
)

Binds a UseCaseGroup to a LifecycleOwner.

open Camera
@MainThread
bindToLifecycle(
    lifecycleOwner: LifecycleOwner,
    cameraSelector: CameraSelector,
    vararg useCases: UseCase?
)

Binds the collection of UseCase to a LifecycleOwner.

open CameraInfo
getCameraInfo(cameraSelector: CameraSelector)

Returns the CameraInfo instance of the camera resulted from the specified CameraSelector.

open Boolean
hasCamera(cameraSelector: CameraSelector)

Checks whether this provider supports at least one camera that meets the requirements from a CameraSelector.

open Boolean
isBound(useCase: UseCase)

Returns true if the UseCase is bound to a lifecycle.

ListenableFuture<Void>
open Unit
@MainThread
unbind(vararg useCases: UseCase?)

Unbinds all specified use cases from the lifecycle provider.

open Unit

Unbinds all use cases from the lifecycle provider and removes them from CameraX.

Public properties

open List<CameraInfo>

The CameraInfo instances of the available cameras.

final List<List<CameraInfo>>

Returns list of CameraInfo instances of the available concurrent cameras.

final Boolean

Returns whether there is a ConcurrentCamera bound.

Public companion functions

configureInstance

Added in 1.4.0
@ExperimentalCameraProviderConfiguration
fun configureInstance(cameraXConfig: CameraXConfig): Unit

Perform one-time configuration of the ProcessCameraProvider singleton with the given CameraXConfig.

This method allows configuration of the camera provider via CameraXConfig. All initialization tasks, such as communicating with the camera service, will be executed on the java.util.concurrent.Executor set by CameraXConfig.Builder.setCameraExecutor, or by an internally defined executor if none is provided.

This method is not required for every application. If the method is not called and CameraXConfig.Provider is not implemented in Application, default configuration will be used.

Once this method is called, the instance configured by the given CameraXConfig can be retrieved with getInstance. CameraXConfig.Provider implemented in Application will be ignored.

Configuration can only occur once. Once the ProcessCameraProvider has been configured with configureInstance() or getInstance, this method will throw an IllegalStateException. Because configuration can only occur once, usage of this method from library code is not recommended as the application owner should ultimately be in control of singleton configuration.

Parameters
cameraXConfig: CameraXConfig

The configuration options for the singleton process camera provider instance.

Throws
kotlin.IllegalStateException

If the camera provider has already been configured by a previous call to configureInstance() or getInstance.

getInstance

Added in 1.4.0
fun getInstance(context: Context): ListenableFuture<ProcessCameraProvider>

Retrieves the ProcessCameraProvider associated with the current process.

The instance returned here can be used to bind use cases to any LifecycleOwner with bindToLifecycle.

The instance's configuration may be customized by subclassing the application's Application class and implementing CameraXConfig.Provider. For example, the sample implements CameraXConfig.Provider.getCameraXConfig and initializes this process camera provider with a Camera2 implementation from androidx.camera.camera2, and with a custom executor.

import androidx.camera.camera2.Camera2Config
import androidx.camera.core.CameraXConfig

@Override
fun getCameraXConfig(): CameraXConfig {
    return CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
        .setCameraExecutor(executor)
        .setSchedulerHandler(scheduleHandler)
        .build()
}

If it isn't possible to subclass the Application class, such as in library code, then the singleton can be configured via configureInstance before the first invocation of getInstance(context), the sample implements a customized camera provider that configures the instance before getting it.

import androidx.camera.camera2.Camera2Config
import androidx.camera.core.CameraProvider
import androidx.camera.core.CameraXConfig
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.lifecycle.ProcessCameraProvider.Companion.configureInstance

fun getInstance(context: Context): ListenableFuture<ProcessCameraProvider> {
    synchronized(CameraProvider::class.java) {
        if (!configured) {
            configured = true
            configureInstance(
                CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
                    .setCameraExecutor(executor)
                    .setSchedulerHandler(scheduleHandler)
                    .build()
            )
        }
    }
    return ProcessCameraProvider.getInstance(context)
}

If no CameraXConfig.Provider is implemented by Application, or if the singleton has not been configured via configureInstance a default configuration will be used.

Parameters
context: Context

The application context.

Returns
ListenableFuture<ProcessCameraProvider>

A future which will contain the ProcessCameraProvider. Cancellation of this future is a no-op. This future may fail with an InitializationException and associated cause that can be retrieved by Throwable.cause. The cause will be a androidx.camera.core.CameraUnavailableException if it fails to access any camera during initialization.

Throws
kotlin.IllegalStateException

if CameraX fails to initialize via a default provider or a CameraXConfig.Provider.

Public functions

bindToLifecycle

Added in 1.3.0
@MainThread
open fun bindToLifecycle(
    singleCameraConfigs: List<ConcurrentCamera.SingleCameraConfig?>
): ConcurrentCamera

Binds list of SingleCameraConfigs to LifecycleOwner.

The concurrent camera is only supporting two cameras currently. If the input list of SingleCameraConfigs have less or more than two SingleCameraConfigs, IllegalArgumentException will be thrown. If cameras are already used by other UseCases, UnsupportedOperationException will be thrown.

A logical camera is a grouping of two or more of those physical cameras. See Multi-camera API

If we want to open concurrent logical cameras, which are one front camera and one back camera, the device needs to support PackageManager.FEATURE_CAMERA_CONCURRENT. To set up concurrent logical camera, call availableConcurrentCameraInfos to get the list of available combinations of concurrent cameras. Each sub-list contains the CameraInfos for a combination of cameras that can be operated concurrently. Each logical camera can have its own UseCases and LifecycleOwner. See {@docRoot}training/camerax/architecture#lifecycles

If the concurrent logical cameras are binding the same preview and video capture use cases, the concurrent cameras video recording will be supported. The concurrent camera preview stream will be shared with video capture and record the concurrent cameras streams as a composited stream. The CompositionSettings can be used to configure the position of each camera stream and different layouts can be built. See CompositionSettings for more details.

If we want to open concurrent physical cameras, which are two front cameras or two back cameras, the device needs to support physical cameras and the capability could be checked via CameraInfo.isLogicalMultiCameraSupported. Each physical cameras can have its own UseCases but needs to have the same LifecycleOwner, otherwise IllegalArgumentException will be thrown.

If we want to open one physical camera, for example ultra wide, we just need to set physical camera id in CameraSelector and bind to lifecycle. All CameraX features will work normally when only a single physical camera is used.

If we want to open multiple physical cameras, we need to have multiple CameraSelectors, each in one SingleCameraConfig and set physical camera id, then bind to lifecycle with the SingleCameraConfigs. Internally each physical camera id will be set on UseCase, for example, Preview and call android.hardware.camera2.params.OutputConfiguration.setPhysicalCameraId.

Currently only two physical cameras for the same logical camera id are allowed and the device needs to support physical cameras by checking CameraInfo.isLogicalMultiCameraSupported. In addition, there is no guarantee or API to query whether the device supports multiple physical camera opening or not. Internally the library checks android.hardware.camera2.CameraDevice.isSessionConfigurationSupported, if the device does not support the multiple physical camera configuration, IllegalArgumentException will be thrown.

Parameters
singleCameraConfigs: List<ConcurrentCamera.SingleCameraConfig?>

Input list of SingleCameraConfigs.

Returns
ConcurrentCamera

Output ConcurrentCamera instance.

Throws
kotlin.IllegalArgumentException

If less or more than two camera configs are provided.

kotlin.UnsupportedOperationException

If device is not supporting concurrent camera or cameras are already used by other UseCases.

bindToLifecycle

Added in 1.0.0
@MainThread
open fun bindToLifecycle(
    lifecycleOwner: LifecycleOwner,
    cameraSelector: CameraSelector,
    useCaseGroup: UseCaseGroup
): Camera

Binds a UseCaseGroup to a LifecycleOwner.

Similar to bindToLifecycle, with the addition that the bound collection of UseCase share parameters defined by UseCaseGroup such as consistent camera sensor rect across all UseCases.

If one UseCase is in multiple UseCaseGroups, it will be linked to the UseCaseGroup in the latest bindToLifecycle call.

Throws
kotlin.UnsupportedOperationException

If the camera is configured in concurrent mode.

bindToLifecycle

Added in 1.0.0
@MainThread
open fun bindToLifecycle(
    lifecycleOwner: LifecycleOwner,
    cameraSelector: CameraSelector,
    vararg useCases: UseCase?
): Camera

Binds the collection of UseCase to a LifecycleOwner.

The state of the lifecycle will determine when the cameras are open, started, stopped and closed. When started, the use cases receive camera data.

Binding to a lifecycleOwner in state currently in Lifecycle.State.STARTED or greater will also initialize and start data capture. If the camera was already running this may cause a new initialization to occur temporarily stopping data from the camera before restarting it.

Multiple use cases can be bound via adding them all to a single bindToLifecycle call, or by using multiple bindToLifecycle calls. Using a single call that includes all the use cases helps to set up a camera session correctly for all uses cases, such as by allowing determination of resolutions depending on all the use cases bound being bound. If the use cases are bound separately, it will find the supported resolution with the priority depending on the binding sequence. If the use cases are bound with a single call, it will find the supported resolution with the priority in sequence of ImageCapture, Preview and then ImageAnalysis. The resolutions that can be supported depends on the camera device hardware level that there are some default guaranteed resolutions listed in android.hardware.camera2.CameraDevice.createCaptureSession.

Currently up to 3 use cases may be bound to a Lifecycle at any time. Exceeding capability of target camera device will throw an IllegalArgumentException.

A UseCase should only be bound to a single lifecycle and camera selector a time. Attempting to bind a use case to a lifecycle when it is already bound to another lifecycle is an error, and the use case binding will not change. Attempting to bind the same use case to multiple camera selectors is also an error and will not change the binding.

If different use cases are bound to different camera selectors that resolve to distinct cameras, but the same lifecycle, only one of the cameras will operate at a time. The non-operating camera will not become active until it is the only camera with use cases bound.

The Camera returned is determined by the given camera selector, plus other internal requirements, possibly from use case configurations. The camera returned from bindToLifecycle may differ from the camera determined solely by a camera selector. If the camera selector can't resolve a valid camera under the requirements, an IllegalArgumentException will be thrown.

Only UseCase bound to latest active Lifecycle can keep alive. UseCase bound to other Lifecycle will be stopped.

Parameters
lifecycleOwner: LifecycleOwner

The lifecycleOwner which controls the lifecycle transitions of the use cases.

cameraSelector: CameraSelector

The camera selector which determines the camera to use for set of use cases.

vararg useCases: UseCase?

The use cases to bind to a lifecycle.

Returns
Camera

The Camera instance which is determined by the camera selector and internal requirements.

Throws
kotlin.IllegalStateException

If the use case has already been bound to another lifecycle or method is not called on main thread.

kotlin.IllegalArgumentException

If the provided camera selector is unable to resolve a camera to be used for the given use cases.

kotlin.UnsupportedOperationException

If the camera is configured in concurrent mode.

getCameraInfo

open fun getCameraInfo(cameraSelector: CameraSelector): CameraInfo

Returns the CameraInfo instance of the camera resulted from the specified CameraSelector.

The returned CameraInfo corresponds to the camera that will be bound when calling bindToLifecycle with the specified CameraSelector.

Parameters
cameraSelector: CameraSelector

the CameraSelector to use for selecting the camera to receive information about.

Returns
CameraInfo

the corresponding CameraInfo.

Throws
kotlin.IllegalArgumentException

if the given CameraSelector can't result in a valid camera to provide the CameraInfo.

hasCamera

Added in 1.0.0
open fun hasCamera(cameraSelector: CameraSelector): Boolean

Checks whether this provider supports at least one camera that meets the requirements from a CameraSelector.

If this method returns true, then the camera selector can be used to bind use cases and retrieve a Camera instance.

Parameters
cameraSelector: CameraSelector

the CameraSelector that filters available cameras.

Returns
Boolean

true if the device has at least one available camera, otherwise false.

Throws
androidx.camera.core.CameraInfoUnavailableException

if unable to access cameras, perhaps due to insufficient permissions.

isBound

Added in 1.0.0
open fun isBound(useCase: UseCase): Boolean

Returns true if the UseCase is bound to a lifecycle. Otherwise returns false.

After binding a use case, use cases remain bound until the lifecycle reaches a Lifecycle.State.DESTROYED state or if is unbound by calls to unbind or unbindAll.

shutdownAsync

Added in 1.4.0
@VisibleForTesting
fun shutdownAsync(): ListenableFuture<Void>

unbind

Added in 1.0.0
@MainThread
open fun unbind(vararg useCases: UseCase?): Unit

Unbinds all specified use cases from the lifecycle provider.

This will initiate a close of every open camera which has zero UseCase associated with it at the end of this call.

If a use case in the argument list is not bound, then it is simply ignored.

After unbinding a UseCase, the UseCase can be bound to another Lifecycle however listeners and settings should be reset by the application.

Parameters
vararg useCases: UseCase?

The collection of use cases to remove.

Throws
kotlin.IllegalStateException

If not called on main thread.

kotlin.UnsupportedOperationException

If called in concurrent mode.

unbindAll

Added in 1.0.0
@MainThread
open fun unbindAll(): Unit

Unbinds all use cases from the lifecycle provider and removes them from CameraX.

This will initiate a close of every currently open camera.

Throws
kotlin.IllegalStateException

If not called on main thread.

Public properties

availableCameraInfos

Added in 1.1.0
open val availableCameraInfosList<CameraInfo>

The CameraInfo instances of the available cameras.

While iterating through all the available CameraInfo, if one of them meets some predefined requirements, a CameraSelector that uniquely identifies its camera can be retrieved using CameraInfo.getCameraSelector, which can then be used to bind use cases to that camera.

availableConcurrentCameraInfos

Added in 1.3.0
final val availableConcurrentCameraInfosList<List<CameraInfo>>

Returns list of CameraInfo instances of the available concurrent cameras.

The available concurrent cameras include all combinations of cameras which could operate concurrently on the device. Each list maps to one combination of these camera's CameraInfo.

For example, to select a front camera and a back camera and bind to LifecycleOwner with preview UseCase, this function could be used with bindToLifecycle.

import androidx.camera.core.CameraSelector
import androidx.camera.core.ConcurrentCamera.SingleCameraConfig
import androidx.camera.core.Preview
import androidx.camera.core.UseCaseGroup
import androidx.camera.view.PreviewView

var cameraSelectorPrimary: CameraSelector? = null
var cameraSelectorSecondary: CameraSelector? = null
for (cameraInfoList in cameraProvider.availableConcurrentCameraInfos) {
    for (cameraInfo in cameraInfoList) {
        if (cameraInfo.lensFacing == CameraSelector.LENS_FACING_FRONT) {
            cameraSelectorPrimary = cameraInfo.getCameraSelector()
        } else if (cameraInfo.lensFacing == CameraSelector.LENS_FACING_BACK) {
            cameraSelectorSecondary = cameraInfo.getCameraSelector()
        }
    }
}
if (cameraSelectorPrimary == null || cameraSelectorSecondary == null) {
    return
}
val previewFront = Preview.Builder().build()
previewFront.setSurfaceProvider(frontPreviewView.getSurfaceProvider())
val primary =
    SingleCameraConfig(
        cameraSelectorPrimary,
        UseCaseGroup.Builder().addUseCase(previewFront).build(),
        lifecycleOwner
    )
val previewBack = Preview.Builder().build()
previewBack.setSurfaceProvider(backPreviewView.getSurfaceProvider())
val secondary =
    SingleCameraConfig(
        cameraSelectorSecondary,
        UseCaseGroup.Builder().addUseCase(previewBack).build(),
        lifecycleOwner
    )
cameraProvider.bindToLifecycle(listOf(primary, secondary))
Returns
List<List<CameraInfo>>

List of combinations of CameraInfo.

isConcurrentCameraModeOn

Added in 1.3.0
final val isConcurrentCameraModeOnBoolean

Returns whether there is a ConcurrentCamera bound.

Returns
Boolean

true if there is a ConcurrentCamera bound, otherwise false.