Android 拍摄 录制

# Android 拍摄 录制

Android 移动开发 拍摄照片 录制视频页面 分两大块 如果业务不是很复杂 对拍摄录制要求没有定制化 ps: 4:3 16:9 照片质量 720P 1080P 不需要实现自己的拍照逻辑 只要借助 Android 原生的 相机 实现拍照录像即可 如果实现定制化开发 ps:照片尺寸 质量 连拍?等 则需要自行开发

# 申请必要的权限

Android 6.0以上 相机权限 录制权限 需要自行申请 这里不再讲明方法

  

  

  

  
  
  

  

# 调用系统相机->拍摄照片

   try {
                //检测相机 权限
                CameraPermissionsUtils.checkCameraPermissions();
                //设置拍摄照片保存位置
                File file = getStorgeFile();
                imgSavePath = file.getPath();
            
                Intent intentFromCapture = new Intent(
                        MediaStore.ACTION_IMAGE_CAPTURE);

                 //添加这一句表示对目标应用临时授权该Uri所代表的文件
                intentFromCapture.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
              
                intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,getUriForFile(getActivity(), file));
                startActivityForResult(intentFromCapture,
                        FLAG_CAMERA);
       } catch (Exception e) {
          ToastUtils.shortToastMessage(BaseApplication.getContext(), "请检查下您是否禁用了照相权限!");
          //执行申请 权限 代码 ...
       }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                //相机拍摄
                case FLAG_CAMERA:
                    File file = new File(imgSavePath);
                    //裁剪 拍摄的照片
                    cropImageUri(getUriForFile(getActivity(), file), 800, 800, FLAG_CLIP, FLAG_CAMERA);
                    break;
            }
        }
    }

# 调用系统相机->录制视频

static final int REQUEST_VIDEO_CAPTURE = 1;

private void dispatchTakeVideoIntent() {
    Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
        Uri videoUri = intent.getData();
        videoView.setVideoURI(videoUri);
    }
}

# 自定义拍摄 录制

  • 设置Camera 参数
  • 初始化 SurfaceView
  • MediaRecorder 参数设置

# 拍摄 录制流程图

Android 拍摄 录制_第1张图片
camera_flow.png

# 设置相机参数

预览比例 保存比例 本机是否支持 该比例?
举个栗子:预览图片希望是4:3 拍照保存也是4:3 手机的屏幕却是 16:9 或者 18:9
如何设置?

  • 按屏幕宽设置 预览View的高

  • 按照比例设置 预览View的宽高 screenHeight = screenWith/3*4

  • 按照预览的比例去轮询 相机支持的参数 设置宽高比

      /**
       * doStartPreview
       * @param holder
       * @param screenProp H/W
       */
      public void doStartPreview(SurfaceHolder holder, float screenProp) {
          if (isPreviewing) {
              LogUtil.i("doStartPreview isPreviewing");
          }
          if (this.screenProp < 0) {
              this.screenProp = screenProp;
          }
          if (holder == null) {
              return;
          }
          this.mHolder = holder;
          if (mCamera != null) {
              try {
                  mParams = mCamera.getParameters();
    
                  mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                  //闪关灯配置
                  //自动模式,当光线较暗时自动打开闪光灯;
                  mParams.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                  //对焦模式
                  //自动模式
                  mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
    
                
                  mParams = mCamera.getParameters();
                  Camera.Size previewSize = CameraParamUtil.getInstance().getPreviewSize(mParams
                          .getSupportedPreviewSizes(), DisplayUtils.getScreenMetrics(BaseApp.getContext()).x, screenProp);
                  Camera.Size pictureSize = CameraParamUtil.getInstance().getPictureSize(mParams
                          .getSupportedPictureSizes(), DisplayUtils.getScreenMetrics(BaseApp.getContext()).x, screenProp);
                  mParams.setPreviewSize(previewSize.width, previewSize.height);
                  preview_width = previewSize.width;
                  preview_height = previewSize.height;
                  mParams.setPictureSize(pictureSize.width, pictureSize.height);
    
                  //设置聚焦方式
                  if (CameraParamUtil.getInstance().isSupportedFocusMode(
                          mParams.getSupportedFocusModes(), android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                      mParams.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                  }
                  // 设置图片保存
                  if (CameraParamUtil.getInstance().isSupportedPictureFormats(mParams.getSupportedPictureFormats(),
                          ImageFormat.JPEG)) {
                      mParams.setPictureFormat(ImageFormat.JPEG);
                      mParams.setJpegQuality(100);
                  }
    
                  mCamera.setParameters(mParams);
                  mParams = mCamera.getParameters();
                  mCamera.setPreviewDisplay(holder);  //SurfaceView
                  mCamera.setDisplayOrientation(cameraAngle);//浏览角度
                  mCamera.setPreviewCallback(this); //每一帧回调
                  mCamera.startPreview();//启动浏览
                  isPreviewing = true;
                  Log.i(TAG, "=== Start Preview ===");
              } catch (Exception e) {
                  e.printStackTrace();
              }
              }
          }
    
  • 按照比例 查询最优 尺寸

       public Camera.Size getPreviewSize(List list, int th, float rate) {
          Collections.sort(list, sizeComparator);
          int i = 0;
          for (Camera.Size s : list) {
              if ((s.width > th) && equalRate(s, rate)) {
                  Log.i(TAG, "MakeSure Preview :w = " + s.width + " h = " + s.height);
                  break;
              }
              i++;
          }
          if (i == list.size()) {
              return getBestSize(list, rate);
          } else {
              return list.get(i);
          }
      }
      
      //排序
      private class CameraSizeComparator implements Comparator {
                   public int compare(Camera.Size lhs, Camera.Size rhs) {
              if (lhs.width == rhs.width) {
                  return 0;
              } else if (lhs.width > rhs.width) {
                  return 1;
              } else {
                  return -1;
              }
          }
      }
    
      //换算 比例差别 
      //如果差别 上下不超过 0.2 则为最佳尺寸 
      private boolean equalRate(Camera.Size s, float rate) {
              float r = (float) (s.width) / (float) (s.height);
              return Math.abs(r - rate) <= 0.2;
       }
    

# 拍照方法 很简单这里不再描述

/**
 * Equivalent to 
takePicture(Shutter, raw, null, jpeg)
. * * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback) */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { takePicture(shutter, raw, null, jpeg); }

# 录制

# 设置录制参数:

//启动录像
public void startRecord(Surface surface, float screenProp, ErrorCallback callback) {
    mCamera.setPreviewCallback(null);
    final int nowAngle = (angle + 90) % 360;
    //获取第一帧图片
    Camera.Parameters parameters = mCamera.getParameters();
    int width = parameters.getPreviewSize().width;
    int height = parameters.getPreviewSize().height;
    YuvImage yuv = new YuvImage(firstFrame_data, parameters.getPreviewFormat(), width, height, null);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    yuv.compressToJpeg(new Rect(0, 0, width, height), 50, out);
    byte[] bytes = out.toByteArray();
    videoFirstFrame = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    Matrix matrix = new Matrix();
    if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
        matrix.setRotate(nowAngle);
    } else if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
        matrix.setRotate(270);
    }
    videoFirstFrame = createBitmap(videoFirstFrame, 0, 0, videoFirstFrame.getWidth(), videoFirstFrame
            .getHeight(), matrix, true);

    if (isRecorder) {
        return;
    }
    if (mCamera == null) {
        openCamera(SELECTED_CAMERA);
    }
    if (mediaRecorder == null) {
        mediaRecorder = new MediaRecorder();
    }
    if (mParams == null) {
        mParams = mCamera.getParameters();
    }
    List focusModes = mParams.getSupportedFocusModes();
    if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
        mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    }
    mCamera.setParameters(mParams);
    mCamera.unlock();
    mediaRecorder.reset();
    mediaRecorder.setCamera(mCamera);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //视频采集来源

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //输出格式
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //编码格式
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //音频模式

    //设置视频输出 尺寸比例
    Camera.Size videoSize;
    if (mParams.getSupportedVideoSizes() == null) {
        videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedPreviewSizes(),
                DisplayUtils.getScreenMetrics(BaseApp.getContext()).x, screenProp);
    } else {
        //            videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedVideoSizes(), 600,
        //                    screenProp);
        videoSize = CamParaUtil.getInstance().getOptimalSize(mParams.getSupportedVideoSizes(),
                DisplayUtils.getScreenMetrics(BaseApp.getContext()).x, DisplayUtils.getScreenMetrics(BaseApp.getContext()).y);
    }
    Log.i(TAG, "setVideoSize    width = " + videoSize.width + "height = " + videoSize.height);
    if (videoSize.width == videoSize.height) {
        mediaRecorder.setVideoSize(preview_width, preview_height);
    } else {
        mediaRecorder.setVideoSize(videoSize.width, videoSize.height);
    }

    //        if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
    //            mediaRecorder.setOrientationHint(270);
    //        } else {
    //            mediaRecorder.setOrientationHint(nowAngle);
    ////            mediaRecorder.setOrientationHint(90);
    //        }
    if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
        //手机预览倒立的处理
        if (cameraAngle == 270) {
            //横屏
            if (nowAngle == 0) {
                mediaRecorder.setOrientationHint(180);
            } else if (nowAngle == 270) {
                mediaRecorder.setOrientationHint(270);
            } else {
                mediaRecorder.setOrientationHint(90);
            }
        } else {
            if (nowAngle == 90) {
                mediaRecorder.setOrientationHint(270);
            } else if (nowAngle == 270) {
                mediaRecorder.setOrientationHint(90);
            } else {
                mediaRecorder.setOrientationHint(nowAngle);
            }
        }
    } else {
        mediaRecorder.setOrientationHint(nowAngle);
    }


    //        if (DeviceUtil.isHuaWeiRongyao()) {
    //            mediaRecorder.setVideoEncodingBitRate(4 * 100000);
    //        } else {
    //            mediaRecorder.setVideoEncodingBitRate(mediaQuality);
    //        }
    
    //设置帧率
    mediaRecorder.setVideoFrameRate(24);
    //设置比特率
    mediaRecorder.setVideoEncodingBitRate(mediaQuality);
    mediaRecorder.setPreviewDisplay(surface);
    
    //文件保存文位置 设置
    videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
    if (saveVideoPath.equals("")) {
        saveVideoPath = Environment.getExternalStorageDirectory().getPath();
    }
    //        videoFileAbsPath = saveVideoPath + File.separator + videoFileName;
    videoFileAbsPath = FileUtil.initPath() + videoFileName;
    mediaRecorder.setOutputFile(videoFileAbsPath);

    try {
        mediaRecorder.prepare();
        mediaRecorder.start();
        isRecorder = true;
    } catch (IllegalStateException e) {
        e.printStackTrace();
        Log.i("CJT", "startRecord IllegalStateException");
        if (this.errorLisenter != null) {
            this.errorLisenter.onError();
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.i("CJT", "startRecord IOException");
        if (this.errorLisenter != null) {
            this.errorLisenter.onError();
        }
    } catch (RuntimeException e) {
        Log.i("CJT", "startRecord RuntimeException");
    }
}

 //停止录像
public void stopRecord(boolean isShort, StopRecordCallback callback) {
    if (!isRecorder) {
        return;
    }
    if (mediaRecorder != null) {
        mediaRecorder.setOnErrorListener(null);
        mediaRecorder.setOnInfoListener(null);
        mediaRecorder.setPreviewDisplay(null);
        try {
            mediaRecorder.stop();
        } catch (RuntimeException e) {
            e.printStackTrace();
            mediaRecorder = null;
            mediaRecorder = new MediaRecorder();
        } finally {
            if (mediaRecorder != null) {
                mediaRecorder.release();
            }
            mediaRecorder = null;
            isRecorder = false;
        }
        if (isShort) {
            if (FileUtil.deleteFile(videoFileAbsPath)) {
                callback.recordResult(null, null);
            }
            return;
        }
        doStopPreview();
        String fileName = FileUtil.initPath() + videoFileName;
        callback.recordResult(fileName, videoFirstFrame);
    }
}

# surfceView 设置

mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
mHolder = mSurfaceView.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.addCallback(this);

@Override
public void surfaceCreated(SurfaceHolder holder) {
    //开启相机
    new Thread() {
        @Override
        public void run() {
            CameraInterface.getInstance().doOpenCamera(CameraShootActivity.this);
        }
    }.start();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    //释放相机
    LogUtil.i("JCameraView SurfaceDestroyed");
    CameraInterface.getInstance().doDestroyCamera();
}

# Activity 生命周期

@Override
protected void onResume() {
    super.onResume();
    CameraInterface.getInstance().registerSensorManager(this);
    if (screenProp > 1.4) {
        isSwitchRecording = true;
        CameraInterface.getInstance().doStopPreview();
        //如果当前屏占比 大于1.8 不是 16:9 采用 16:9设置 小于16:9 采用原先屏占比
        CameraInterface.getInstance().doStartPreview(mSurfaceView.getHolder(), DisplayUtils.getScreenRate(this) > 1.8
                ? 16f / 9f : DisplayUtils.getScreenRate(this));
        screenProp = DisplayUtils.getScreenRate(this) > 1.8
                ? 16f / 9f : DisplayUtils.getScreenRate(this);
        measureVideoSize();
    } else {
        isSwitchRecording = false;
        CameraInterface.getInstance().doStopPreview();
        screenProp = 4f / 3f;
        CameraInterface.getInstance().doStartPreview(mSurfaceView.getHolder(), 4f / 3f);
        measureCameraSize();
    }
}

 @Override
protected void onPause() {
    super.onPause();
    CameraInterface.getInstance().isPreview(false);
    CameraInterface.getInstance().unregisterSensorManager(this);
    CameraInterface.getInstance().doStopPreview();
}

你可能感兴趣的:(Android 拍摄 录制)