创建一个 CameraProvider类
package com.example.opencv_cpp_test;
import android.Manifest;
import android.annotation.SuppressLint;
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.graphics.Matrix;
import android.graphics.RectF;
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.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import java.nio.ByteBuffer;
import java.util.Arrays;
import static androidx.core.content.ContextCompat.checkSelfPermission;
public class CameraProvider {
private Activity mContext;
private String mCameraId;
private Handler mCameraHandler;
private CameraDevice mCameraDevice;
private TextureView mTextureView;
private CaptureRequest.Builder mPreviewBuilder;
private Size previewSize;
ImageReader mImageReader;
private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
//获取最新的一帧的Image
Image image = reader.acquireLatestImage();
Log.e("cam123","onImageAvailable");
if(image!=null){
image.close();
}
}
};
public CameraProvider(Activity mContext) {
this.mContext = mContext;
//创建了一个Thread来供Camera运行使用,使用HandlerThread而不使用Thread是因为HandlerThread给我们创建了Looper,不用我们自己创建了。
HandlerThread handlerThread = new HandlerThread("camera");
handlerThread.start();
mCameraHandler = new Handler(handlerThread.getLooper());
}
public void initTexture(TextureView textureView) {
mTextureView = textureView;
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera(width, height);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
}
private void configureTransform(int viewWidth, int viewHeight) {
int rotation = Surface.ROTATION_90;
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* surface ready的时候开启Camera
*
* @param width surface的宽
* @param height surface的高
*/
@SuppressLint("MissingPermission")
private void openCamera(int width, int height) {
CameraManager cameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : cameraManager.getCameraIdList()) {
//描述相机设备的属性类
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
//获取是前置还是后置摄像头
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//使用后置摄像头
if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map != null) {
//previewSize = CameraUtil.getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);
previewSize=new Size(mTextureView.getWidth(),mTextureView.getHeight());
mCameraId = cameraId;
}
}
}
mImageReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(),
ImageFormat.JPEG, 2);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mCameraHandler);
cameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler);
configureTransform(previewSize.getWidth(),previewSize.getHeight());
} catch (CameraAccessException r) {
}
}
/**
* 状态回调
*/
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//如果需要多个surface可以add多个
mPreviewBuilder.addTarget(previewSurface);
mPreviewBuilder.addTarget(mImageReader.getSurface());
//mPreviewBuilder.set(CaptureRequest.O, 270);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()), mStateCallBack, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onDisconnected(CameraDevice camera) {
camera.close();
}
@Override
public void onError(CameraDevice camera, int error) {
camera.close();
}
};
private CameraCaptureSession.StateCallback mStateCallBack = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
CaptureRequest request = mPreviewBuilder.build();
try {
//获取一个Image,one-shot
// session.capture(request, null, mCameraHandler);
//开启获取Image,repeat模式
session.setRepeatingRequest(request, null, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {}
};
/**
* 记得关掉Camera
*/
public void closeCamera() {
mCameraDevice.close();
}
}
通过这个类可以把摄像头预览绑定到textureView上,然后的话。记得申请权限。我是 事先申请好了的。
使用的话应该看得懂吧 先 new,再init传入textureView就好了。
然后旋转的设置在configureTransform里面。
关键语句
mPreviewBuilder.addTarget(previewSurface);
mPreviewBuilder.addTarget(mImageReader.getSurface());
//mPreviewBuilder.set(CaptureRequest.O, 270);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()), mStateCallBack, mCameraHandler);
这里要注意的是,加了两种surface。下面也要相应地加入包含这两种的list