一、CameraManager类概述
CameraManager是用于检测、表征和连接到 CameraDevices 的系统服务管理器。
CameraManager 是一个负责查询和建立相机连接的系统服务,它的功能不多,这里列出几个 CameraManager 的关键功能:
1)、将相机信息封装到 Camera Characteristics 中,并提获取 CameraCharacteristics 实例的方式。
2)、根据指定的相机 ID 打开相机设备(openCamera)。
3)、提供将闪光灯设置成手电筒模式的快捷方式。
可以通过调用 Context.getSystemService()
得到这个类的一个实例。
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
二、内部类
1、AvailabilityCallback抽象类
相机设备变为可用或不可打开的回调。
当不再使用相机或连接新的可拆卸相机时,相机将变得可用。 当某些应用程序或服务开始使用相机时,或者当可移动相机断开连接时,它们将变得不可用。
扩展此回调并将子类的实例传递给 {@link CameraManager#registerAvailabilityCallback} 以获取此类可用性更改的通知。
回调接口:
/**
新相机已经可以使用。
此方法的默认实现不执行任何操作。
参数:
cameraId – 新相机的唯一标识符。
*/
public void onCameraAvailable(@NonNull String cameraId) { // default empty implementation }
/**
之前可用的相机已无法使用。
如果应用程序具有当前已断开连接的相机的活动 CameraDevice 实例,则该应用程序将收到断开连接错误。
此方法的默认实现不执行任何操作。
参数:
cameraId – 断开连接的摄像头的唯一标识符。
*/
public void onCameraUnavailable(@NonNull String cameraId) { // default empty implementation }
/**
每当相机访问优先级发生变化时调用。
相机访问优先级已更改并且相机现在可以打开的通知。 之前由于较高优先级用户已使用相机而拒绝相机访问的应用程序,或者由于较高优先级用户尝试打开相机而与活动相机会话断开连接的应用程序,应尝试再次打开相机,如果 它仍然想使用它。 请注意,多个应用程序可能会同时收到此回调,并且实际上只有其中一个应用程序会成功打开相机,具体取决于确切的访问优先级和时间。 当多个应用程序可能同时处于恢复状态并且用户在它们之间切换焦点,或者当前使用相机的应用程序在全屏和画中画 (PiP) 之间移动时,此方法非常有用 。 在这种情况下,将不会调用相机可用/不可用回调,但另一个应用程序现在可能比当前使用相机的应用程序具有更高的相机访问优先级。
此方法的默认实现不执行任何操作。
*/
public void onCameraAccessPrioritiesChanged() { // default empty implementation }
/**
物理相机已再次可用。
默认情况下,逻辑多机位的所有物理机均可用,因此在调用逻辑多机位的onCameraAvailable时,逻辑多机位的任何物理机都不会调用onPhysicalCameraAvailable。 但是,如果某些特定的物理相机一开始不可用,则可能会在 onCameraAvailable 之后调用 onPhysicalCameraUnavailable。
此方法的默认实现不执行任何操作。
参数:
cameraId – 逻辑多摄像头的唯一标识符。
physicalCameraId – 物理相机的唯一标识符。
*/
public void onPhysicalCameraAvailable(@NonNull String cameraId, @NonNull String physicalCameraId) { // default empty implementation }
/**
之前可用的物理相机已无法使用。
默认情况下,逻辑多机位的所有物理机均可用,因此在调用逻辑多机位的onCameraAvailable时,逻辑多机位的任何物理机都不会调用onPhysicalCameraAvailable。 如果某些特定的物理相机一开始不可用,则可能会在 onCameraAvailable 之后调用 onPhysicalCameraUnavailable。
此方法的默认实现不执行任何操作。
参数:
cameraId – 逻辑多摄像头的唯一标识符。
physicalCameraId – 物理相机的唯一标识符。
*/
public void onPhysicalCameraUnavailable(@NonNull String cameraId, @NonNull String physicalCameraId) { // default empty implementation }
/**
相机设备已被应用程序打开。
此方法的默认实现不执行任何操作。
需要 android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER 才能接收此回调
参数:
cameraId – 打开的相机的唯一标识符。
packageId – 打开相机的应用程序的包 ID。
*/
@SystemApi @TestApi @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) { // default empty implementation }
/**
先前打开的相机已被关闭。
此方法的默认实现不执行任何操作。
需要 android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER 才能接收此回调。
参数:
cameraId – 关闭相机的唯一标识符。
*/
@SystemApi @TestApi @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String cameraId) { // default empty implementation }
2、TorchCallback抽象类
相机闪光灯模式变得不可用、禁用或启用的回调。
当手电筒模式所属的相机设备不可用或由于其他更高优先级的相机活动而导致其所需的其他相机资源变得繁忙时,手电筒模式将变得不可用。 当手电筒模式被关闭或者其所属的相机设备不再使用且其所需的其他相机资源不再繁忙时,手电筒模式将被禁用。 当应用程序调用 setTorchMode 关闭相机的手电筒模式时,或者当应用程序打开另一台相机的手电筒模式(如果不支持同时打开多个手电筒模式)时,相机的手电筒模式将关闭。 当通过 setTorchMode 打开手电筒模式时,手电筒模式将被启用。
仅当手电筒模式处于禁用或启用状态时,才可通过 setTorchMode 设置。
扩展此回调并将子类的实例传递给 registerTorchCallback 以收到此类状态更改的通知。
/**
相机的手电筒模式无法通过 setTorchMode 设置。
如果之前通过调用 setTorchMode 打开了火炬模式,则在调用 onTorchModeUnavailable 之前将它关闭。 setTorchMode 将失败,直到火炬模式再次进入禁用或启用状态。
此方法的默认实现不执行任何操作。
参数:
cameraId – 手电筒模式不可用的相机的唯一标识符。
*/
public void onTorchModeUnavailable(@NonNull String cameraId) { // default empty implementation }
/**
相机的手电筒模式已启用或禁用,并且可以通过 setTorchMode 进行更改。
此方法的默认实现不执行任何操作。
参数:
cameraId – 手电筒模式已更改的相机的唯一标识符。
enabled– 相机手电筒模式已更改为的状态。 当手电筒模式已打开并且可以关闭时为 true。 当手电筒模式已关闭且可以打开时为 false。
*/
public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) { // default empty implementation }
/**
在手电筒模式下,相机的闪光灯单元亮度级别已通过 TurnOnTorchWithStrengthLevel 进行了更改。 当手电筒关闭时,即使手电筒强度重置为默认值,也不会触发此回调 CameraCharacteristics.FLASH_INFO_STRENGTH_DEFAULT_LEVEL
此方法的默认实现不执行任何操作。
参数:
cameraId – 闪光灯亮度级别已更改的相机的唯一标识符。
newStrengthLevel – 已更改的闪光灯装置的亮度级别。
*/
public void onTorchStrengthLevelChanged(@NonNull String cameraId, int newStrengthLevel) { // default empty implementation }
三、方法
/**
根据相机id获取相机特性,相机特性保存在一个CameraCharacteristics对象中。一项属性表示为一个键值对,所以该对象是一个键值对的集合。
查询相机设备的功能。 对于给定的相机,这些功能是不可变的。
从API级别29开始,该函数还可以用于查询只能用作逻辑多摄像头一部分的物理摄像头的功能。 这些相机无法通过openCamera直接打开
同样从 API 级别 29 开始,虽然即使没有 CAMERA 权限,大多数基本相机信息仍然可用,但某些值对于不持有该权限的应用程序不可用。 CameraCharacteristics.getKeysNeedingPermission 列出了不可用的键。
参数:
cameraId – 要查询的相机设备的 ID。 这可以是可以由 openCamera 直接打开的独立摄像机 ID,也可以是只能用作逻辑多摄像机一部分的物理摄像机 ID。
Return:
给定相机的属性
Throws:
IllegalArgumentException – 如果cameraId 与任何已知的相机设备都不匹配。
CameraAccessException – 如果相机设备已断开连接。
*/
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId) throws CameraAccessException
/**
查询摄像头设备的摄像头扩展能力。
参数:
cameraId – 要查询的相机设备的 ID。 这必须是一个独立的相机ID,可以直接由openCamera打开。
Rturn:
给定相机的属性
Throws:
IllegalArgumentException – 如果cameraId 与任何已知的相机设备都不匹配。
CameraAccessException – 如果相机设备已断开连接
*/
public CameraExtensionCharacteristics getCameraExtensionCharacteristics( @NonNull String cameraId) throws CameraAccessException
/**
获取相机列表,每个相机用一个String类型的id表示,后面通过id可以获取对应的相机设备。所有相机id的列表保存在一个String数组中,设备上有几个相机就在数组中几个元素。
按标识符返回当前连接的相机设备列表,包括其他相机 API 客户端可能正在使用的相机。
不可移动相机使用从 0 开始的整数作为标识符,而可移动相机对每个单独的设备都有唯一的标识符,即使它们是同一型号。
此列表不包含只能用作逻辑多摄像头设备一部分的物理摄像头。
Return:
当前连接的相机设备列表。
*/
public String[] getCameraIdList() throws CameraAccessException
/**
与 getCameraIdList() 类似。 然而,getCamerIdListNoLazy() 必须与cameraserver 通信才能获取相机ID 列表。 这是为了方便测试,因为某些相机 ID 可能会因以下更改而“离线”,而无需从相机服务器回调
SYSTEM_CAMERA 权限(尽管这不是可更改的权限,但测试可以调用 acquire(drop)ShellPermissionIdentity() 并有效地更改其权限)。 此调用也会影响 getCameraIdList() 返回的相机 ID。 采用 shell 权限标识的测试不应混合 getCameraIdList() 和 getCameraListNoLazyCalls()。
*/
public String[] getCameraIdListNoLazy() throws CameraAccessException
/**
返回当前连接的相机设备标识符的组合集,支持同时配置相机设备会话。
这些组合中的设备可以由同一客户端相机应用程序同时配置。 但是,不保证支持两个不同的应用程序同时使用这些相机设备。
对于并发操作,按时间顺序: - 应用程序必须首先使用 CameraDevice.close 关闭已配置会话的所有打开的摄像头。 - 在任何相机设备上配置会话之前,必须使用 openCamera 打开所有要同时操作的相机设备。
组合中的每个设备都保证支持流组合,可以通过查询 getCameraCharacteristics 中的关键 CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS 来获得流组合。
对于并发操作,如果相机设备具有由 CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE 指定的非空缩放比例范围,则其完整的缩放比例范围可能不适用。 应用程序可以在并发操作期间使用 CaptureRequest.CONTROL_ZOOM_RATIO >=1 且 <= CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM。
该组组合可以包括可以由其他相机API客户端使用的相机设备。
当前不支持并发相机扩展会话 CameraExtensionSession。
该组合集不包含只能用作逻辑多摄像头设备的一部分的物理摄像头。
如果通过 CameraManager.AvailabilityCallback.onCameraUnavailable(String) 有新的相机 ID 可用,客户端可以调用此方法来检查可并发流式传输的新相机 ID 组合是否可用。
Rturn:
当前连接的相机设备的组合集,可能同时配置会话。 如果相机子系统不支持此类组合,则该组合集将为空。
Throw:
CameraAccessException – 如果相机设备已断开连接。
*/
@NonNull public Set> getConcurrentCameraIds() throws CameraAccessException
/**
检查提供的一组摄像头设备及其相应的 SessionConfiguration 是否可以同时配置。
此方法对给定的 SessionConfiguration 和相机 ID 组合执行运行时检查。 结果确认是否可以使用 CameraDevice.createCaptureSession(SessionConfiguration) 在给定相机设备上成功使用传递的会话配置来同时创建相机捕获会话。
该方法可以在活动捕获会话之前、期间和之后的任何时刻调用。 它不会以任何方式影响正常的相机行为,并且必须比创建常规或受限捕获会话快得多。
尽管此方法比创建新的捕获会话更快,但它并不旨在用于探索受支持的并发流组合的整个空间。 可用的强制并发流组合可以通过查询 getCameraCharacteristics 中的关键 CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS 来获取。
请注意,会话参数将被忽略,并且不需要调用 SessionConfiguration.setSessionParameters。
Rturn:
如果相机子系统同时支持会话配置和相应相机 ID 的给定组合,则为 true;否则为 false,或者如果提供的相机设备集不是 getConcurrentCameraIds 返回的相机设备集的子集。
Throw:
CameraAccessException – 如果查询的相机设备之一不再连接。
*/
@RequiresPermission(android.Manifest.permission.CAMERA) public boolean isConcurrentSessionConfigurationSupported( @NonNull MapcameraIdAndSessionConfig) throws CameraAccessException
/**
返回与cameraId关联的闪光灯装置的亮度级别。
参数:
cameraId – 闪光灯所属相机设备的唯一标识符。
Return:
与cameraId关联的闪光灯的亮度级别。 当手电筒关闭时,强度级别将重置为默认级别 CameraCharacteristics.FLASH_INFO_STRENGTH_DEFAULT_LEVEL。 在这种情况下,返回值将为 CameraCharacteristics.FLASH_INFO_STRENGTH_DEFAULT_LEVEL 而不是 0。
Throws:
CameraAccessException – 如果无法访问闪光灯单元。
IllegalArgumentException – 如果cameraId 为 null,则cameraId 与任何当前或以前可用的相机设备都不匹配,或者相机设备没有闪光灯装置。
*/
public int getTorchStrengthLevel(@NonNull String cameraId)throws CameraAccessException
/**
openCamera()方法有三个参数,第一个参数是cameraId,这里使用上一步获取到的后置相机的id。第二个参数是处理结果的回调对象,和事件处理机制中的监听器一样。openCamera()方法是异步执行的,调用以后方法马上返回,继续执行后续代码,打开相机是否成功的结果要过一段时间才返回,返回后调用回调对象的对应方法。第三个参数是执行回调方法的线程,可以是主线程,也可以是后台线程。回调对象需要在调用openCamera()方法之前创建。
打开与给定 ID 的相机的连接。
使用 {@link #getCameraIdList} 获取可用相机的列表
设备。 请注意,即使列出了 id,如果设备
在对 {@link #getCameraIdList} 的调用之间断开连接
{@link #openCamera},或者更高优先级的相机 API 客户端开始使用相机设备。
从 API 级别 23 开始,由于设备正在被较低优先级的后台相机 API 客户端使用而被调用 {@link AvailabilityCallback#onCameraUnavailable(String)} 回调的设备仍然可以通过调用此方法打开 当调用相机 API 客户端的优先级高于当前使用该设备的相机 API 客户端时。 一般来说,如果顶级前台活动在您的应用程序进程中运行,则您的进程在访问相机时将获得最高优先级,并且即使相机设备正在被另一个相机 API 客户端使用,此方法也会成功。 任何以这种方式失去对相机控制的低优先级应用程序都将收到 {@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected} 回调。 在同一个应用程序中打开同一个相机 ID 两次同样会导致第一次打开调用时为 {@link CameraDevice} 触发 {@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected} 回调,并且所有正在进行的任务都会被丢弃 。
成功打开相机后,将使用新打开的 {@link CameraDevice} 调用 {@link CameraDevice.StateCallback#onOpened}。 然后可以通过调用 {@link CameraDevice#createCaptureSession} 和 {@link CameraDevice#createCaptureRequest} 来设置相机设备以进行操作。
在 API 级别 30 之前,当应用程序尝试打开多个不同 ID 的 {@link CameraDevice} 并且该设备不支持打开此类组合时,{@link #openCamera} 将失败并抛出 {@link CameraAccessException} 或一个 或多个已打开的 {@link CameraDevice} 将断开连接并接收 {@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected} 回调。 会发生哪种行为取决于设备实现,并且可能因不同设备而异。从 API 级别 30 开始,如果设备不支持摄像头组合
打开后,可以保证 {@link #openCamera} 调用会失败,并且现有的 {@link CameraDevice} 都不会断开连接。
由于相机设备将异步打开,因此在返回的 CameraDevice 实例上完成的任何异步操作都将排队,直到设备启动完成并调用回调的 {@link CameraDevice.StateCallback#onOpened onOpened} 方法。 然后按顺序处理待处理的操作。
如果此函数调用返回后,相机在初始化期间断开连接,则 {@link CameraDevice.StateCallback#onDisconnected} 与处于断开连接状态的 {@link CameraDevice} (且 {@link CameraDevice.StateCallback#onOpened} 将被跳过)。
如果打开相机设备失败,则会调用设备回调的 {@link CameraDevice.StateCallback#onError onError} 方法,并且后续对相机设备的调用将抛出 {@link CameraAccessException}。
参数:
cameraId-要打开的摄像头设备的唯一标识符
callback-相机打开后调用的回调
handler-应调用回调的处理程序,或使用当前线程的 {@link android.os.Looper Looper}。
Throws:
CameraAccessException-如果相机被设备策略禁用、已断开连接、正在被更高优先级的相机 API 客户端使用,或者设备已达到其最大资源并且无法打开此相机设备。
IllegalArgumentException-如果cameraId或回调为null,或者cameraId与{@link #getCameraIdList}返回的任何当前或以前可用的相机设备不匹配。
SecurityException-如果应用程序没有访问相机的权限
*/
@RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String cameraId, @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler) throws CameraAccessException
/**
无需打开相机设备即可设置给定 ID 相机的闪光灯模式。
使用 getCameraIdList 获取可用相机设备列表,并使用 getCameraCharacteristics 检查相机设备是否有闪光灯。 请注意,即使相机设备具有闪光灯装置,如果相机设备或打开手电筒模式所需的其他相机资源正在使用,打开手电筒模式也可能会失败。
如果调用setTorchMode成功打开或关闭手电筒模式,则会调用CameraManager.TorchCallback.onTorchModeChanged。 然而,即使开启手电筒模式成功,应用程序也不拥有闪光灯或相机设备的独占所有权。 当闪光灯所属的相机设备不可用或其他保持手电筒开启的相机资源不可用时(将调用 CameraManager.TorchCallback.onTorchModeUnavailable),手电筒模式将关闭并变得不可用。 此外,其他应用程序可以随意调用 setTorchMode 来关闭手电筒模式(将调用 CameraManager.TorchCallback.onTorchModeChanged)。 如果最近打开手电筒模式的应用程序退出,手电筒模式将会关闭。
参数:
cameraId – 闪光灯所属相机设备的唯一标识符。
enabled– 目标相机设备所需的手电筒模式状态。 设置为 true 以打开手电筒模式。 设置为 false 可关闭手电筒模式。
Throws:
CameraAccessException – 如果无法访问闪光灯单元。 如果正在使用相机设备,则会抛出CameraAccessException.CAMERA_IN_USE。如果正在使用打开手电筒模式所需的其他相机资源,则会抛出CameraAccessException.MAX_CAMERA_IN_USE。 如果相机服务不可用,将抛出 CameraAccessException.CAMERA_DISCONNECTED。
IllegalArgumentException – 如果cameraId 为 null,则cameraId 与任何当前或以前可用的相机设备都不匹配,或者相机设备没有闪光灯装置。
*/
public void setTorchMode(@NonNull String cameraId, boolean enabled) throws CameraAccessException
/**
注册回调以获取有关相机设备可用性的通知。
再次注册相同的回调会将处理程序替换为提供的新处理程序。
第一次注册回调时,会立即调用它并显示所有当前已知相机设备的可用性状态。
每当任何相机 API 客户端打开相机设备时,都会调用 CameraManager.AvailabilityCallback.onCameraUnavailable(String)。 从 API 级别 23 开始,其他相机 API 客户端仍然可以打开此类相机设备,如果它们具有比相机设备现有客户端更高的优先级,则会驱逐现有客户端。 有关详细信息,请参阅 open()。
由于此回调将注册到相机服务中,因此请记住在不再需要时注销它; 否则回调将无限期地继续接收事件,并且可能会阻止其他资源被释放。 具体来说,回调的调用将独立于一般活动生命周期,也独立于各个 CameraManager 实例的状态。
参数:
callback – 用于发送相机可用性通知的新回调
handler – 应调用回调的处理程序,或 null 以使用当前线程的循环程序。
投掷:
IllegalArgumentException – 如果处理程序为 null 但当前线程没有looper。
*/
public void registerAvailabilityCallback(@NonNull AvailabilityCallback callback, @Nullable Handler handler)
/**
删除之前添加的回调; 回调将不再接收连接和断开连接回调。
删除未注册的回调没有任何效果。
参数:
callback– 从通知列表中删除的回调
*/
public void unregisterAvailabilityCallback(@NonNull AvailabilityCallback callback)
/**
注册回调以获取有关火炬模式状态的通知。
此方法的行为与 registerTorchCallback(CameraManager.TorchCallback, Handler) 的行为一致,只是它使用 Executor 而不是 Handler 作为参数。
参数:
executor – 将用于调用回调的执行器
callback – 将火炬模式状态发送到的新回调
Throws:
IllegalArgumentException – 如果执行器为 null。
*/
public void registerTorchCallback(@NonNull @CallbackExecutor Executor executor, @NonNull TorchCallback callback)
/**
删除之前添加的回调; 回调将不再接收火炬模式状态回调。
删除未注册的回调没有任何效果。
参数:
callback– 从通知列表中删除的回调
*/
public void unregisterTorchCallback(@NonNull TorchCallback callback)