Camera相关知识

作者: 天青色等煙雨_而我在等妳 | 来源:发表于2016-10-27 09:06 被阅读60次

    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

    相关文章

      网友评论

        本文标题:Camera相关知识

        本文链接:https://www.haomeiwen.com/subject/oajjuttx.html