MSCameraSurfaceViewManager.java

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
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.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import java.nio.ByteBuffer;
import java.util.Arrays;

import static com.mingshine.msdemo.MSCameraSurfaceManager.REQUEST_CAMERA_CODE;

/**
* Main UI for the statistics screen.
*/
public class MSCameraSurfaceViewManager {

//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
private static MSCameraSurfaceViewManager instance;
public final static String CAMERA_FRONT = "1";
public final static String CAMERA_BACK = "0";
private SurfaceView mSurfaceView;
private boolean mIsFaceAi;
private Activity mActivity;
private String mCameraId;//摄像头Id 0 为后 1 为前
private SurfaceHolder mSurfaceHolder;
private Handler childHandler, mainHandler;
private ImageReader mImageReader;
private CameraManager mCameraManager;//摄像头管理器
private CameraDevice mCameraDevice;
private CameraCaptureSession mCameraCaptureSession;

//构造器私有化
private MSCameraSurfaceViewManager() {
}

private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

///为了使照片竖直显示
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

//方法同步,调用效率低
public static synchronized MSCameraSurfaceViewManager getInstance() {
if (instance == null) {
instance = new MSCameraSurfaceViewManager();
}
return instance;
}

public void initCamera(Activity activity, SurfaceView surfaceView, boolean isFaceAi) {
this.mSurfaceView = surfaceView;
this.mActivity = activity;
this.mIsFaceAi = isFaceAi;
if (isFaceAi) {
mCameraId = CAMERA_FRONT;
} else {
mCameraId = CAMERA_BACK;
}
initData();
}

private void initData() {
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setKeepScreenOn(true);
// mSurfaceView添加回调
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
// 初始化Camera
initCamera2();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
/**
* 人脸识别计算
*/

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
// 释放Camera资源
if (null != mCameraDevice) {
mCameraDevice.close();
MSCameraSurfaceViewManager.this.mCameraDevice = null;
}
}
});
}

/**
* 初始化Camera2
*/
private void initCamera2() {
HandlerThread handlerThread = new HandlerThread("Camera2");
handlerThread.start();
childHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(mActivity.getMainLooper());
mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如,写入本地
@Override
public void onImageAvailable(ImageReader reader) {
//mCameraDevice.close();
// 拿到拍照照片数据
Image image = reader.acquireNextImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);//由缓冲区存入字节数组
final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
if (bitmap != null) {
// iv_show.setImageBitmap(bitmap);
}
Log.e("==========", "=====拍照======");
image.close();
}
}, mainHandler);
//获取摄像头管理
mCameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
//申请WRITE_EXTERNAL_STORAGE权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mActivity.requestPermissions(new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_CODE);
}
//return;
} else {
//打开摄像头
mCameraManager.openCamera(mCameraId, stateCallback, mainHandler);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

/**
* 摄像头创建监听
*/
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {//打开摄像头
mCameraDevice = camera;
//开启预览
takePreview();
}

@Override
public void onDisconnected(CameraDevice camera) {//关闭摄像头
if (null != mCameraDevice) {
mCameraDevice.close();
MSCameraSurfaceViewManager.this.mCameraDevice = null;
}
}

@Override
public void onError(CameraDevice camera, int error) {//发生错误
Toast.makeText(mActivity, "摄像头开启失败", Toast.LENGTH_SHORT).show();
}
};

/**
* 开始预览
*/
private void takePreview() {
try {
// 创建预览需要的CaptureRequest.Builder
final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
// 将SurfaceView的surface作为CaptureRequest.Builder的目标
previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
// 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③
{
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
if (null == mCameraDevice) return;
// 当摄像头已经准备好时,开始显示预览
mCameraCaptureSession = cameraCaptureSession;
try {
// 自动对焦
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 打开闪光灯
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// 显示预览
CaptureRequest previewRequest = previewRequestBuilder.build();
mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Toast.makeText(mActivity, "配置失败", Toast.LENGTH_SHORT).show();
}
}, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

/**
* 拍照
*/
public void takePhoto() {
if (mCameraDevice == null) return;
// 创建拍照需要的CaptureRequest.Builder
final CaptureRequest.Builder captureRequestBuilder;
try {
captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 将imageReader的surface作为CaptureRequest.Builder的目标
captureRequestBuilder.addTarget(mImageReader.getSurface());
// 自动对焦
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 自动曝光
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
// 获取手机方向
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
// 根据设备方向计算设置照片的方向
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
//拍照
CaptureRequest mCaptureRequest = captureRequestBuilder.build();
mCameraCaptureSession.capture(mCaptureRequest, null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}


}