美文网首页Android知识Android技术知识Android开发
android 摄像头Camera调用的几个小坑

android 摄像头Camera调用的几个小坑

作者: 书柜里的松鼠 | 来源:发表于2017-04-14 10:36 被阅读3505次

    Camera的使用教程很多了,就不写完整的了。
    这里就记一下遇到的几个小坑。

    1.在Surface建立后再调用摄像头。

    这是个简单到傻的问题,然而一开始用的时候居然困扰了半天。明明有Camera对象却黑屏。简直要被自己蠢哭。
    这里给SurfaceHolder设置回调就可以知道是否已创建了。

    /**
         * 初始化surfaceView
         */
        private void initSurfaceView(){
            SurfaceView surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
            SurfaceHolder sfHolder=surfaceView.getHolder();
            // 设置分辨率
            sfHolder.setFixedSize(screenW, screenH);
            sfHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    Log.d("LOGCAT", "surfaceDestroyed");
                }
    
                //必须监听surfaceView的创建,创建完毕后才可以处理播放
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    Log.d("LOGCAT", "surfaceCreated");
                    if(hasCamera) {
                        initCamera();//接收到Surface的回调后再启用摄像头。
                    }else{
                        Toast.makeText(context, "没有摄像头,退散吧!", Toast.LENGTH_SHORT).show();
                    }
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                    Log.d("LOGCAT", "surfaceChanged");
                }
            });
        }
    
    2.切换前后摄像头
    camera.stopPreview();
    camera.release();
    if(camIdx==Camera.CameraInfo.CAMERA_FACING_FRONT){
        camIdx=Camera.CameraInfo.CAMERA_FACING_BACK;
    }else{
        camIdx=Camera.CameraInfo.CAMERA_FACING_FRONT;
    }
    camera = Camera.open(camIdx);
    camera.setPreviewDisplay(sfHolder);
    camera.startPreview(); //开始预览
    
    3.摄像头的释放

    切换摄像头,或关闭应用的时候一定要释放。不然即使应用关闭了,摄像头还是可能处于使用状态。

    @Override
        public void onDestroy() {
            Log.d("LOGCAT", "player onDestroy");
            camera.release();
            camera=null;
            super.onDestroy();
        }
    
    4.检测摄像头是否存在
        private boolean checkCameraHardware(Context context) {
            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
                return true;
            } else {
                return false;
            }
        }
    
    5.录制视频
    camera.unlock();
    mRecorder = new MediaRecorder();
    mRecorder.reset();
    mRecorder.setCamera(camera);
    // 设置从麦克风采集声音(或来自录像机的声音AudioSource.CAMCORDER)
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    // 设置从摄像头采集图像
    mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    //录制角度
    //mRecorder.setOrientationHint(90);
    // 设置视频文件的输出格式
    // 必须在设置声音编码格式、图像编码格式之前设置
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    // 设置声音编码的格式
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    // 设置图像编码的格式
    mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    // 设置图像的码率
    mRecorder.setVideoEncodingBitRate(5*screenW*screenH);
    mRecorder.setVideoSize(screenW, screenH);
    // 每秒24帧
    mRecorder.setVideoFrameRate(24);
    mRecorder.setOutputFile(videoFile.getAbsolutePath());
    // 指定使用SurfaceView来预览视频
    mRecorder.setPreviewDisplay(sfHolder.getSurface());
    mRecorder.prepare();
    // 开始录制
    mRecorder.start();
    

    需要特别注意的是,录制前必须

    Camera.unlock();
    

    以及

    mRecorder.setCamera(camera);
    

    不然会报错。

    或者,录制之前释放掉Camere

    camera.release();
    camera=null;
    

    那MediaRecorder.start()时会打开默认摄像头录制。

    6. MediaRecorder: start failed: -19错误

    这个问题通常是由setVideoFrameRate方法引起的。不支持就去掉吧。
    还有setVideoSize方法,如果设置的分辨率是不支持的,也会报错。

    7. camera setParameters failed错误

    这个是由于设置的分辨率不被当前摄像头支持造成的。可以使用默认,或者通过

    Camera.Parameters parameters  = mCamera.getParameters();  
    List<Camera.Size> prviewSizeList = parameter.getSupportedPreviewSizes();
    List<Camera.Size> videoSizeList = parameter.getSupportedVideoSizes();
    

    获取支持的分辨率进行设置。

    8. 6.0及以上系统权限问题

    6.0开始有了运行中请求权限的设置,所以要调用摄像头的话除了需要在AndroidManifest中设置权限<uses-permission android:name="android.permission.CAMERA" />外,还要在调用的过程中请求权限:

    if (Build.VERSION.SDK_INT >= 24) {
                    requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PHOTO_REQUEST_TAKEPHOTO);
                } 
    

    这里的PHOTO_REQUEST_TAKEPHOTO是任意定的一个标识符,回调的时候获取以区分来源。

    相关文章

      网友评论

        本文标题:android 摄像头Camera调用的几个小坑

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