Camera API笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jason_Lewis/article/details/86677041

说明

最近在学习音视频相关知识,把一些需要注意的点记录一下方便后续查阅,可能有些翻译不准确,如有错误欢迎指正,后面不再说明。以下内容都是摘自官方API文档。

正文

如果要访问设备的相机,首先要添加Manifest.permission.CAMERA权限,如果是6.0以上不要忘记权限申请,还有就是要包含 清单元素声明在你的应用中使用的相机功能。例如,你使用了相机及自动对焦功能,你的清单文件应该包含下面几项:

<uses-permission android:name="android.permission.CAMERA" />
 <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />

使用相机类拍照的步骤如下

  1. 使用open(int)方法获取一个Camera实例
  2. 使用getParameters()方法获取现有(默认)的设置
  3. 如有必要,修改返回的 Camera.Parameters 对象并调用 setParameters(Camera.Parameters)方法
  4. 调用 setDisplayOrientation(int) 方法保证正确的预览方向
  5. 重要:给setPreviewDisplay(SurfaceHolder)方法传一个完全初始化的SurfaceHolder。没有surface,相机将不能开始预览。
  6. 重要:调用 startPreview() 方法开始更新预览显示。在你能够拍照之前必须要先开始预览。
  7. 当你想要通过调用 takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback) 方法来捕获一张照片时。等待回调返回真实的图像数据。
  8. 拍照后预览显示将停止,如果想拍更多的照片,请再次调用startPreview() 方法
  9. 调用 stopPreview() 停止更新预览显示
  10. 重要:调用 release() 方法释放相机以供其他应用使用。应用应该在Activity.onPause()方法立即释放相机( 并在 Activity.onResume()方法重新创建).

快速切换到录像模式步骤如下

  1. 跟上面拍照步骤一样获取一个相机实例并开始预览
  2. 调用 unlock() 方法来允许媒体进程访问相机
  3. 将相机实例传递给MediaRecorder.setCamera(Camera)
  4. 录制完成后,调用 reconnect() 方法重新获取并锁定相机
  5. 如果需要,请重新开始预览拍摄更多的照片和视频
  6. 跟拍照描述的那样调用 stopPreview() 和 release()

Camera类非线程安全,适用于事件线程。大多数长时间运行的操作(如预览、对焦、拍照等)都是异步发生的,并在需要时调用回调。回调会在调用 open(int) 的事件线程中调用。一定不要同时在多个线程中调用Camera类的方法。

检查相机状态的一些方法

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

2访问相机

要访问主摄像头,请使用Camera.open()方法并确保捕获任何异常,如下面的代码所示:

/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    } catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

警告:适用Camera.open()时请务必要检查异常。如果相机正在使用或不存在导致检查异常失败,系统将会关闭你的应用。
如果一个设备上有多个相机,上面的代码会访问第一个后摄像头。

3创建一个基本的相机预览类

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

4拍照

如果想要实现一个JPEG格式的图片,你首先要实现Camera.PictureCallback接口用来接收图像数据并写入到文件,请看下面的示例:

private PictureCallback mPicture = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions");
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};

下面是调用拍照的方法

// get an image from the camera
mCamera.takePicture(null, null, mPicture);

5MediaRecorder录制视频

使用MediaRecorder类录制视频时,必须要按照特定的顺序执行配置。下面的示例演示了怎么正确的配置并准备MediaRecorder类来录制视频:

private boolean prepareVideoRecorder(){

    mCamera = getCameraInstance();
    mMediaRecorder = new MediaRecorder();

    // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mMediaRecorder.setCamera(mCamera);

    // Step 2: Set sources
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    // Step 4: Set output file
    mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

    // Step 5: Set the preview output
    mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    // Step 6: Prepare configured MediaRecorder
    try {
        mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
        Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    }
    return true;
}

6使用相机功能

大部分相机功能可以通过 Camera.Parameters 对象激活并控制。你可以首先通过相机对象获得 Camper.Parameters 对象的实例,然后调用 getParameters() 方法,修改返回的参数对象并重新设置给相机对象。示例代码如下:

// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
mCamera.setParameters(params);

猜你喜欢

转载自blog.csdn.net/Jason_Lewis/article/details/86677041