Android camera2 使用方法
2021-10-28 本文已影响0人
飞不起的小鸟
private TextureView textureview;
private Camera2 camera;
protected void onCreate(@Nullable Bundle savedInstanceState) {
textureview = findViewById(R.id.textureview);
//进入这个页面之前要申请相机权限
camera = new Camera2(textureview, this, new Camera.OnCameraListener() {
@Override
public void onCall(Bitmap bitmap) {
//拍照的bitmap
}
});
findViewById(R.id.btn).setOnClickListener(new OnClickLimitListener() {
@Override
public void click(View v) {
Log.d(TAG, "click: 拍照");
camera.takePic();
}
});
}
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.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.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
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.Size;
import android.view.Surface;
import android.view.TextureView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Camera {
private Activity mActivity;
private TextureView mTextureView;
private HandlerThread handlerThread;
private CameraManager mCameraManager;
private ImageReader mImageReader;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCameraCaptureSession;
private String mCameraId;
private CameraCharacteristics mCameraCharacteristics;
private int mCameraSensorOrientation;
private boolean canTakePic;
private Handler mCameraHandler;
private Size mPreviewSize;
private Size mSavePicSize;
private ImageReader.OnImageAvailableListener onImageAvailableListener;
private CameraCaptureSession.CaptureCallback mCaptureCallBack;
public Camera(TextureView textureView, Activity activity, OnCameraListener listener) {
mTextureView = textureView;
mActivity = activity;
handlerThread = new HandlerThread("CameraThread");
handlerThread.start();
mCameraHandler = new Handler(handlerThread.getLooper());
mPreviewSize = new Size(720, 1280);
mSavePicSize = new Size(720, 1280);
onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
byte[] byteArray = new byte[byteBuffer.remaining()];
byteBuffer.get(byteArray);
image.close();
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
listener.onCall(bitmap);
}
};
mCaptureCallBack = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
canTakePic = true;
}
};
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
initInfo();
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
release();
return true;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
});
}
public void release() {
if (mCameraCaptureSession != null) {
mCameraCaptureSession.close();
mCameraCaptureSession = null;
}
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
if (mImageReader != null) {
mImageReader.close();
mImageReader = null;
}
}
private void initInfo() {
try {
mCameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
String[] cameraIdList = mCameraManager.getCameraIdList();
if (cameraIdList == null || cameraIdList.length == 0) {
Toast.makeText(mActivity, "没有可用相机", Toast.LENGTH_SHORT).show();
return;
}
for (int i = 0; i < cameraIdList.length; i++) {
String id = cameraIdList[i];
CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(id);
Integer integer = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
if (integer == CameraCharacteristics.LENS_FACING_BACK ) {
mCameraId = id;
mCameraCharacteristics = cameraCharacteristics;
}
}
mCameraSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
StreamConfigurationMap configurationMap = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (configurationMap != null) {
Size[] savePicSize = configurationMap.getOutputSizes(ImageFormat.JPEG);
Size[] previewSize = configurationMap.getOutputSizes(SurfaceTexture.class);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
boolean exchange = exchangeWidthAndHeight(rotation, mCameraSensorOrientation);
mSavePicSize = getBestSize(
exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
exchange ? mSavePicSize.getHeight() : mSavePicSize.getWidth(),
exchange ? mSavePicSize.getWidth() : mSavePicSize.getHeight(),
Arrays.asList(savePicSize));
mPreviewSize = getBestSize(
exchange ? mPreviewSize.getHeight() : mPreviewSize.getWidth(),
exchange ? mPreviewSize.getWidth() : mPreviewSize.getHeight(),
exchange ? mTextureView.getHeight() : mTextureView.getWidth(),
exchange ? mTextureView.getWidth() : mTextureView.getHeight(),
Arrays.asList(previewSize));
mTextureView.getSurfaceTexture().setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
mImageReader = ImageReader.newInstance(mSavePicSize.getWidth(), mSavePicSize.getHeight(), ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(onImageAvailableListener, mCameraHandler);
openCamera();
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(mActivity, "没有相机权限!", Toast.LENGTH_SHORT).show();
return;
}
try {
mCameraManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
createCaptureSession(camera);
}
@Override
public void onDisconnected(CameraDevice camera) {
}
@Override
public void onError(CameraDevice camera, int error) {
}
}, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCaptureSession(CameraDevice cameraDevice) {
try {
CaptureRequest.Builder captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
Surface surface = new Surface(mTextureView.getSurfaceTexture());
captureRequest.addTarget(surface);
captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Toast.makeText(mActivity, "开启预览会话失败!", Toast.LENGTH_SHORT).show();
}
@Override
public void onConfigured(CameraCaptureSession session) {
mCameraCaptureSession = session;
try {
session.setRepeatingRequest(captureRequest.build(), mCaptureCallBack, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private boolean exchangeWidthAndHeight(int displayRotation, int sensorOrientation) {
boolean exchange = false;
if (displayRotation == Surface.ROTATION_0 || displayRotation == Surface.ROTATION_180) {
if (sensorOrientation == 90 || sensorOrientation == 270) {
exchange = true;
} else if (sensorOrientation == 0 || sensorOrientation == 180) {
exchange = true;
}
}
return exchange;
}
private Size getBestSize(int targetWidth, int targetHeight, int maxWidth, int maxHeight, List<Size> sizeList) {
List<Size> bigEnough = new ArrayList<>();
List<Size> notBigEnough = new ArrayList<>();
for (Size size : sizeList) {
if (size.getWidth() <= maxWidth && size.getHeight() <= maxHeight && size.getWidth() == size.getHeight() * targetWidth / targetHeight) {
if (size.getWidth() >= targetWidth && size.getHeight() >= targetHeight)
bigEnough.add(size);
else {
notBigEnough.add(size);
}
}
}
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
}
return sizeList.get(0);
}
/**
* 拍照
*/
public void takePic() {
if (mCameraDevice == null || !mTextureView.isAvailable() || !canTakePic) {
return;
}
if (mCameraDevice != null) {
try {
CaptureRequest.Builder captureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequest.addTarget(mImageReader.getSurface());
captureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
captureRequest.set(CaptureRequest.JPEG_ORIENTATION, mCameraSensorOrientation);
mCameraCaptureSession.capture(captureRequest.build(), null, mCameraHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(mActivity, "拍照异常!", Toast.LENGTH_SHORT).show();
}
}
}
class CompareSizesByArea implements Comparator<Size> {
@Override
public int compare(Size size1, Size size2) {
return java.lang.Long.signum(
size1.getWidth() * size1.getHeight() -
size2.getWidth() * size2.getHeight());
}
}
public interface OnCameraListener {
void onCall(Bitmap bitmap);
}
}