阅读 575

Andorid自定义相机,点击拍照,长按录制以及调用系统相机录制(相机系列二)

前言:本章是针对相机系列一衍生的,都是基于camera自定义的。可能网上也有很多资料或者文章,但是看完这两篇文章,你也肯定学会了自定义相机这块(仿微信点击拍照,长按录制);而且我觉得我文章的最大优势是用最简单的语言去描述代码。那么接下来同样是图文并茂。如果大家没有看相机系列一,建议去看看。我这里会直接开始讲视频这块的。

本章2节:
自定义相机拍照,及调用系统相机 -- 相机系列(1)
自定义相机录制,及调用系统录制 -- 相机系列(2)

先看看最终实现的效果

点击拍照 长按录制视频

一、点击拍照

本章只讲视频录制,点击拍照请看相机系列(1)


二、录制视频

视频录制是基于 之前相机系列(1)讲的。所以最好把之前的文章看一遍。首先系统提供了MediaRecorder类,供我们录制视频。直接来到我们之前的CameraInterface管理类里。记得一定要按照这个顺序来,且记得加上之前相机权限和音频权限

2.1、准备录制视频,prepareVideoRecorder(SurfaceHolder surfaceHolder)

    public boolean prepareVideoRecorder(SurfaceHolder surfaceHolder) {
        //视频存放的路径
        videoPath = context.getFilesDir().getAbsolutePath().toString() + "/" + TimeUtils.getDateToStringLeo(System.currentTimeMillis() + "") + "_atmancarm.mp4";

        mMediaRecorder = new MediaRecorder();
        // Step 1: Unlock and set camera to MediaRecorder
        mCamera.unlock();
        //将camera设置给MediaRecorder
        mMediaRecorder.setCamera(mCamera);

        // Step 2: Set sources
        //设置音频资源,所以记得打开音频权限android.permission.RECORD_AUDIO
        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(videoPath);

        // Step 5: Set the preview output
        mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
        
        //这里和拍照一个概念,如果不旋转方向,那么拍摄出来的视频都是横屏的。
        //这里唯一存在的问题的,前置录制视频时会出现镜像问题。可以利用FFmpeg解决。本章讲的是录制,这个问题就留着了
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mMediaRecorder.setOrientationHint(90);
        } else if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mMediaRecorder.setOrientationHint(270);
        }


        // Step 6: Prepare configured MediaRecorder
        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            //释放mMediaRecorder
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    }
复制代码

2.2、开始录制,startRecord()

    public void startRecord() {
        //录制
        mMediaRecorder.start();
    }
复制代码

2.3、停止录制,stopRecod()

public String stopRecod() {
        //停止录制,即是录制完成,我们将路径return出去。如果大家想做视频编辑,可以去了解FFmpeg
        mMediaRecorder.stop();
        return videoPath;
    }
复制代码

2.4、释放mMediaRecorder,releaseMediaRecorder()

    public void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }
复制代码

2.5、简单录制我们的视频

因为我为了代码分离,把所有管理代码放在CameraInterface,同时自定义CameraView起调用作用,避免我们的activity直接出现CameraInterface,这样代码也更佳清晰。

录制视频直接调用:cameraView.startRecord();
录制完成直接调用:String path = binding.cameraView.stopRecod();path即是视频路径


三、预览视频界面

本来用系统的MediaController配合VideoView就能实现下面的效果。奈何比较丑,所以我用线程和ui自定义了一个。

使用VideoView注意一下几点

  • 设置播放路径
//如果是网络路径,那么转换成uri
videoView.setVideoPath(path);
复制代码

  • 暂停和播放
 //开始播放
 binding.videoView.start();
 //暂停
 binding.videoView.pause();
 //跳都某个时刻播放,毫秒数
 binding.videoView.seekTo(currentPosition);
复制代码

  • 设置循环播放
        binding.videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                //设置循环播放
                mp.setLooping(true);
            }
        });
复制代码

  • 释放
 @Override
    protected void onDestroy() {
        super.onDestroy();
        binding.videoView.suspend();
    }
复制代码

  • 播放路径出错,自带会弹出无法播放此视频,我们点击确定的时候,播放不了,那么取消系统的,加上自己的。点确定后退出界面
binding.videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                // 这里加上你自定义的dialog作操作
                // 这里return true后,就不弹出系统的无法播放此视频的弹窗
                return true;
            }
        });
复制代码

四、调用系统相机录制,并获取录制视频路径

直接调用下面代码调用

    Intent intentVideo = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    startActivityForResult(intentVideo, CAMERA_VIDEO_PATH);
复制代码

在onActivityResult获取视频路径

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            if (requestCode == CAMERA_VIDEO_PATH) {
                //获取视频路径
                String path = data.getData().toString();
                VideoPlayActivity.startActivity(SystemCameraActivity.this, path);
            }
        }
    }
复制代码

本github地址

如果你也是一个爱学习,并想学习的话。那么携手共进吧,下面是我的公众号