Android 使用Camera2 调用摄像头显示预览与拍照

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;//摄像头Id 0 为 后 1 为前
    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
        mSurfaceView = (SurfaceView)root.findViewById(R.id.surface_view_camera2);
        mCapture = (ImageView)root.findViewById(R.id.capture);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
        //mSurfaceView添加回调
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                //初始化camera
                initCamera2();
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                //释放camera资源
                if (null != mCameraDevice){
                    mCameraDevice.close();
                    CameraFragment.this.mCameraDevice = null;
                }
            }
        });
    }

    /**
     * 初始化Camera2
     */
    @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) {
//                if (image != null){
//                    image = null;
//                }
                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{
            //创建预览需要的CaptureRequest.Builder
            final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            //将SurfceView的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(getContext(), "配置失败", Toast.LENGTH_SHORT).show();
                }
            },childHandler);
        }catch (CameraAccessException e){
            e.printStackTrace();
        }
    }

    private void takePicture(){
        if (mCameraDevice == null)return;
        //创建拍照所需要的CaptureRequestBuilder
        final CaptureRequest.Builder captureResquestBuilder;
        try{
            captureResquestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            //将imageReader的surface作为CaptureRequest.Builder的目标
            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();
        }
    }
}
原文地址:https://www.cnblogs.com/PythonFCG/p/13860156.html