Android Camera API和Android版本一样,也是碎片化比较严重,所以Google官方推出了CameraView ,提供给开发者参考和学习,现在最新的可以使用Jetpack CameraX 来开发,大大简化了开发的复杂度。本系列从Camera1->Camera2->CameraView->CameraX,一步步讲解Camera的进化过程,本篇先介绍Camera1的使用。
相机开发的流程:
检测设备摄像头,打开相机
创建预览画面,显示实时预览画面
设置相机参数,进行拍照监听
监听中,保存图片资源或者直接操作原始数据
释放相机资源
上面的是基本的相机开发流程,不同的Camera API在实现上会有不同,整体流程上还是统一的。
Camera1使用 权限声明 1 2 3 4 5 <uses-feature android:name ="android.hardware.camera" android:required ="true" /> <uses-permission android:name ="android.permission.CAMERA" />
相机必须声明CAMERA
权限,在Android6.0上,你还需要在代码中动态申请权限
1 2 ActivityCompat.requestPermissions(this , new String []{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
开发流程 下图是一个开发流程的导览:
打开相机
该方法的系统源码实现
1 2 3 4 5 6 7 8 9 10 11 public static Camera open () { int numberOfCameras = getNumberOfCameras(); CameraInfo cameraInfo = new CameraInfo (); for (int i = 0 ; i < numberOfCameras; i++) { getCameraInfo(i, cameraInfo); if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { return new Camera (i); } } return null ; }
这里会检查可用的摄像头,默认使用的CameraInfo.CAMERA_FACING_BACK
后置摄像头
创建预览画面 这里使用的是SurfaceView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private SurfaceView mSurfaceView;private SurfaceHolder mSurfaceHolder;... mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.addCallback(new SurfaceHolder .Callback() { @Override public void surfaceCreated (SurfaceHolder holder) { ... startPreview(); } @Override public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed (SurfaceHolder holder) { releaseCamera(); } }); ... private void startPreview () { try { mCamera.setPreviewDisplay(mSurfaceHolder); setCameraDisplayOrientation(); mCamera.startPreview(); startFaceDetect(); } catch (Exception e) { e.printStackTrace(); } }
设置预览的时候,可以设置setPreviewCallback
监听预览数据的回调
1 void onPreviewFrame (byte [] data, Camera camera) ;
设置相机参数 设置相机参数后,需要重新启动预览,这边在初始化的时候,已经设置好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private void initParameters (final Camera camera) { mParameters = camera.getParameters(); mParameters.setPreviewFormat(ImageFormat.NV21); if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if (isSupportFocus(Camera.Parameters.FOCUS_MODE_AUTO)) { mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } setPreviewSize(); setPictureSize(); camera.setParameters(mParameters); }
Camera.Parameters可以设置的参数非常多,这里就介绍几个比较常用的
1.setFocusMode 设置对焦模式
FOCUS_MODE_AUTO:自动对焦
FOCUS_MODE_INFINITY:无穷远
FOCUS_MODE_MACRO:微距
FOCUS_MODE_FIXED:固定焦距
FOCUS_MODE_EDOF:景深扩展
FOCUS_MODE_CONTINUOUS_PICTURE:持续对焦(针对照片)
FOCUS_MODE_CONTINUOUS_VIDEO:(针对视频)
2.setPreviewSize 设置预览图片大小
支持的格式:
ImageFormat.NV16
ImageFormat.NV21
ImageFormat.YUY2
ImageFormat.YV12
ImgaeFormat.RGB_565
ImageFormat.JPEG 如果不设置,默认返回NV21的数据
4.setPictureSize 设置保存图片的大小
设置保存图片的格式,格式和setPreviewFormat
一样
6.setDisplayOrientation 设置相机预览画面旋转的角度,degress取值0,90,180,270
7.setPreviewDisplay 设置实时预览SurfaceHolder
8.setPreviewCallback 监听相机预览数据回调
9.setParameters 设置相机的Parameters 其他一些设置,大家可以查看Android文档进行相应的设置
设置方向 设置相机的预览方向,orientation比较详细的介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 private void setCameraDisplayOrientation () { Camera.CameraInfo cameraInfo = new Camera .CameraInfo(); Camera.getCameraInfo(mCameraId, cameraInfo); int rotation = getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0 ; switch (rotation) { case Surface.ROTATION_0: degrees = 0 ; break ; case Surface.ROTATION_90: degrees = 90 ; break ; case Surface.ROTATION_180: degrees = 180 ; break ; case Surface.ROTATION_270: degrees = 270 ; break ; } int result; if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (cameraInfo.orientation + degrees) % 360 ; result = (360 - result) % 360 ; } else { result = (cameraInfo.orientation - degrees + 360 ) % 360 ; } mOrientation = result; mCamera.setDisplayOrientation(result); }
拍照 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void takePicture () { if (null != mCamera) { mCamera.takePicture(new Camera .ShutterCallback() { @Override public void onShutter () { } }, new Camera .PictureCallback() { @Override public void onPictureTaken (byte [] data, Camera camera) { } }, new Camera .PictureCallback() { @Override public void onPictureTaken (final byte [] data, Camera camera) { mCamera.startPreview(); } }); } }
takePicture的源码实现:
1 2 3 4 public final void takePicture (ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { takePicture(shutter, raw, null , jpeg); }
shutter(ShutterCallback):快门按下后的回调
raw(PictureCallback):raw图像数据
jpeg(PictureCallback):jpeg图像生成以后的回调
释放相机资源 在使用完成后,onPause或者onDestory中进行相机资源的释放
1 2 3 4 5 6 7 8 9 private void releaseCamera () { if (null != mCamera) { mCamera.stopPreview(); mCamera.stopFaceDetection(); mCamera.setPreviewCallback(null ); mCamera.release(); mCamera = null ; } }
stopPreview:停止预览
release:释放资源
Camera1的开发上,还是相对比较简单的,需要定制的功能项比较少,下面一篇开始介绍Camera2的使用。 文章中涉及到的代码
参考