Android Camera、Camera2详解
前言
Android5.0之前使用android.hardware包下的Camera类进行拍照、录视频等功能。5.0以后,新增了android.hardware.camera2包,利用新的机制、新的类进行拍照、录视频。
camera使用
摄像头权限自己去AndroidMainfest.xml配置就行了 直接上代码工具类 下面展示一些 代码 。
package com.tony.sonicinspection.ui.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import com.serenegiant.widget.Camera2Helper;
import com.tony.sonicinspection.App;
import com.tony.sonicinspection.Const;
import com.tony.sonicinspection.bean.eventbean.CameraPicPathEventBean;
import com.tony.sonicinspection.utils.ImageUtil;
import org.greenrobot.eventbus.EventBus;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
public class MyTextureView extends TextureView implements View.OnLayoutChangeListener {
public Camera mCamera;
private Context context;
private Camera.Parameters param;
private boolean isCanTakePicture = false;
int mWidth = 0;
int mHeight = 0;
int mDisplayWidth = 0;
int mDisplayHeight = 0;
int mPreviewWidth = 540;
int mPreviewHeight = 399;
public MyTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
if (null == mCamera) {
mCamera = Camera.open();
}
this.setSurfaceTextureListener(new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
param = mCamera.getParameters();
param.setPreviewFpsRange(4,10);
param.getPictureSize().width = mPreviewWidth;
param.getPictureSize().height = mPreviewHeight;
param.setPictureFormat(PixelFormat.JPEG);
param.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setParameters(param);
RectF previewRect = new RectF(0, 0, mPreviewWidth, mPreviewHeight);
RectF surfaceDimensions = new RectF(0, 0, mPreviewWidth, 960);
Matrix matrix = new Matrix();
matrix.setRectToRect(previewRect, surfaceDimensions, Matrix.ScaleToFit.FILL);
MyTextureView.this.setTransform(matrix);
int displayRotation = 0;
WindowManager windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
int rotation = windowManager.getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
displayRotation = 0;
break;
case Surface.ROTATION_90:
displayRotation = 90;
break;
case Surface.ROTATION_180:
displayRotation = 180;
break;
case Surface.ROTATION_270:
displayRotation = 270;
break;
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(0, info);
int orientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
orientation = (info.orientation - displayRotation + 360) % 360;
} else {
orientation = (info.orientation + displayRotation) % 360;
orientation = (360 - orientation) % 360;
}
mCamera.setParameters(param);
mCamera.setDisplayOrientation(orientation);
try {
mCamera.setPreviewTexture(surfaceTexture);
mCamera.startPreview();
isCanTakePicture = true;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
isCanTakePicture = true;
}
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
});
}
public void take() {
if (mCamera != null && isCanTakePicture) {
mCamera.takePicture(new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
}, null, mPictureCallback);
}
}
public void startPreview() {
if (mCamera != null && !isCanTakePicture) {
MyTextureView.this.setBackgroundDrawable(null);
mCamera.startPreview();
isCanTakePicture = true;
}
}
public void stopPreview() {
if (mCamera != null) {
mCamera.stopPreview();
isCanTakePicture = false;
}
}
public void releaseTextureView(){
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
isCanTakePicture = true;
}
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (mCamera != null) {
try {
Const.PHOTO_PATH = App.getInstance().generatePhotoPath();
File file = new File(Const.PHOTO_PATH);
file.createNewFile();
FileOutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
bitmap = ImageUtil.rotaingImageView(90, bitmap);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
bos.flush();
bos.close();
os.close();
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
mWidth = right - left;
mHeight = bottom - top;
}
}
Activity使用 ,这我是我项目中的一些代码 ,根据自己需要自行处理逻辑
@BindView(R.id.textureView_system_camera)
MyTextureView textureViewSystemCamera;
textureViewSystemCamera.startPreview();
textureViewSystemCamera.stopPreview();
@Subscribe(threadMode = ThreadMode.MAIN)
public void showPic(CameraPicPathEventBean cameraPicPathEventBean) {
if (cameraPicPathEventBean != null) {
showDialog(cameraPicPathEventBean.getData());
}
}
private void showDialog(byte[] data) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.popup_capture, null, false);
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setView(view).create();
TextView delete = (TextView) view.findViewById(R.id.tv_delete);
TextView save = (TextView) view.findViewById(R.id.tv_save);
Glide.with(this)
.load(data)
.into((ImageView) view.findViewById(R.id.captureImage));
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File file = new File(Const.PHOTO_PATH);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
getActivity().sendBroadcast(intent);
file.delete();
mainActivity.showToast(R.string.device_socket_capture_delete_success);
dialog.dismiss();
}
});
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainActivity.showToast("保存成功:" + Const.PHOTO_PATH);
curInspectionData = null;
curImageIndex = 0;
CommonUtils.updateGallery(mainActivity, Const.PHOTO_PATH);
dialog.dismiss();
}
});
dialog.show();
dialog.getWindow().setLayout((getActivity().getResources().getDisplayMetrics().widthPixels/4*3),LinearLayout.LayoutParams.WRAP_CONTENT);
}
camera2使用
直接上使用方法
@BindView(R.id.surfaceView_system_camera)
SurfaceView surfaceViewSystemCamera;
private SurfaceHolder mSurfaceHolder;
private CameraManager cameraManager;
private String cameraID;
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);
}
private CameraDevice mCameraDevice;
private Handler childHandler, mainHandler;
private ImageReader mImageReader;
private CameraCaptureSession mCameraCaptureSession;
private void initCameraView() {
mSurfaceHolder = surfaceViewSystemCamera.getHolder();
mSurfaceHolder.setKeepScreenOn(true);
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera2();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
}
});
}
private void initCamera2() {
HandlerThread handlerThread = new HandlerThread("Camera2");
handlerThread.start();
childHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(Looper.getMainLooper());
cameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;
mImageReader = ImageReader.newInstance(540, 399, ImageFormat.JPEG,1);
RectF previewRect = new RectF(0, 0, 540, 399);
RectF surfaceDimensions = new RectF(0, 0, 540, 960);
Matrix matrix = new Matrix();
matrix.setRectToRect(previewRect, surfaceDimensions, Matrix.ScaleToFit.FILL);
surfaceViewSystemCamera.setAnimationMatrix(matrix);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
try {
Image image = reader.acquireNextImage();
if (image != null) {
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
showDialog(bytes);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Const.PHOTO_PATH = App.getInstance().generatePhotoPath();
File file = new File(Const.PHOTO_PATH);
file.createNewFile();
FileOutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
bos.flush();
bos.close();
os.close();
image.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
},mainHandler);
cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
cameraManager.openCamera(cameraID, stateCallback, mainHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
takePreview();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
Toast.makeText(getActivity(), "摄像头开启失败", Toast.LENGTH_SHORT).show();
}
};
private void takePreview() {
try {
final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (null == mCameraDevice) return;
mCameraCaptureSession = session;
try {
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
CaptureRequest previewRequest = previewRequestBuilder.build();
mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(getActivity(), "配置失败", Toast.LENGTH_SHORT).show();
}
},childHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void takePicture() {
if (mCameraDevice == null) return;
final CaptureRequest.Builder captureRequestBuilder;
try {
captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
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 = getActivity().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();
}
}
if (mCameraDevice != null) {
mCameraDevice.close();
}
if (mCameraDevice != null) {
initCamera2();
} else {
initCameraView();
}
暂时就这么多,具体camera2原理的话: 链接: https://www.jianshu.com/p/0ea5e201260f
|