Android camera2

240人阅读 评论(0) 收藏 举报

这里写图片描述
布局只用到了SurfaceView跟Button。有的手机黑屏,需要给SurfaceViewHolder设置FixedSize。

public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private SurfaceView mCameraSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    //相机相关代码,三个必须的
    private CameraManager mCameraManager;
    private CameraDevice mCameraDevice;
    private CameraCaptureSession mCameraCaptureSession;
    //阻止相机关闭前退出app
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
    //摄像头id  0:后摄像头 1:前摄像头
    private static final String mCameraId = "" + CameraCharacteristics.LENS_FACING_FRONT;
    //opencamera方法中需要ImageReader和handler
    private ImageReader mImageReader;
    private Handler mHandler;
    private Size previewsize;
    private ImageReader.OnImageAvailableListener mImageAvailableListenter = new ImageReader.OnImageAvailableListener() {
        @SuppressLint("NewApi")
        @Override
        public void onImageAvailable(ImageReader reader) {
            mCameraDevice.close();
            //这里获取到图片数据
           ……

        }
    };

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

    /**
     * Max preview width that is guaranteed by Camera2 API
     */
    private static final int MAX_PREVIEW_WIDTH = 1920;

    /**
     * Max preview height that is guaranteed by Camera2 API
     */
    private static final int MAX_PREVIEW_HEIGHT = 1080;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        initView();
        initSurfaceView();
    }

    private void initView() {
        mCameraSurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
        mFrameIv = (ImageView) findViewById(R.id.frame_imageview);
        mTakePhotoBt = (Button) findViewById(R.id.takephoto_bt);
        mFocusView = findViewById(R.id.focus_index);

    }

    private void initSurfaceView() {
        mCameraSurfaceView.setBackgroundColor(TRIM_MEMORY_BACKGROUND);
        mSurfaceHolder = mCameraSurfaceView.getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
        mSurfaceHolder.addCallback(this);
    }


    @Override
    protected void onResume() {
        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
//这里可以设置也可以不设置,使用过程中发现有的手机不设置这个时会出现黑屏现象
        mSurfaceHolder.setFixedSize(800, 600);
        super.onResume();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

 //不设置holder的Fixedsize时设置initCamera2(mCameraSurfaceView.getWidth(),mCameraSurfaceView.getHeight());
            initCamera2(800, 600);         

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @SuppressLint("NewApi")
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCameraDevice != null) {
            mCameraDevice.close();
        }
    }

    @SuppressLint("NewApi")
    private void initCamera2(int width, int height) {
        if (checkCameraPermission()) {
            try {
                String camerId = mCameraManager.getCameraIdList()[0];
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(camerId);
                StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                previewsize = map.getOutputSizes(SurfaceTexture.class)[0];
                HandlerThread handlerthread = new HandlerThread("Camera2");
                handlerthread.start();
                mHandler = new Handler(handlerthread.getLooper());
                mImageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG,  /*maxImages*/2);
                mImageReader.setOnImageAvailableListener(mImageAvailableListenter, mHandler);
                mCameraManager.openCamera(mCameraId, mCameraDeviceCallBack, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        } else {
            finish();
            return;
        }

    }

    private boolean checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(getApplicationContext(),
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(getApplicationContext(), "没有相机权限", Toast.LENGTH_LONG).show();
            return false;
        } else {
            return true;
        }
    }


    @SuppressLint("NewApi")
    private CameraDevice.StateCallback mCameraDeviceCallBack = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            try {
                //当相机被打开,该方法将被回调,因此再这里进行相机预览设置
                mCameraOpenCloseLock.release();
                mCameraDevice = camera;
                //开启预览
                createCameraCaptureSession();
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCameraOpenCloseLock.release();
            if (mCameraDevice != null) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
        }


        @Override
        public void onError(@NonNull CameraDevice camera, int error) {

        }
    };
    private CaptureRequest.Builder mCaptureRequestBuilder;

    @SuppressLint("NewApi")//开启预览
    private void createCameraCaptureSession() throws CameraAccessException {
        //创建预览需要的CaptureRequest.Builder
        mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        //添加surface为CaptureRequest.Builder的目标
        mCaptureRequestBuilder.addTarget(mSurfaceHolder.getSurface());
        //创建CameraCaptureSession该对象负责管理处理预览请求和拍照请求
        mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(),
                mImageReader.getSurface()), mSessionPreviewStateCallback, mHandler);
    }

    @SuppressLint("NewApi")
    private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            try {
                //摄像头已经准备好,开始显示预览
                mCameraCaptureSession = session;
                //自动对焦
                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                //打开闪光灯
//                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                //显示预览
                CaptureRequest previewRequest = mCaptureRequestBuilder.build();
                mCameraCaptureSession.setRepeatingRequest(previewRequest, null, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Log.e("Camera2", "相机预览失败");
        }
    };
//


    public void takePicture(View view) {
        takePic();
    }

    @SuppressLint("NewApi")
    public void takePic() {
        if (mCameraDevice == null) return;
        // 创建拍照需要的CaptureRequest.Builder
        try {
            // 将imageReader的surface作为CaptureRequest.Builder的目标
            mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
            // 自动对焦
            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 自动曝光
            mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            // 获取手机方向
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            // 根据设备方向计算设置照片的方向
            mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            //拍照
            CaptureRequest mCaptureRequest = mCaptureRequestBuilder.build();
            mCameraCaptureSession.capture(mCaptureRequest, null, mHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

}
查看评论

android camera2 的基础应用

之前一直用android camera,但现在市面上新出的手机都是支持camera2的,项目要求也是运用camera2,于是自己学习了下,将一些知识点罗列出来,以供复习和大家参考。 一、camera...
  • zhangpengzp
  • zhangpengzp
  • 2017-12-07 19:12:49
  • 306

android相机

  • 2017年08月30日 13:17
  • 23.34MB
  • 下载

Android Camera2相机封装讲解(含Demo)

Android 5.0对拍照API进行了全新的设计,新增了全新设计的Camera v2 API,这些API不仅大幅提高了Android系统拍照的功能,还能支持RAW照片输出,甚至允许程序调整相机的对焦...
  • Android_Technology
  • Android_Technology
  • 2017-07-26 16:20:14
  • 3711

android 自定义相机Camera2

上一篇文章我们已经运用Camera自定义了一个相机,今天我们就用Camera2自定义一个相机。Camera2是android5.0新增的api,Camera2与Camera差别比较大,采用了全新的模式...
  • qq_38416326
  • qq_38416326
  • 2017-05-03 16:27:17
  • 3756

Android camera2 之我的理解

参考:http://www.jianshu.com/p/060016ba01ff 参考:http://wiki.jikexueyuan.com/project/android-actual-co...
  • lushuo9156
  • lushuo9156
  • 2017-02-27 13:30:51
  • 793

Android 笔记 关于camera2使用的一些问题

camera2使用的一些问题、这几天一直在研究camera2,但是实际测试的时候发现一些很令人头疼的问题。分辨率的设置。我希望能设置不同的预览分辨率,然后对应不同的照片分辨率,其实主要就两种,一个是1...
  • super_zq
  • super_zq
  • 2016-09-09 13:50:38
  • 3592

Android.Camera2相机超详细讲解

Android.Camera2相机超详细讲解在API21中Google就发布了Camera2类来取代Camera类,那么这个Camera2类到底改变了那些地方呢,我们来看看...
  • vinicolor
  • vinicolor
  • 2016-03-27 17:21:36
  • 23523

android camera2配置流程

android camera2配置流程
  • fireness
  • fireness
  • 2016-02-05 10:46:34
  • 1783

Android Camera2 API和拍照与录像过程

简介: Android 5.0开始出现了新的相机Camera 2 API,用来替代以前的camera api。 Camera2 API不仅提高了android系统的拍照性能,还...
  • hexingen
  • hexingen
  • 2018-02-08 15:17:20
  • 712

Android自定义Camera2 拍照,用SurfaceView预览。

布局文件不用说了,就它了SurfaceView。其他花里古哨的布局,自己想着加吧! ...
  • qq_28779083
  • qq_28779083
  • 2017-12-29 10:42:30
  • 362
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 38万+
    积分: 6698
    排名: 4412
    博客专栏
    最新评论