Android开发笔记

Camera 、Camera2 预览 和 二次预览

2019-03-12  本文已影响0人  天敦敦

1、创建CameraApiInterface,供Activity和Camera实现

public interface CameraApiInterface {

  interface CameraNeed {

      <V extends View>  void  init (Context context, V view , CameraCallBack callBack);

      void openCamera (int index);

      void closeCamera ();

  }

  interface CameraCallBack {

      void frameChange (byte[] data, int width, int height);

  }
}

2、编写Camera Api的调用

public class Camera1Api implements CameraApiInterface.CameraNeed, SurfaceHolder.Callback,
        Camera.PreviewCallback {

    private Context mContext;
    private SurfaceView mSurfaceView;
    private CameraApiInterface.CameraCallBack mCallBack;
    private Camera mCamera;
    private int mCameraIndex;
    /**
     * 预览尺寸
     */
    private Size mSize = new Size(1280,720);
    private boolean mCameraOpen = false;


    @Override
    public <V extends View> void init(Context context, V view, CameraApiInterface.CameraCallBack callBack) {

        mCallBack = callBack;
        mContext = context;
        mSurfaceView = (SurfaceView) view;

    }

    @Override
    public void openCamera(int index) {

        mCameraIndex = index;
        mSurfaceView.getHolder().addCallback(this);

    }

    @Override
    public void closeCamera() {
        if ( mSurfaceView != null ) {
            mSurfaceView.getHolder().removeCallback (this);
        }
        if ( mCamera != null ) {
            mCamera.setPreviewCallback ( null );
            mCamera.stopPreview ();
            mCamera.release ();
            mCamera = null;
            mCameraOpen = false;
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = getCameraInstance();
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
            mCamera.setPreviewCallback(this);
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        int rotation = getDisplayOrientation(); //获取当前窗口方向
        mCamera.setDisplayOrientation(rotation); //设定相机显示方向
        try {
            if (null != mCamera) {
                mCamera.setPreviewDisplay(holder);
                if (mCameraOpen) {
                    mCamera.startPreview();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (holder!= null) {
            holder.removeCallback(this);
        }
    }

    private android.hardware.Camera getCameraInstance(){
        android.hardware.Camera c = null;
        try {
            c = android.hardware.Camera.open(mCameraIndex);
            android.hardware.Camera.Parameters p = c.getParameters();
            p.setPreviewFormat( ImageFormat.NV21);
            int imageWidth = mSize.getWidth();
            int imageHeight = mSize.getHeight();
            p.setPreviewSize(imageWidth, imageHeight);
            p.setPictureFormat( ImageFormat.NV21);
            p.setPictureSize(imageWidth, imageHeight);
            p.setZoom(0);
            int frameRate = 30;
            p.setPreviewFrameRate(frameRate);
            int cameraRotation = 0;
            p.setRotation(cameraRotation);
            c.setParameters ( p );
        } catch(Exception e){
            e.printStackTrace();
        }
        return c;
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        mCallBack.frameChange(data, camera.getParameters().getPictureSize().width,
                camera.getParameters().getPictureSize().height);
    }

    // 获取当前窗口管理器显示方向
    private int getDisplayOrientation(){
        WindowManager windowManager = ((Activity)mContext).getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        int rotation = display.getRotation();
        int degrees = 0;
        switch (rotation){
            case Surface.ROTATION_0:
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        android.hardware.Camera.CameraInfo camInfo = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(
                android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);
        return (camInfo.orientation - degrees + 360) % 360;
    }
}

3、Activity 调用

    public class CameraShowActivity extends Activity implements CameraApiInterface.CameraCallBack {

        CameraApiInterface.CameraNeed cameraNeed;
        private YuvGLRenderer mGLRenderer;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_camera_show);

            GLSurfaceView glSurfaceView = findViewById(R.id.gl_surface_view);
            mGLRenderer = new YuvGLRenderer(glSurfaceView, 1280, 720);
            SurfaceView surfaceView = findViewById(R.id.surface_view);

            cameraNeed = new Camera1Api();
            cameraNeed.init(this, surfaceView, this);

        }

        @Override
        protected void onResume() {
            super.onResume();
            cameraNeed.openCamera(1);
        }

        @Override
        protected void onPause() {
            super.onPause();
            cameraNeed.closeCamera();
        }

        @Override
        public void frameChange(byte[] data, int width, int height) {
            mGLRenderer.nv21Update(data, width, height);
        }

    }

4、xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="1280px"
        android:layout_height="720px" />

    <android.opengl.GLSurfaceView
        android:id="@+id/gl_surface_view"
        android:layout_width="1280px"
        android:layout_height="720px" />

</LinearLayout>

5、Camera2 预览

public class Camera2Api implements CameraApiInterface.CameraNeed, SurfaceHolder.Callback {

    private SurfaceHolder mSurfaceHolder;

    private ImageReader mImageReader;
    private CameraCaptureSession mCameraCaptureSession;
    private CameraDevice mCameraDevice;
    private Context mContext;
    private CameraApiInterface.CameraCallBack mCameraCallBack;
    private int mCameraIndex;
    private int mWidth = 1280;
    private int mHeight = 720;

    private Handler mChildHandler;

    @Override
    public <V extends View> void init(Context context, V view, CameraApiInterface.CameraCallBack callBack) {
        mContext = context;
        mCameraCallBack = callBack;

        mSurfaceHolder = ((SurfaceView)view).getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
    }

    @Override
    public void openCamera(int index) {
        mCameraIndex = index;
        mSurfaceHolder.addCallback(this);

    }

    @Override
    public void closeCamera() {
        if (mSurfaceHolder != null) {
            mSurfaceHolder.removeCallback(this);
        }
        if (null != mCameraDevice) {
            mCameraDevice.close();
            mCameraDevice = null;
        }

        if (null != mCameraCaptureSession) {
            mCameraCaptureSession.close();
            mCameraCaptureSession = null;
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        initCamera();
    }

    @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;
        }
    }

    @SuppressLint("MissingPermission")
    private void initCamera() {
        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        mChildHandler = new Handler(handlerThread.getLooper());
        Handler mainHandler = new Handler(mContext.getMainLooper());
        mImageReader = ImageReader.newInstance(mWidth, mHeight,
                ImageFormat.YUV_420_888, 1);
        mImageReader.setOnImageAvailableListener(new ImageReader
                .OnImageAvailableListener() { // 可以在这里处理拍照得到的临时照片 例如,写入本地
            @Override
            public void onImageAvailable(ImageReader reader) {


            }
        }, mainHandler);
        CameraManager mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        try {
            mCameraManager.openCamera(String.valueOf(mCameraIndex), mStateCallback, mainHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 摄像头创建监听
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) { // 打开摄像头
            mCameraDevice = camera;
            // 开启预览
            createPreview();
        }

        @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(mContext, "摄像头开启失败", Toast.LENGTH_SHORT).show();
        }
    };


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void createPreview() {
        try {
            // 创建预览需要的CaptureRequest.Builder
            final CaptureRequest.Builder previewRequestBuilder = mCameraDevice
                    .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            // 将SurfaceView的surface作为CaptureRequest.Builder的目标
            previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
//            previewRequestBuilder.addTarget(mImageReader.getSurface());

            // 创建CameraCaptureSession,该对象负责管理处理预览请求
            mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface()),
                    new CCSStateCallback(previewRequestBuilder),
                    mChildHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    class CCSStateCallback extends CameraCaptureSession.StateCallback {

        private CaptureRequest.Builder previewRequestBuilder;

        CCSStateCallback(CaptureRequest.Builder previewRequestBuilder) {

            this.previewRequestBuilder = previewRequestBuilder;

        }

        @Override
        public void onConfigured(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, mChildHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(CameraCaptureSession session) {
            Toast.makeText(mContext, "配置失败", Toast.LENGTH_SHORT).show();
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读