以前学了很多东西,都没怎么做记录,慢慢的时间长了也就给忘了,当初踩过的坑翻来覆去的踩,由于这些血淋林的教训,所以从现在开始,每次学了新的东西都要来写个博客做个记录总结一下了。
最近在学习Android多媒体这一块,现在刚好学到了MediaRecorder和MediaPlayer。今天也就介绍下这两个类吧,也有利于以后初学者的学习。
本文一共分3个部分:第一和第二部分用来介绍这两个类,第3部分做一个录音的小Demo(附源码)
1.MediaRecorder
关于MediaRecorder 官网给的解释是
Used to record audio and video. The recording control is based on a simple state machine
大致意思就是,这个类是用来去录制音频和视频的。录制基于一种简单的状态机制。
这个状态机制是什么呢?Google给了一张图
从图中可以看出MediaRecorder 有这么几种状态:
Initial:初始化。也就是MediaRecorder 刚被创建的时候。在这个时候我们去设置音频或者视频的来源了,可能这个时候就有人问了 音频或者视频的来源是什么意思,举个例子吧,比如当我们在录音的时候,这个声音的来源就可以设置成手机的麦克风。
Initialized:初始化完成。这里我们已经知道音频或者视频的来源了,在这里我们就可以设置一些输出的属性了,比如输出文件的保存格式,编码什么的。由于水平有限还有很多关于媒体文件属性,我也不是太理解。
DataSourceConfigured:数据源配置改变。也就是我们改变了一些输出的属性,就会进入到这个状态。
Prepered:处于这个状态就说明了我们的配置已经完成了,现在就等去录制了。
Recordeing:这个不用我说也应该明白了。
Released:资源被释放了。
Error:录制的时候发生了错误。
图中已经把状态之间是怎么切换的已经描述的非常清楚了,我也不过多介绍了。
2.MediaPlayer
关于MediaPlayer官网给的解释是:
MediaPlayer class can be used to control playback of audio/video files and streams.
简单翻译过来就是:这个类是用来去播放音频,视频文件和流文件的。
他也对应了一个状态图:
其实他的大致流程和MediaRecorder差不多,这里我就略过了。
你以为到这就结束了吗?肯定不是的,上面的也就为下面我要做的做个铺垫而已,有了上面的基础,后面的肯定就轻松了。
3.做一个录音的小Demo
先来看一看效果图吧
看起来还是很简单吧。
开始是初始状态,然后是录制状态(中间有个波浪形的自定义控件),在这个状态下会显示当前的录制时长,波浪形控件会显示,最后就是录制完成,可以点击播放了。
最下面是保存和删除按钮,可以删除当前的录音。PS:保存按钮没有任何实现,录音文件会自动保存。
知道了这个效果现在就来介绍是怎么做的吧。
这个小Demo我对MediaRecorder和MediaPlayer做了一下封装,方便以后使用调用方便。
MediaRecorderHelper代码如下:
public class MediaRecorderHelper {private MediaRecorder mMediaRecorder; private String mSavePath; private String mCurrentFilePath; public MediaRecorderHelper(String savePath) { mSavePath = savePath; File file = new File(mSavePath); if (!file.exists()) file.mkdirs(); } /** * 开始录音 */ public void startRecord() { try { mMediaRecorder = new MediaRecorder(); File file = new File(mSavePath, generateFileName()); mCurrentFilePath = file.getAbsolutePath(); // 设置录音文件的保存位置 mMediaRecorder.setOutputFile(mCurrentFilePath); // 设置录音的来源(从哪里录音) mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置录音的保存格式 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 设置录音的编码 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.prepare(); mMediaRecorder.start(); } catch (Exception e) { e.printStackTrace(); } } /** * 停止录音 */ public void stopAndRelease() { if (mMediaRecorder == null) return; mMediaRecorder.stop(); mMediaRecorder.release(); mMediaRecorder = null; } /*** * 取消本次录音操作 */ public void cancel() { this.stopAndRelease(); if (mCurrentFilePath != null) { File file = new File(mCurrentFilePath); file.delete(); mCurrentFilePath = null; } } private String generateFileName() { return UUID.randomUUID().toString() + ".amr"; } /** * 得到录音文件的路径 * * @return */ public String getCurrentFilePath() { return mCurrentFilePath; }
}
MediaPlayerHelper代码如下:
public class MediaPlayerHelper {private static MediaPlayer mMediaPlayer; private static boolean isPause = false; public static void playSound(String filePath) { playSound(filePath, null); } public static void playSound(String filePath, MediaPlayer.OnCompletionListener onCompletionListener) { if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayer(); mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { mMediaPlayer.reset(); return false; } }); } else { mMediaPlayer.reset(); } try { mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); if (onCompletionListener != null) { mMediaPlayer.setOnCompletionListener(onCompletionListener); } mMediaPlayer.setDataSource(filePath); mMediaPlayer.prepare(); mMediaPlayer.start(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 暂停播放 */ public static void pause() { if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); isPause = true; } } /** * 继续播放 */ public static void resume() { if (mMediaPlayer != null && isPause) { mMediaPlayer.start(); isPause = false; } } /** * 释放资源 */ public static void realese() { if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; isPause = true; } }
}
这两个类的代码注释的已经非常详细了,我再在这里介绍也就显得有点多余了。如果还是又不懂或者有问题需要提出的,欢迎留言。
到这里我们的核心东西已经准备好了,现在就剩下一个Activity让我们去实现刚才效果图上的小Demo了。
我们来分析一下我们的小Demo会有哪些状态:
1.正常状态,也就是没有录制的状态
2.录制中
3.录制完成
4.播放状态
5.暂停状态
对于这几种状态我定义了对应的五个常量来表示。
private static final int ACTION_NORMAL = 0;
private static final int ACTION_RECORDING = 1;
private static final int ACTION_COMMPLETE = 2;
private static final int ACTION_PLAYING = 3;
private static final int ACTION_PAUSE = 4;
在中间的录制按钮在点击的时候,我们要根据当前的状态来进行状态之间的切换:
依然是附代码,就是这么任性~~~~
/**
* 切换ACTION状态
*/
private void switchActionState() {
mIsRecorder = false;
if (mCurrentActionState == ACTION_NORMAL) {
mCurrentActionState = ACTION_RECORDING;
mIvAction.setImageResource(R.drawable.pause);//开始录音 mMediaRecorderHelper.startRecord(); mWaveView.setVisibility(View.VISIBLE); mIsRecorder = true; //开启计时线程 mCountTimeThread = new Thread(this); mCountTimeThread.start(); } else if (mCurrentActionState == ACTION_RECORDING) {//录制中 mCurrentActionState = ACTION_COMMPLETE; mIvAction.setImageResource(R.drawable.icon_audio_state_uploaded); //停止录音 mMediaRecorderHelper.stopAndRelease(); mRlBottom.setVisibility(View.VISIBLE); mWaveView.setVisibility(View.INVISIBLE); } else if (mCurrentActionState == ACTION_COMMPLETE) {//录制完成 mCurrentActionState = ACTION_PLAYING; mIvAction.setImageResource(R.drawable.icon_audio_state_uploaded_play); //播放录音 MediaPlayerHelper.playSound(mMediaRecorderHelper.getCurrentFilePath(), new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { //当播放完了之后切换到录制完成的状态 mCurrentActionState = ACTION_COMMPLETE; mIvAction.setImageResource(R.drawable.icon_audio_state_uploaded); } }); } else if (mCurrentActionState == ACTION_PLAYING) {//播放中 mCurrentActionState = ACTION_PAUSE; mIvAction.setImageResource(R.drawable.icon_audio_state_uploaded); //暂停播放 MediaPlayerHelper.pause(); } else if (mCurrentActionState == ACTION_PAUSE) {//暂停 mCurrentActionState = ACTION_PLAYING; mIvAction.setImageResource(R.drawable.icon_audio_state_uploaded_play); //继续播放 MediaPlayerHelper.resume(); } }
上面的就是整个Demo的核心思想。
需要源码的可以点击下面的链接下载。
MediaRecorderDemo
如果在阅读的过程中又发现错误,也欢迎留言纠错。