实用控件自定义控件首页投稿(暂停使用,暂停投稿)

Android 多媒体之MediaRecorder MediaP

2016-03-26  本文已影响3010人  _SOLID

以前学了很多东西,都没怎么做记录,慢慢的时间长了也就给忘了,当初踩过的坑翻来覆去的踩,由于这些血淋林的教训,所以从现在开始,每次学了新的东西都要来写个博客做个记录总结一下了。

最近在学习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_state_diagram.gif

从图中可以看出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

如果在阅读的过程中又发现错误,也欢迎留言纠错。

上一篇下一篇

猜你喜欢

热点阅读