# Android shoot and record

Android mobile development photo shooting video recording page is divided into two blocks. If the business is not very complex, there is no customization of shooting and recording requirements. Ps: 4:316: 9 photo quality 720P 1080P do not need to achieve their own photography logic as long as the use of Android native camera to achieve photography and video can be customized development PS: photo size quality continuous shooting? Others need to develop their own

Request the necessary permissions

Android 6.0 or above camera permission recording permission needs to apply for by yourself

	  <uses-feature android:name="android.hardware.camera" />
	  <uses-feature android:name="android.hardware.camera.autofocus" />
	  <uses-permission android:name="android.permission.CAMERA" />
      <uses-permission android:name="android.permission.RECORD_AUDIO" />
	  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Copy the code

# Call system Camera -> Take a photo

       try {
					// Check camera permissions
                    CameraPermissionsUtils.checkCameraPermissions();
					// Set the location to save the photo
                    File file = getStorgeFile();
                    imgSavePath = file.getPath();
				
                    Intent intentFromCapture = new Intent(
                            MediaStore.ACTION_IMAGE_CAPTURE);

					 // Add this sentence to apply temporary authorization to the file represented by the Uri to the target
                    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(), "Please check whether you have disabled the camera permission!");
			  // Execute the request permission code...
           }

		@Override
	    public void onActivityResult(int requestCode, int resultCode, Intent data) {
	        super.onActivityResult(requestCode, resultCode, data);
	        if (resultCode == RESULT_OK) {
	            switch (requestCode) {
	                // Camera shot
	                case FLAG_CAMERA:
	                    File file = new File(imgSavePath);
						// Crop the photo taken
	                    cropImageUri(getUriForFile(getActivity(), file), 800.800, FLAG_CLIP, FLAG_CAMERA);
	                    break; }}}Copy the code

# Call system camera -> Record video

    static final int REQUEST_VIDEO_CAPTURE = 1;

	private void dispatchTakeVideoIntent(a) {
	    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); }}Copy the code

# Custom shooting recording

  • Setting Camera Parameters
  • Initialize the SurfaceView
  • MediaRecorder parameter Settings

# Shooting and recording flow chart

# Set camera parameters

Preview scale Save Scale Does the machine support this scale? For example: I want to preview pictures at 4:3 and save photos at 4:3, but the screen of the phone is 16:9 or 18:9.

  • Set the height of the preview View by screen width
  • ScreenHeight = screenWith/3*4
  • Poll the camera to support the aspect ratio based on the preview scale
	    /**
	     * 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);
	                // Flash off configuration
	                // Automatic mode, when the light is low automatically turn on the flash;
	                mParams.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
	                // Focus mode
	                // Automatic mode
	                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);

					// Set the focus mode
	                if (CameraParamUtil.getInstance().isSupportedFocusMode(
	                        mParams.getSupportedFocusModes(), android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
	                    mParams.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
	                }
					// Set the image to save
	                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);// View the Angle
	                mCamera.setPreviewCallback(this); // Every frame callback
	                mCamera.startPreview();// Start browsing
	                isPreviewing = true;
	                Log.i(TAG, "=== Start Preview ===");
	            } catch(Exception e) { e.printStackTrace(); }}} - Query the optimal size according to the scalepublic Camera.Size getPreviewSize(List<Camera.Size> 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 {
	            returnlist.get(i); }}/ / sorting
		private class CameraSizeComparator implements Comparator<Camera.Size> {
       				 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; }}}// Convert the scale difference
		// If the difference is not more than 0.2, the best size
		private boolean equalRate(Camera.Size s, float rate) {
		        float r = (float) (s.width) / (float) (s.height);
		        return Math.abs(r - rate) <= 0.2;
		 }
Copy the code

# The method of taking photos is very simple and is not described here

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

# recorded

# Set recording parameters:

	// Start recording
    public void startRecord(Surface surface, float screenProp, ErrorCallback callback) {
        mCamera.setPreviewCallback(null);
        final int nowAngle = (angle + 90) % 360;
        // Get the first frame
        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<String> 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); // Video capture source

        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // Output format
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // Encoding format
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // Audio mode

		// Set the video output size ratio
        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) {
            // Phone preview handstand handling
            if (cameraAngle == 270) {
                / / landscape
                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);
        / /}
		
		// Set the frame rate
        mediaRecorder.setVideoFrameRate(24);
		// Set the bit rate
        mediaRecorder.setVideoEncodingBitRate(mediaQuality);
        mediaRecorder.setPreviewDisplay(surface);
		
		// Set the file location
        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"); }}// Stop recording
    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); }}Copy the code

# surfceView set

	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) {
		// Start the camera
        new Thread() {
            @Override
            public void run(a) {
                CameraInterface.getInstance().doOpenCamera(CameraShootActivity.this);
            }
        }.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Override
    public void surfaceDestroyed(SurfaceHolder holder) {
		// Release the camera
        LogUtil.i("JCameraView SurfaceDestroyed");
        CameraInterface.getInstance().doDestroyCamera();
    }
Copy the code

# Activity lifecycle

    @Override
    protected void onResume() {
        super.onResume();
        CameraInterface.getInstance().registerSensorManager(this);
        if(screenProp > 1.4) {isSwitchRecording =true; CameraInterface.getInstance().doStopPreview(); // If the current screen size is greater than 1.8, not 16: 9 16:9 ratio less than 16:9 Settings to use the original screen than CameraInterface.is 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();
    }
Copy the code