Android 多媒体之MediaRecorder MediaP
以前学了很多东西,都没怎么做记录,慢慢的时间长了也就给忘了,当初踩过的坑翻来覆去的踩,由于这些血淋林的教训,所以从现在开始,每次学了新的东西都要来写个博客做个记录总结一下了。
最近在学习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.
简单翻译过来就是:这个类是用来去播放音频,视频文件和流文件的。
他也对应了一个状态图:
mediaplayer_state_diagram.gif其实他的大致流程和MediaRecorder差不多,这里我就略过了。
你以为到这就结束了吗?肯定不是的,上面的也就为下面我要做的做个铺垫而已,有了上面的基础,后面的肯定就轻松了。
3.做一个录音的小Demo
先来看一看效果图吧
未标题-1.png看起来还是很简单吧。
开始是初始状态,然后是录制状态(中间有个波浪形的自定义控件),在这个状态下会显示当前的录制时长,波浪形控件会显示,最后就是录制完成,可以点击播放了。
最下面是保存和删除按钮,可以删除当前的录音。PS:保存按钮没有任何实现,录音文件会自动保存。
知道了这个效果现在就来介绍是怎么做的吧。
这个小Demo我对MediaRecorder和MediaPlayer做了一下封装,方便以后使用调用方便。
MediaRecorderHelper代码如下:
<pre>
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;
}
}
</pre>
MediaPlayerHelper代码如下:
<pre>
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;
}
}
}
</pre>
这两个类的代码注释的已经非常详细了,我再在这里介绍也就显得有点多余了。如果还是又不懂或者有问题需要提出的,欢迎留言。
到这里我们的核心东西已经准备好了,现在就剩下一个Activity让我们去实现刚才效果图上的小Demo了。
我们来分析一下我们的小Demo会有哪些状态:
1.正常状态,也就是没有录制的状态
2.录制中
3.录制完成
4.播放状态
5.暂停状态
对于这几种状态我定义了对应的五个常量来表示。
<pre>
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;
</pre>
在中间的录制按钮在点击的时候,我们要根据当前的状态来进行状态之间的切换:
依然是附代码,就是这么任性~~~~
<pre>
/**
* 切换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();
}
}
</pre>
上面的就是整个Demo的核心思想。
需要源码的可以点击下面的链接下载。
MediaRecorderDemo
如果在阅读的过程中又发现错误,也欢迎留言纠错。