android Camera(一)

前言

在API级别21中不
推荐使用该类。我们建议[android.hardware.camera2](https://developer.android.com/reference/android/hardware/camera2/package-summary)对新应用程序使用新的API。

Camera类用于设置图像捕获设置,开始/停止预览,快照和检索帧以对视频进行编码。此类是Camera服务的客户端,该服务管理实际的相机硬件。

Camera1的使用

一、权限

要访问设备相机,您必须[Manifest.permission.CAMERA](https://developer.android.com/reference/android/Manifest.permission#CAMERA)在Android清单中声明该 权限。另外,请确保包含 清单元素,以声明应用程序使用的相机功能。例如,如果您使用相机和自动对焦功能,则清单应包括以下内容:

 
 
 

如果是6.0以上的手机还要动态申请权限,关于权限这块大家可以使用PermissionUtil全局管理。

二、相机的初始化

1.摄像头数量确定

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}
  1. 从中获取Camera的实例Camera.open(camera_Id);设置参数,getParameters()获取已有参数,如果有必要对返回的参数进行修改,然后调用setParameters();

 private void openCamera(int cameraType, int width, int height) {
            if (mCamera != null) {
                throw new RuntimeException("camera already initialized");
            }

            Camera.CameraInfo info = new Camera.CameraInfo();
            int numCameras = Camera.getNumberOfCameras();
            for (int i = 0; i < numCameras; i++) {
                Camera.getCameraInfo(i, info);
                if (info.facing == cameraType) {
                    CAMERA_ID = i;
                    mCamera = Camera.open(i);
                    break;
                }
            }
            if (mCamera == null) {
                throw new RuntimeException("unable to open camera");
            }

            final Camera.Parameters params = mCamera.getParameters();

      //  帧率设置
            final List supportedFpsRange = params.getSupportedPreviewFpsRange();
            final int[] max_fps = supportedFpsRange.get(supportedFpsRange.size() - 1);
            params.setPreviewFpsRange(max_fps[0], max_fps[1]);

            // 优化后的camera FPS设置方法
            int framerate = 30 * 1000;
            List rates = params.getSupportedPreviewFpsRange();
            int[] closetFramerate = rates.get(0);
            for (int i = 0; i < rates.size(); i++) {
                int[] rate = rates.get(i);
 
                int curDelta = Math.abs(rate[1] - framerate);
                int bestDelta = Math.abs(closetFramerate[1] - framerate);
                if (curDelta < bestDelta) {
                    closetFramerate = rate;
                } else if (curDelta == bestDelta) {
                    closetFramerate = closetFramerate[0] < rate[0] ? rate : closetFramerate;
                }
            }
            params.setPreviewFpsRange(closetFramerate[0], closetFramerate[1]);

            // 请求最近支持的预览大小
            final Camera.Size closestSize = getClosestSupportedSize(params.getSupportedPreviewSizes(), width, height);
            params.setPreviewSize(closestSize.width, closestSize.height);


            // 在Nexus7上请求最接近的图片大小以解决纵横比问题
            final Camera.Size pictureSize = getClosestSupportedSize(params.getSupportedPictureSizes(), width, height);
            params.setPictureSize(pictureSize.width, pictureSize.height);

            //根据设备方向旋转相机预览
            setRotation(params);
            mCamera.setParameters(params);
        }

3.调用setDisplayOrientation(int) 确保正确的预览和照片方向

 private final void setRotation(final Camera.Parameters params) {
       
            final CameraGLSurfaceView parent = mWeakParent.get();
            if (parent == null) return;

            final Display display = ((WindowManager) parent.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            final int rotation = display.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;
            }
            //获取摄像头是前置摄像头还是后置摄像头
            final Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(CAMERA_ID, info);
            int orientation = info.orientation;
            mIsFrontFace = (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
            if (mIsFrontFace) {    // front camera
                degrees = (orientation + degrees) % 360;
                degrees = (360 - degrees) % 360;  // reverse
            } else {  // back camera
                degrees = (orientation - degrees + 360) % 360;
            }

            // 设置方向
            mCamera.setDisplayOrientation(degrees);
            parent.mPreviewRotation = orientation;
            parent.mRotation = degrees;

        }

4.预览 ,调用startPreview(),开始更新预览图 ,将相机与SurfaceHolde或者texturer绑定Camera.setPreviewDisplay(surfaceHolder)
Camera.setPreviewTexture(surfaceTexture)

 /**
         * start camera preview
         *
         * @param width
         * @param height
         */
        private void startPreview(final int width, final int height, final SurfaceTexture surfaceTexture, int cameraId) {
            mViewWidth = width;
            mViewHeight = height;
            CAMERA_ID = cameraId;
            if (mCamera == null) {
                try {
                    openCamera(width, height);
                    final Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
                    CameraManager.getInstance().getFirstCameraPreviewListener().onBeforeStartPreviewWithChained(previewSize.width, previewSize.height, true);
                    byte[] preAllocedBuffer = new byte[previewSize.width * previewSize.height * ImageFormat.getBitsPerPixel(ImageFormat.NV21)];
                    mCamera.addCallbackBuffer(preAllocedBuffer);
                    mCamera.setPreviewCallbackWithBuffer(this);
                } catch (final RuntimeException e) {
                    if (mCamera != null) {
                        mCamera.release();
                        mCamera = null;
                    }
                }

                if (mCamera != null) {
                    try {
                        mCamera.startPreview();
                    } catch (Exception e) {

                    }
                    CameraManager.getInstance().getFirstCameraPreviewListener().onAfterStartPreviewWithChained();
                }
            }

            if (surfaceTexture != null) {
                setPreviewTexture(surfaceTexture);
            }
        }


        private void setPreviewTexture(SurfaceTexture surfaceTexture) {
            if (mCamera != null && surfaceTexture != null) {
                mSurfaceTexture = surfaceTexture;
                try {
                    mCamera.setPreviewTexture(surfaceTexture);
                } catch (IOException e) {
                }
            }
        }

5.获取实时NV21格式的数据
mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {

}

});
onPreview回调回来的data就是实时的帧数据,我们可以对数据进行处理,比如加美颜等等。

你可能感兴趣的:(android Camera(一))