Camera相关知识

App如何试图使用camera硬件特性的?
-在manifest中声明使用camera权限
-快速拍照还是自定义Camera?如果只是拍照或拍视频,使用现有的Camera App即可,否则要自定义Camera了。
-存储。产生的图片或视频打算只对你的应用可用还是可被其他应用(如Gallery或其他媒体库)共享?在App卸载时是否仍可用?

几个关键类:Camera,SurfaceView,MediaRecorder,Intent

Camera App:
-检测&访问Camera,用代码监测camera的存在并请求访问。

// Check if this device has a camera
private boolean checkCameraHardware(Context context) {
    return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
private static Camera getCameraInstance() {
    Camera camera = null;
    try {
        camera = Camera.open();
    } catch (Exception e) {
        // Camero is not available (in use or does not exist)
       }
    return camera;
}

-创建Preview类,创建一个继承自SurfaceView的Preview类,实现SurfaceHolder接口。这个类预览实时的图片和camera。

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = SurfaceView.class.getSimpleName();
    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);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    public CameraPreview(Context context, AttributeSet attrs) {
        super(context, attires);
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview " + e.getMessage());
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mHolder.getSurface() == null) {
            return;
        }
        try {
            mCamera.stopPreview();
        } catch (Exception e) {        }
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(TAG, "Error starting camera preview " + e.getMessage());
        }
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // releasing
    }
}

-构建一个Preview布局。
略。
-设置捕获监听,对用户动作连接一个监听器,来控制开始拍照/拍摄

mHolder.addCallback(Callback c);

-捕获&保存文件。
构建完一个Preview类,将它置入一个layout之后,你就做好了捕获图像的准备。为了以JPEG格式接收数据,必需实现一个Camera.PictureCallback接口以接收图像数据,再写入文件。
图像文件/视频文件
(1)捕获图像
比较简单,主要是一个捕获图像后的回调。

mCamera.takePicture(null, null, mPicture);
private Camera.PictureCallback mPicture = new Camera.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 permisions: ");
            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());
        }
    }
};

在onPictureTaken()回调方法里,把字节数组写进文件输出流里即可。
(2)捕获视频
主要是捕获视频的准备工作:

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

完了之后就可以调mMediaRecorder.start()了。
但是存在一个让我疑惑的地方,录制的视频是如何写进视频文件的呢?我还没找到代码在哪。
-释放Camera。
略。

注:Camera是共享的资源,必需管理好对camera的使用。

这篇文章有点水了,这是官方training里面的一篇,我只是简单翻译了一下。

https://developer.android.com/guide/topics/media/camera.html#saving-media

推荐阅读更多精彩内容