之前有用过旧版的Camera实现相机预览,可是很多东西不好控制,而且旧版的camera现在以被弃用,所以使用Camera2来进行项目的开发。
先看效果:
camera2是为连接Android相机的接口。
这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送Capture请求,而摄像头返回CameraMetadata。在一切建立在一个叫做CameraCaptureSession的会话中。
Camera2支持RAW输出,可以调节曝光,对焦模式,快门等。
- CameraManager:摄像头管理器,用于检测摄像头,打开系统摄像头,调用
CameraManager.getCameraCharacteristics(String)
可以获取指定摄像头的相关特性 - CameraCharacteristics 摄像头的特性
- CameraDevice 摄像头,类似android.hardware.Camera也就是Camera1的Camera
- CameraCaptureSession 这个对象控制摄像头的预览或者拍照,setRepeatingRequest()开启预览,capture()拍照,CameraCaptureSession提供了StateCallback、CaptureCallback两个接口来监听CameraCaptureSession的创建和拍照过程。
- CameraRequest和CameraRequest.Builder,预览或者拍照时,都需要一个CameraRequest对象。CameraRequest表示一次捕获请求,用来对z照片的各种参数设置,比如对焦模式、曝光模式等。CameraRequest.Builder用来生成CameraRequest对象。
预览的基本思想
在这里,我使用的是OpenGL ES,用摄像头获取的图像,调用OpenGL ES的库进行绘制。
摄像头:
Camera2使用的是Surface来进行预览,这个surface包括:SurfaceView, SurfaceTexture ( Surface(SurfaceTexture))
关于各个surface的区别可以参考:https://blog.csdn.net/jinzhuojun/article/details/44062175
主要思路
- 获得摄像头管理器
mCameraManager
,mCameraManager.openCamera()
来打开摄像头 - 指定要打开的摄像头,并创建
openCamera()
所需要的CameraDevice.StateCallback stateCallback
- 在
CameraDevice.StateCallback stateCallback
中调用createPreview()
,这个方法中,使用CaptureRequest.Builder
创建预览需要的CameraRequest
,并初始化了CameraCaptureSession
- 在
CameraCaptureSession
的回调中,最后调用了setRepeatingRequest(previewRequest, null, null)
进行了预览
Camera代码:
public class CameraHelper {
private Context mContext;
private CameraManager mCameraManager;
private CameraDevice mCameraDevice;
private String mCameraId = null;
private boolean mFlashSupport = false;
private Surface mSurface;
private CaptureRequest.Builder mPreviewBuilder;
private android.os.Handler mMainHandler;
private android.os.Handler mChildHanlder;
private static final String TAG = "CameraHelper";
public CameraHelper(Context context, SurfaceTexture surfaceTexture){
mContext = context;
Display display = ((WindowManager)context
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHidth = metrics.heightPixels;
//设置图像像素比位4:3
surfaceTexture.
setDefaultBufferSize(4*screenWidth/3,3 * screenWidth / 4);
mSurface = new Surface(surfaceTexture);
initCamera();
}
private void initCamera(){
//得到CameraManager
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
try {
for(String id : mCameraManager.getCameraIdList()){
CameraCharacteristics characteristics
= mCameraManager.getCameraCharacteristics(id);
Integer front = cha