热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android使用MediaRecorder类实现视频和音频录制功能

Android提供了MediaRecorder这一个类来实现视频和音频的录制功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧

这里写图片描述

一、前期基础知识储备

Android提供了MediaRecorder这一个类来实现视频和音频的录制。

这里写图片描述 

 由官方配图可知,MediaRecorder用于录制视频时需要调用一系列的API来设置和录制相关的配置,而且调用方法的顺序是固定的,必须按照这个顺序进行API调用才能正确利用手机摄像头实现录像功能。

调用MediaRecorder的录像API顺序如下:

1)Open Camera - Use the Camera.open() to get an instance of the camera object.  

2)Connect Preview - Prepare a live camera image preview by connecting a SurfaceView to the camera using Camera.setPreviewDisplay(). 

 3)Start Preview - Call Camera.startPreview() to begin displaying the live camera images. 

 4)Start Recording Video - The following steps must be completed in order to successfully record video: 

a.Unlock the Camera - Unlock the camera for use by MediaRecorder by calling Camera.unlock(). 

 b.Configure MediaRecorder - Call in the following MediaRecorder methods in this order:

setCamera() - Set the camera to be used for video capture,绑定Camera进行视频录制。
setAudioSource() - Set the audio source,设置音频源。
setVideoSource() - Set the video source,设置视频源。
setProfile() - Set the video output format and encoding,录制效果的配置。
setOutputFile() - Set the output file, 设置录制好的文件存储位置。
setPreviewDisplay() - Connect Preview,设置预览效果。

c.Prepare MediaRecorder- Prepare the MediaRecorder with provided configuration settings by calling MediaRecorder.prepare(). 

d.Start MediaRecorder - Start recording video by calling MediaRecorder.start().

停止录像时调用的API顺序如下:

1)Stop MediaRecorder - Stop recording video by calling MediaRecorder.stop().
 2)Reset MediaRecorder - Optionally, remove the configuration settings from the recorder by calling MediaRecorder.reset().
 3)Release MediaRecorder - Release the MediaRecorder by calling MediaRecorder.release().
 4)Lock the Camera - Lock the camera so that future MediaRecorder sessions can use it by calling Camera.lock().
 5)Stop the Preview - When your activity has finished using the camera, stop the preview using Camera.stopPreview().
 6)Release Camera - Release the camera so that other applications can use it by calling Camera.release().

二、上代码,具体实现录制视频和视频播放功能

这里调用MediaRecorder的API实现视频录制功能并借用MediaPlayer多媒体播放类实现录制好的视频播放。

(1)布局文件如下,非常简单两个按钮下放置一个SurfaceView;


  
   

(2)相机录像前的准备代码;

 /*
 * 相机预览前的准备工作代码 单独抽出来
 * */
 private boolean prepareVideoRecorder() throws IOException {
  if (mMediaRecorder == null) {
   mMediaRecorder = new MediaRecorder();
   mMediaRecorder.reset();
  }
   /*camera相关设置部分*/
  mCamera = Camera.open(0);//Camera.CameraInfo.CAMERA_FACING_BACK
  if (mCamera != null) {
   //设置旋转角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了
   mCamera.setDisplayOrientation(90);
   mCamera.unlock();
   mMediaRecorder.setCamera(mCamera);
  }
   /*recorder设置部分*/
  mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
  mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
  mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
  mMediaRecorder.setOutputFile(getOutputMediaFile());
  mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
  mMediaRecorder.prepare();
  return true;
 }

(3)创建录像文件存储位置代码; 

 /*
 * 获取手机外部存储路径
 * */
 private String getOutputFile() {
  File mediaFile = null;
  boolean OutputExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
  if (OutputExist) {
   mediaFile = Environment.getExternalStorageDirectory();
   return mediaFile.toString();
  }
  return null;
 }
 /*
 * 获取录制视频的日期 作为存储文件路径一部分
 * */
 private String getDate() {
  Log.d(TAG, "获取录制视频的日期 ");
  Calendar ca = Calendar.getInstance();
  int year = ca.get(Calendar.YEAR);   // 获取年份
  int mOnth= ca.get(Calendar.MONTH);   // 获取月份
  int day = ca.get(Calendar.DATE);   // 获取日
  String date = "" + year + "_" + (month + 1) + "_" + day;
  return date;
 }
 /*
 *创建视频存储文件夹 录制好的视频存储在手机外部存储中 以录像时间+mp4格式命名
 * */
 private String getOutputMediaFile() {
  Log.d(TAG, "获取视频存储的位置 ");
  String mediaPath = getOutputFile();
  if (mediaPath != null) {
   File mediaFile = new File(mediaPath + "/recordVideo");
   if (!mediaFile.exists()) {
    mediaFile.mkdir();
   }
   return mMediaPath = mediaFile.getAbsolutePath() + File.separator + getDate() + ".mp4";
  }
  return null;
 }

(4)录制视频结束时释放相机资源;

 /*
 * 录制视频结束时释放相机资源
 * */
 private void releaseMediaRecorder() {
  Log.d(TAG, "录制结束后释放资源 ");
  if (mMediaRecorder != null) {
   mMediaRecorder.reset(); // clear recorder configuration
   mMediaRecorder.release(); // release the recorder object
   mMediaRecorder = null;
   mCamera.lock();   // lock camera for later use
  }
 }

(5)点击录制视频按钮mRecordBtn开始录制和再次点击停止录制;

 private void initBtnClick() {
  StartRecording();
  mPlayBtn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    if (mMediaPlayer == null) {
     mMediaPlayer = new MediaPlayer();
     mMediaPlayer.reset();
     Uri uri = Uri.parse(mMediaPath);
     mMediaPlayer = MediaPlayer.create(MainActivity.this,uri);
     mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
     mMediaPlayer.setDisplay(mSurfaceHolder);
     try{
      mMediaPlayer.prepare();
     }catch (Exception e){
      e.printStackTrace();
     }
     mMediaPlayer.start();
    }
   }
  });
 }
 private void StartRecording(){
  mRecordBtn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    if (!mIsRecord) {
     try {
      Log.d(TAG, "首次点击开始录像 ");
      if (prepareVideoRecorder()) {
       mMediaRecorder.start();
       mIsRecord = true;
       mRecordBtn.setText("stop");
      }
     } catch (IOException e) {
      e.printStackTrace();
     }
    } else {
     Log.d(TAG, "再次点击停止录像");
     mMediaRecorder.stop();
     releaseMediaRecorder();
     mCamera.lock();
     mRecordBtn.setText("record");
     mIsRecord = false;
     if (mCamera != null) {
      mCamera.release();
      mCamera = null;
     }
    }
   }
  });
 }

(6)点击播放视频按钮 mPlayBtn开始播放录制刚刚录制好的视频;      

 mPlayBtn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    if (mMediaPlayer == null) {
     mMediaPlayer = new MediaPlayer();
     mMediaPlayer.reset();
     Uri uri = Uri.parse(mMediaPath);
     mMediaPlayer = MediaPlayer.create(MainActivity.this,uri);
     mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
     mMediaPlayer.setDisplay(mSurfaceHolder);
     try{
      mMediaPlayer.prepare();
     }catch (Exception e){
      e.printStackTrace();
     }
     mMediaPlayer.start();
    }
   }
  });

(7)针对6.0以上系统进行运行时权限申请

 private void requestCameraAndStoragePermission() {
  //检查用户是否授权
  for (int i = 0; i 

录制视频及播放录制视频完整代码如下

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
 private static final String TAG = "MainActivity";
 private SurfaceView mSurfaceView;
 private Button mRecordBtn, mPlayBtn;
 private boolean mIsRecord = false; //是否正在录像
 private Camera mCamera;
 private MediaRecorder mMediaRecorder;
 private String mMediaPath;
 private MediaPlayer mMediaPlayer;
 private SurfaceHolder mSurfaceHolder;
 private PermissionsUtils mPermissionsUtils;
 private String[] permissiOns= {Manifest.permission.WRITE_EXTERNAL_STORAGE,
         Manifest.permission.CAMERA,
         Manifest.permission.RECORD_AUDIO};
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  //6.0及以上系统请求运行时权限 利用权限申请工具类(见下文)
  requestCameraAndStoragePermission();
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
  mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 必须-设置Surface不需要维护自己的缓冲区
  mRecordBtn = (Button) findViewById(R.id.record_btn);
  mPlayBtn = (Button) findViewById(R.id.play_btn);
  initBtnClick();
  SurfaceHolder holder = mSurfaceView.getHolder();
  holder.addCallback(this);
 }
 private void requestCameraAndStoragePermission() {
  //检查用户是否授权
  for (int i = 0; i 

三、延伸知识,运行时权限申请工具类

调用手机系统内置的摄像头进行视频录制时及录制视频后将视频保存在本地都需要申请系统权限,而且申请的权限(调用摄像头权限、存储权限)都属于26个危险权限,针对6.0以上的手机,需要进行运行时权限的申请,由于申请的权限过多,而且申请的时间不一致,所以这里提供一个权限申请工具类协助实现权限申请。(来自文章:Android动态请求权限的工具类(可请求多个,并且功能完善))

完整代码如下

/**
 * 运行时权限申请工具类:
 * 检查用户是否授权——ContextCompat.checkSelfPermission
 * 如果没有授权,那么申请授权——ActivityCompat.requestPermissions
 * 申请授权之后的回调——onRequestPermissionsResult
 * 精髓:检查权限 申请权限的代码写在工具类内 同时写入一个接口 两个抽象方法-获取权限成功 + 获取权限失败 然后在外部使用权限工具类时实现这两个抽象方法
 * Created by Administrator on 2018/7/3.
 */
public class PermissionsUtils {
 private final int mRequestCode = 100;//权限请求码
 public static boolean showSystemSetting = true;
 private PermissionsUtils() {
 }
 private static PermissionsUtils permissionsUtils;
 private IPermissionsResult mPermissionsResult;
 /*
 * 单例模式创建PermissionUtils实例 工具类中的静态方法可以直接使用类名+方法名调用 非静态方法还是需要获取到工具类的实例 实例对方法进行调用
 * */
 public static PermissionsUtils getInstance() {
  if (permissiOnsUtils== null) {
   synchronized (PermissionsUtils.class) {
    if (permissiOnsUtils== null)
    permissiOnsUtils= new PermissionsUtils();
   }
  }
  return permissionsUtils;
 }
 /*
 * 检查用户是否授权 + 如果没有授权 则申请授权 - 系统标准方法
 * */
 public void chekPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) {
  mPermissiOnsResult= permissionsResult;
  if (Build.VERSION.SDK_INT <23) {//6.0系统及以上才会动态申请权限 以下不用 所以直接return出去
   permissionsResult.passPermissons();
   return;
  }
  //创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPerrrmissionList中
  List mPermissiOnList= new ArrayList<>();
  //逐个判断你要的权限是否已经通过
  for (int i = 0; i  0) {//有权限没有通过,需要申请
   ActivityCompat.requestPermissions(context, permissions, mRequestCode);
  } else {
   //说明权限都已经通过,利用接口变量调用实现的接口方法 即有权限之后需要调用的方法
   permissionsResult.passPermissons();
   return;
  }
 }
 //请求权限后回调的方法
 //参数: requestCode 是我们自己定义的权限请求码
 //参数: permissions 是我们请求的权限名称数组
 //参数: grantResults 是我们在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限
 public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions,
           @NonNull int[] grantResults) {
  boolean hasPermissiOnDismiss= false;//有权限没有通过
  if (mRequestCode == requestCode) {
   for (int i = 0; i 

总结

以上所述是小编给大家介绍的Android使用MediaRecorder实现录制视频功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • 在使用如新浪微博和腾讯微博等平台的Python API时,发现了一种将字典转换为函数参数的有效方法,即通过在字典前添加双星号(*)来实现动态变量的传递。这种方法不仅提高了代码的灵活性,也简化了API调用过程。 ... [详细]
  • 基于函数实现的进制转换工具
    本文介绍了一种利用函数实现不同进制数(二进制、八进制、十进制)之间转换的方法。包括了程序的运行效果展示、所使用的主要函数解析、以及如何验证用户输入的合法性。整个项目仅使用了两个全局变量来存储用户的选项和输入的数值。 ... [详细]
  • 深度兴趣网络在点击率预测中的应用研究
    本文探讨了一种名为深度兴趣网络(Deep Interest Network, DIN)的新方法,该方法通过捕捉用户的历史行为和当前上下文之间的交互来提高点击率预测的准确性。DIN模型不仅考虑了用户的静态偏好,还动态地调整了对不同商品的兴趣权重,从而实现了更加个性化的推荐。 ... [详细]
  • Only2 Labs 是一家专注于视觉设计的工作室,如果您对当前的设计感到不满,或者急需寻找一个可靠的设计合作伙伴,甚至是您的团队项目需要专业指导,Only2 Labs 都将竭诚为您提供帮助。 ... [详细]
  • 本文探讨了HDU 4035的问题,涉及一个由n个房间组成的迷宫,这些房间通过n-1条隧道相互连接,形成一棵树结构。任务是从起点1号房间出发,计算到达出口所需经过的平均隧道数量,考虑了在每个房间中可能发生的三种情况及其相应概率。 ... [详细]
  • 本文探讨了在iOS应用中实现类似Android Snack Bar功能的方法,并特别关注如何确保Snack Bar正确显示在键盘下方。 ... [详细]
  • SQL注入实验:SqliLabs第38至45关解析
    本文深入探讨了SqliLabs项目中的第38至45关,重点讲解了堆叠注入(Stacked Queries)的应用技巧及防御策略。通过实际案例分析,帮助读者理解如何利用和防范此类SQL注入攻击。 ... [详细]
  • KKCMS代码审计初探
    本文主要介绍了KKCMS的安装过程及其基本功能,重点分析了该系统中存在的验证码重用、SQL注入及XSS等安全问题。适合初学者作为入门指南。 ... [详细]
  • 使用Inno Setup将EXE与JRE封装为Windows安装程序
    本文详细介绍了如何利用Inno Setup工具将EXE文件及Java运行环境(JRE)整合为适用于Windows操作系统的安装程序。我们将提供必要的软件下载链接,并逐步指导您完成整个打包过程。 ... [详细]
  • 这篇博文介绍使用命令行参数的编程方法,载体是用于文件复制的程序。这也是我用Markdown编辑器写的第一篇博文。Markdown在写《逆袭大学》时用过,写博文是第一次。本文正文:引子 ... [详细]
  • 本文详细介绍了如何在iOS应用中更改状态栏的颜色,包括设置状态栏为黑色或白色风格的方法,以及在不同配置下的具体实现步骤。 ... [详细]
  • Windows 10 中 F5 键无法刷新页面,而是调整亮度的解决方法
    在 Windows 操作系统中,F5 键通常用于刷新桌面、文件夹或网页。然而,部分笔记本用户发现 F5 键的功能发生了变化,无法正常刷新页面,反而变成了调整屏幕亮度。本文将提供解决方案,帮助用户恢复 F5 键的原始功能。 ... [详细]
  • 如何在Ubuntu上查询OpenCV版本
    本文介绍了一种简单的方法来查询Ubuntu系统中已安装的OpenCV版本,对于开发者来说非常实用。 ... [详细]
  • 本文将详细介绍如何在华硕笔记本已安装Windows 10系统的情况下,添加安装Windows 7,实现双系统共存的方法。 ... [详细]
  • 为了增强服务器的安全性,管理员可以通过SSH进行精细的访问控制。本文将介绍两种有效的方法来限制用户从特定IP地址登录,包括更改默认端口和设置允许访问的IP列表。 ... [详细]
author-avatar
用户d4k2wd8en1
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有