Android Camera2 调用摄像头显示预览与拍照
CameraFragment.java
package com.example.customcamaratest;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Camera;
import android.graphics.ImageFormat;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
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.media.Image;
import android.media.ImageReader;
import android.os.Looper;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class CameraFragment extends Fragment {
public static final int REQUEST_CAMERA_CODE = 100;
public static final String PACKAGE = "package";
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 SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private ImageView iv_show;
private ImageView mCapture;
private CameraManager mCameraManager;
private Handler childHandler, mainHandler;
private String mCameraID;
private ImageReader mImageReader;
private CameraCaptureSession mCameraCaptureSession;
private CameraDevice mCameraDevice;
private Image image;
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
takePreview();
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
if (null != mCameraDevice){
mCameraDevice.close();
CameraFragment.this.mCameraDevice = null;
}
}
@Override
public void onError(CameraDevice cameraDevice, int i) {
Toast.makeText(getContext(), "摄像头开启失败", Toast.LENGTH_SHORT).show();
}
};
public static CameraFragment newInstance(){
return new CameraFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_camera2,container,false);
initView(root);
initListener();
return root;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
}
private void initView(View root){
iv_show = (ImageView)root.findViewById(R.id.iv_show_camera2);
mSurfaceView = (SurfaceView)root.findViewById(R.id.surface_view_camera2);
mCapture = (ImageView)root.findViewById(R.id.capture);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setKeepScreenOn(true);
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
initCamera2();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (null != mCameraDevice){
mCameraDevice.close();
CameraFragment.this.mCameraDevice = null;
}
}
});
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void initCamera2(){
HandlerThread handlerThread = new HandlerThread("Camera2");
handlerThread.start();
childHandler = new Handler(handlerThread.getLooper());
mainHandler = new Handler(Looper.getMainLooper());
mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;
mImageReader = ImageReader.newInstance(1080,1920, ImageFormat.JPEG,1);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
image = imageReader.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);
image.close();
}
}
},mainHandler);
mCameraManager = (CameraManager)getContext().getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.CAMERA},REQUEST_CAMERA_CODE);
}else {
mCameraManager.openCamera(mCameraID,stateCallback,mainHandler);
}
}catch (CameraAccessException e){
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CAMERA_CODE){
if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
try {
mCameraManager.openCamera(mCameraID,stateCallback,mainHandler);
}catch (CameraAccessException e){
e.printStackTrace();
}catch (SecurityException e){
e.printStackTrace();
}
}else {
Toast.makeText(getContext(),"Permission Denied",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(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(getContext(), "配置失败", Toast.LENGTH_SHORT).show();
}
},childHandler);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private void takePicture(){
if (mCameraDevice == null)return;
final CaptureRequest.Builder captureResquestBuilder;
try{
captureResquestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureResquestBuilder.addTarget(mImageReader.getSurface());
captureResquestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureResquestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
captureResquestBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
CaptureRequest mCaptureRequest = captureResquestBuilder.build();
mCameraCaptureSession.capture(mCaptureRequest,null,childHandler);
}catch (CameraAccessException e){
e.printStackTrace();
}
}
private void initListener(){
mCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
takePicture();
}
});
}
}
MainActivity.java
package com.example.customcamaratest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CameraFragment cameraFragment = (CameraFragment)getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (cameraFragment ==null){
cameraFragment = CameraFragment.newInstance();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.contentFrame,cameraFragment);
fragmentTransaction.commit();
}
}
}