之前博文《Android学习笔记之——调用前后置相机的视频流》已经实现了视频流的捕获与显示了(通过 camera1 setPreviewCallback 类似功能实现)。本博文继续学习一下Android中的camera相关的API
目录
Camera2
基本框架及流程
Camera2的各个部分详解
CaptureRequest
CaptureResult
CameraCaptureSession
CameraDevice
CameraManager
CameraCharacteristics
Surface和CaptureRequest
TextureView + Camera2
Test demo1
UI
mainactivity
权限申请
参考资料
全新的android.hardware.Camera2 。Android 5.0对拍照API进行了全新的设计,新增了全新设计的Camera 2 API,这些API不仅大幅提高了Android系统拍照的功能,还能支持RAW照片输出,甚至允许程序调整相机的对焦模式、曝光模式、快门等。
在API架构方面, Camera2和之前的Camera有很大区别, APP和底层Camera之前可以想象成用管道方式连接, 如下图:
如上图所示, Camera APP 通过CameraCaptureSession发送CaptureRequest, CameraDevices收到请求后返回对应数据到对应的Surface,预览数据一般都是到TextureView, 拍照数据则在ImageReader中, 整体来说就是一个请求--响应过程, 请求完成后, 可以在回调中查询到相应的请求参数和CameraDevice当前状态, 总的来说, Camera2中预览/拍照/录像数据统一由Surface来接收, CaptureRequest代表请求控制的Camera参数, CameraMetadata(CaptureResult)则表示当前返回帧中Camera使用的参数以及当前状态.
API使用流程大体如下:
步骤
context.getSystemService(Context.CAMERA_SERVICE)
获取CameraManager
.CameraManager .open()
方法在回调中得到CameraDevice
.CameraDevice.createCaptureSession()
在回调中获取CameraCaptureSession
.CaptureRequest
, 有三种模式可选 预览/拍照/录像.CameraCaptureSession
发送CaptureRequest
, capture表示只发一次请求, setRepeatingRequest表示不断发送请求.ImageReader.OnImageAvailableListener
回调中获取, CaptureCallback
中则可获取拍照实际的参数和Camera当前状态.
叫出CameraManager ,打开 CameraDevice ,拿住CameraCaptureSession,发送CaptureRequest 。
(参考资料https://blog.csdn.net/afei__/article/details/86326991)
(官方资料https://developer.android.com/reference/android/hardware/camera2/CaptureRequest)
CaptureRequest
表示一个捕捉的请求。我们可以为不同的场景(预览、拍照)创建不同的捕捉请求,并可以配置不同的捕捉属性,如:预览分辨率,预览目标,对焦模式、曝光模式等等。
Camera2下的摄像机称为CameraDevice,可以有很多个(一般是前后两个),每个CameraDevice都带有ameraCaptureSession的会话通道,只要我们捉住了一条会话通道,就可以通过这条通道传送CameraRequest请求预览,拍照,录像。所以我们只要向目标CameraDevice索取一条CameraCaptureSession会话通道,利用以下方法就可以实现控制摄像头预览,拍照或者录像:
CameraCaptureSession.setRepeatingRequest(CaptureRequest arg0, CaptureCallback arg1, Handler arg2)
//第一个参数,需要通过这个会话通道向CameraDevice传送一个CaptureRequest请求
//第二个参数是回调,回调不做处理,所以null
//第三个参数是给回调用的线程,回调是null,线程自然也是null
CameraCaptureSession由CameraDevice创建,CameraDevice由CameraManage创建。
通过 CameraDevice 对象的 createCaptureRequest() 方法得到一个 CaptureRequest.Builder 对象,基本配置都是通过该构造者来配置;最后通过 CaptureRequest.Builder 对象的 build() 方法便可得到 CaptureRequest 实例。
内部类
1.CaptureRequest.Builder
典型的建造者模式,是 CaptureRequest 的构建者。
CaptureRequest.Builder builder;//先拿到一个 CaptureRequest.Builder 对象
builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
获取:使用 CameraDevice.createCaptureRequest(int) 方法获取一个 CaptureRequest.Builder 对象。其中的 int 取值为:
常用方法
2. CaptureRequest.Key
上面 get/set
方法中的 Key 类就是这个内部类了,用作 CaptureRequest.Builder 的属性字段设置和查询使用。
注意:通过getAvailableCaptureRequestKeys()
就是得到该相机设备可用的 CaptureRequest.Key 列表
(参考资料https://blog.csdn.net/afei__/article/details/86326991)
(官方文档链接:https://developer.android.com/reference/android/hardware/camera2/CaptureResult)
CaptureResult
表示捕捉的结果,是从图像传感器捕获单个图像的结果的子集。包含捕获硬件(传感器、镜头、闪光灯)、处理管道、控制算法和输出缓冲区的最终配置的子集。
捕获结果由摄像机在对捕获请求进行处理后产生。还可以对捕获结果查询为捕获请求列出的所有属性,以确定捕获使用的最终值。结果还包括捕获过程中相机设备状态的附加元数据。
CaptureResult 对象也是不可变的。常使用的子类是 TotalCaptureResult
。
(https://blog.csdn.net/afei__/article/details/86108482)
CameraCaptureSession 是一个事务,用来向相机设备发送获取图像的请求。
主要有 setRepeatingRequest() 和 capture() 方法。setRepeatingRequest() 是重复请求获取图像数据,常用于预览或连拍,capture() 是获取一次,常用于单张拍照。
CameraCaptureSession
类是一个抽象类,其直接的实现类为 CameraConstrainedHighSpeedCaptureSession
。
下面通过CameraDevice类的 createCaptureSession()
方法创建创建CameraCaptureSession实例,创建出来的CameraCaptureSession就在参数二的回调类CameraCaptureSession.StateCallback()的onConfigured(CameraCaptureSession arg0)方法的参数给与,参数三是给回调用的线程,可以null即使用主线程,参数一是一个Surface的list集合,用以存放请求结果,可以把多个Surface打包成List送过去,实现你想同时多个显示或者其他利用如存储的需求。
CameraDevice.createCaptureSession(List arg0, StateCallback arg1, Handler arg2)
参数说明:
内部类
1. CameraCaptureSession.StateCallback
当相机捕捉事务的状态发生变化时,会回调这个类中的相应方法。其中只有 onConfigured
和 onConfigureFailed
两个方法是抽象的(必须重写),其余均有空实现。
(https://blog.csdn.net/afei__/article/details/85342597)
(官方关于CameraDevice的介绍https://developer.android.google.cn/reference/android/hardware/camera2/CameraDevice)
CameraDevice
是一个连接的相机设备代表,可以把它看作为相机设备在 java 代码中的表现。
通过 CameraManager
的 openCamera()
方法打开相机,在 CameraDevice.StateCallback
的 onOpened(CameraDevice camera)
方法中可获得 CameraDevice 的实例。
CameraDevice是由CameraManager的openCamera方法创建的,CameraDevice同样是在参数二回调类参数中的onOpened(CameraDevice arg0)方法的参数送回,参数一是指定打开的摄像头,“0”是后置,“1”是前置,详细不多说,参数三又是回调占用的线程,null吧。
CameraManager.openCamera(String cameraId, StateCallback callback, Handler handler)
(参考资料https://blog.csdn.net/afei__/article/details/85342160)
(官方文档https://developer.android.google.cn/reference/android/hardware/camera2/CameraManager)
CameraManager
是系统服务之一,专门用于检测和打开相机,以及获取相机设备特性。
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
// 方式一
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
// 方式二
CameraManager manager = (CameraManager) context.getSystemService(CameraManager.class);
String[] getCameraIdList()
获取当前连接的相机设备列表,这个 id 通常都是从 0 开始并依次递增的。对于一般的手机而言:
CameraCharacteristics getCameraCharacteristics(String cameraId)
根据 cameraId 获取对应相机设备的特征。返回一个 CameraCharacteristics,类比于旧 API 中的 Camera.Parameter 类,里面封装了相机设备固有的所有属性功能
void openCamera(String cameraId, final CameraDevice.StateCallback callback, Handler handler)
打开指定的相机设备,该方法使用当前进程 uid 继续调用 openCameraForUid(cameraId, callback, handler, USE_CALLING_UID) 方法。
参数解释:
cameraId : 需要打开的相机 id。
callback : 回调类,常用如下几个回调方法。
onOpened(CameraDevice camera) 成功打开时的回调,此时 camera 就准备就绪,并且可以得到一个 CameraDevice 实例。
onDisconnected(CameraDevice camera) 当 camera 不再可用或打开失败时的回调,通常在该方法中进行资源释放的操作。
onError(CameraDevice camera, int error) 当 camera 打开失败时的回调,error 为具体错误原因,定义在 CameraDevice.StateCallback 类中。通常在该方法中也要进行资源释放的操作。
handler : 指定回调执行的线程。传 null 时默认使用当前线程的 Looper,我们通常创建一个后台线程来处理。
(参考资料https://blog.csdn.net/afei__/article/details/85960343)
(官方示例https://developer.android.google.cn/reference/android/hardware/camera2/CameraCharacteristics)
CameraCharacteristics 是描述相机设备的属性类,其中的属性都是固定的,继承自CameraMetadata
类。类比于旧 API 中的 CameraInfo
类。
包括:曝光补偿(Exposure compensation)、自动曝光/自动对焦/自动白平衡模式(AE / AF / AWB mode)、自动曝光/自动白平衡锁(AE / AWB lock)、自动对焦触发器(AF trigger)、拍摄前自动曝光触发器(Precapture AE trigger)、测量区域(Metering regions)、闪光灯触发器(Flash trigger)、曝光时间(Exposure time)、感光度(ISO Sensitivity)、帧间隔(Frame duration)、镜头对焦距离(Lens focus distance)、色彩校正矩阵(Color correction matrix)、JPEG 元数据(JPEG metadata)、色调映射曲线(Tonemap curve)、裁剪区域(Crop region)、目标 FPS 范围(Target FPS range)、拍摄意图(Capture intent)、硬件视频防抖(Video stabilization)等。
Surface可以来自控件TextureView,它用来显示摄像头的图像,在布局文件放一个,获取它的Surface可以通过它的监听事件
TextureView.setSurfaceTextureListener(SurfaceTextureListener listener)
之前博文《Android学习笔记之——调用前后置相机的视频流》就是用TextureView
new一个SurfaceTextureListener,在它的onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2)方法里的参数一提取SurfaceTexture arg0得到。
CaptureRequest.Builder builder;
builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(mPreviewSurface);
mCameraCaptureSession.setRepeatingRequest(builder.build(), null, null);
CaptureRequest则由CameraDevice.createCaptureRequest()创建的builder,绑定目标surface后再builder()出来。
https://blog.csdn.net/afei__/article/details/85269753
https://blog.csdn.net/afei__/article/details/86710164
之前博文《 Android学习笔记之——调用前后置相机的视频流》已经介绍过TextureView。由于 SurfaceView
是拥有一个独立的 Surface
,不在 View hierachy
体系中,因此不支持动画和截图,而 TextureView
则没有该限制。TextureView
是 Android 4.0 之后引入的,它将内容流直接投影到 View 中,数据流可以来自 App 进程或远端进程。缺点是必须在硬件加速的窗口中使用,且内存和耗电比 SurfaceView
更高,绘制也可能存在 1~3 帧的延迟。
package com.example.camera2test;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
private TextureView mTextureView;//显示数据流的UI控件
private CameraCaptureSession mCameraCaptureSession;//是一个事务,用来向相机设备发送获取图像的请求。
private CameraDevice mCameraDevice;//是一个连接的相机设备代表,你可以把它看作为相机设备在 java 代码中的表现
private Surface mPreviewSurface;//Surface来自控件TextureView,它用来显示摄像头的图像,
//权限
private static String[] PERMISSIONS_STORAGE = {
// Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,//写权限
Manifest.permission.CAMERA//照相权限
};
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
如果提示【Fail to connect to camera service】很可能是没申请权限,或申请权限了但用户没有给你权限
//华为手机摄像头权限申请
//用于判断SDK版本是否大于23
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//检查权限
int i = ContextCompat.checkSelfPermission(this,PERMISSIONS_STORAGE[0]);
//如果权限申请失败,则重新申请权限
if(i!= PackageManager.PERMISSION_GRANTED){
//重新申请权限函数
startRequestPermission();
Log.e("这里","权限请求成功");
}
}
//预览用的surface
mTextureView = (TextureView) this.findViewById(R.id.texture_view_back);
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
//SurfaceTexture准备就绪后调用这个方法
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// TODO 自动生成的方法存根
mPreviewSurface = new Surface(surface);//定义一个surface
//1、先通过通过context.getSystemService(Context.CAMERA_SERVICE) 方法来获取CameraManager
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);//系统服务,专门用于检测和打开相机,以及获取相机设备特性
try {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
//2、再通过调用CameraManager .open()方法在回调中得到CameraDevice。ID0为后置摄像头
manager.openCamera("0", new CameraDevice.StateCallback() {//打开指定的相机设备
//成功打开时的回调,此时 camera 就准备就绪,并且可以得到一个 CameraDevice 实例。
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;//所回调的相机设备赋予给mCameraDevice
try {
//CameraCaptureSession 是一个事务,用来向相机设备发送获取图像的请求
//3、通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession
mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface), new CameraCaptureSession.StateCallback() {
//CameraCaptureSession.StateCallback是其内部类
//相机设备完成配置,并开始处理捕捉请求时回调
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCameraCaptureSession = session;//是一个事务,用来向相机设备发送获取图像的请求。
try {
//4、构建CaptureRequest, 有三种模式可选 预览/拍照/录像
//通过下面方法获得一个CaptureRequest.Builder对象。
//基本配置都是通过该构造者来配置
//最后通过 CaptureRequest.Builder 对象的 build() 方法便可得到 CaptureRequest 实例(见setRepeatingRequest方法)
CaptureRequest.Builder builder;//先拿到一个 CaptureRequest.Builder 对象
builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//TEMPLATE_PREVIEW : 用于创建一个相机预览请求。相机会优先保证高帧率而不是高画质。适用于所有相机设备
//TEMPLATE_STILL_CAPTURE : 用于创建一个拍照请求。
//TEMPLATE_RECORD : 用于创建一个录像请求。
//通过 CaptureRequest.Builder 对象设置一些捕捉请求的配置
//设置指定key的值
// builder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
builder.addTarget(mPreviewSurface);//绑定目标Surface
//5、通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求.
//不断的重复请求捕捉画面,常用于预览或者连拍场景。
mCameraCaptureSession.setRepeatingRequest(builder.build(), null, null);
} catch (CameraAccessException e1) {
e1.printStackTrace();
}
}
//该会话无法按照相应的配置发起请求时回调
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
//当 camera 不再可用或打开失败时的回调,通常在该方法中进行资源释放的操作。
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
}
//当 camera 打开失败时的回调,error 为具体错误原因
// 定义在 CameraDevice.StateCallback 类中。通常在该方法中也要进行资源释放的操作。
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
}, null);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
//在surface发生format或size变化时调用。
//SurfaceTexture缓冲大小变化
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
//SurfaceTexture即将被销毁
//在此处回调做一些释放资源的操作
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
//SurfaceTexture通过updateImage更新
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
}
private void startRequestPermission(){
//321为请求码
ActivityCompat.requestPermissions(this,PERMISSIONS_STORAGE,321);
}
}
设置曝光时间
package com.example.camera2test;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Range;
import android.view.Surface;
import android.view.TextureView;
import android.widget.Toast;
import java.util.Arrays;
import static android.hardware.camera2.CaptureRequest.SENSOR_EXPOSURE_TIME;
public class MainActivity extends AppCompatActivity {
private TextureView mTextureView;//显示数据流的UI控件
private CameraCaptureSession mCameraCaptureSession;//是一个事务,用来向相机设备发送获取图像的请求。
private CameraDevice mCameraDevice;//是一个连接的相机设备代表,你可以把它看作为相机设备在 java 代码中的表现
private Surface mPreviewSurface;//Surface来自控件TextureView,它用来显示摄像头的图像,
private CameraCharacteristics mCameraCharacteristics;
//权限
private static String[] PERMISSIONS_STORAGE = {
// Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,//写权限
Manifest.permission.CAMERA//照相权限
};
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
如果提示【Fail to connect to camera service】很可能是没申请权限,或申请权限了但用户没有给你权限
//华为手机摄像头权限申请
//用于判断SDK版本是否大于23
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//检查权限
int i = ContextCompat.checkSelfPermission(this,PERMISSIONS_STORAGE[0]);
//如果权限申请失败,则重新申请权限
if(i!= PackageManager.PERMISSION_GRANTED){
//重新申请权限函数
startRequestPermission();
Log.e("这里","权限请求成功");
}
}
//预览用的surface
mTextureView = (TextureView) this.findViewById(R.id.texture_view_back);
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
//SurfaceTexture准备就绪后调用这个方法
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// TODO 自动生成的方法存根
mPreviewSurface = new Surface(surface);//定义一个surface
//1、先通过通过context.getSystemService(Context.CAMERA_SERVICE) 方法来获取CameraManager
final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);//系统服务,专门用于检测和打开相机,以及获取相机设备特性
try {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
//2、再通过调用CameraManager .open()方法在回调中得到CameraDevice。ID0为后置摄像头
manager.openCamera("0", new CameraDevice.StateCallback() {//打开指定的相机设备
//成功打开时的回调,此时 camera 就准备就绪,并且可以得到一个 CameraDevice 实例。
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;//所回调的相机设备赋予给mCameraDevice
try {
//获取曝光时间这个属性。
mCameraCharacteristics = manager.getCameraCharacteristics(Integer.toString(0));
Range range=mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
long max=range.getUpper();
long min=range.getLower();
//通过Toast输出
Toast.makeText(MainActivity.this, "max:"+max+"min:"+min,Toast.LENGTH_LONG).show();
//CameraCaptureSession 是一个事务,用来向相机设备发送获取图像的请求
//3、通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession
mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface), new CameraCaptureSession.StateCallback() {
//CameraCaptureSession.StateCallback是其内部类
//相机设备完成配置,并开始处理捕捉请求时回调
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCameraCaptureSession = session;//是一个事务,用来向相机设备发送获取图像的请求。
try {
//4、构建CaptureRequest, 有三种模式可选 预览/拍照/录像
//通过下面方法获得一个CaptureRequest.Builder对象。
//基本配置都是通过该构造者来配置
//最后通过 CaptureRequest.Builder 对象的 build() 方法便可得到 CaptureRequest 实例(见setRepeatingRequest方法)
CaptureRequest.Builder builder;//先拿到一个 CaptureRequest.Builder 对象
builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//TEMPLATE_PREVIEW : 用于创建一个相机预览请求。相机会优先保证高帧率而不是高画质。适用于所有相机设备
//TEMPLATE_STILL_CAPTURE : 用于创建一个拍照请求。
//TEMPLATE_RECORD : 用于创建一个录像请求。
//设置曝光时间
builder.set(CaptureRequest.BLACK_LEVEL_LOCK, false);//黑电平补偿是锁定
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, (long) 10000);
//通过 CaptureRequest.Builder 对象设置一些捕捉请求的配置
//设置指定key的值
// builder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
builder.addTarget(mPreviewSurface);//绑定目标Surface
//5、通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求.
//不断的重复请求捕捉画面,常用于预览或者连拍场景。
mCameraCaptureSession.setRepeatingRequest(builder.build(), null, null);
} catch (CameraAccessException e1) {
e1.printStackTrace();
}
}
//该会话无法按照相应的配置发起请求时回调
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
//当 camera 不再可用或打开失败时的回调,通常在该方法中进行资源释放的操作。
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
}
//当 camera 打开失败时的回调,error 为具体错误原因
// 定义在 CameraDevice.StateCallback 类中。通常在该方法中也要进行资源释放的操作。
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
}, null);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
//在surface发生format或size变化时调用。
//SurfaceTexture缓冲大小变化
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
//SurfaceTexture即将被销毁
//在此处回调做一些释放资源的操作
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
//SurfaceTexture通过updateImage更新
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
}
private void startRequestPermission(){
//321为请求码
ActivityCompat.requestPermissions(this,PERMISSIONS_STORAGE,321);
}
}
但还是失败了。。。。设置了,但是显示的曝光时间没有降低
https://www.jianshu.com/p/d83161e77e90
https://zhuanlan.zhihu.com/p/85271179(代码主要参考这个)
https://github.com/android/camera-samples(官方资料)
https://www.jianshu.com/p/23e8789fbc10
https://blog.csdn.net/afei__/article/details/51540188(一些bug的解决)