摘要
本文介绍使用MediaRecorder进行录制音频、录制视频学习,熟悉MediaRecorder执行流程,通过简单的Demo结合解释运行效果,最后封装MediaRecorder的API工具,实现常见比如:微信、QQ、易信、人人、支付宝等录音功能模块开发,最后测试效果。
目录:
- MediaRecorder概念
- 执行流程图
- 简单Demo介绍
-
- 封装API
- getMaxAmplitude()方法介绍
- MediaUtil封装类工具
- 类工具使用介绍
- 测试
概念
MediaRecorder录制音频、视频文件时,需要注意:Android模拟器不具备录制音频的功能,在具备录音功能的真机测试,下面是使用MediaRecorder通用的开发步骤:
1、创建一个MediaRecorder实例
2、设置音频源setAudioSource(),你可能使用MediaRecorder.AudioSource.MIC
3、设置输出文件格式,用MediaRecorder.setOutputFormat()
4、设置输出文件名,用MediaRecorder.setOutputFile()
5、设置音频编码,用MediaRecorder.setAudioEncoder()
6、回调MediaRecorder.prepare()方法
7、开始录制音频MediaRecorder.start()
8、停止录制音频MediaRecorder.stop()
9、当你使用MediaRecorder实例录制音频回调MediaRecorder.release()方法立即释放资源
下面是通用的配置代码:
- MediaRecorder recorder = new MediaRecorder();
- recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- recorder.setOutputFile(PATH_NAME);
- recorder.prepare();
- recorder.start(); // Recording is now started
- ...
- recorder.stop();
- recorder.reset(); // You can reuse the object by going back to setAudioSource() step
- recorder.release(); // Now the object cannot be reused
MediaRecorder在录制时采用注册监听器的方式获得更新或异常错误的事件消息,比如:setOnInfoListener(OnInfoListener)、setOnErrorListener(OnErrorListener),接收与监听相关的回调方法,MediaRecorder需要运行在循环的Thread线程中,默认UI Thread是循环的线程。
执行流程图
详情参考:官方文档
简单Demo介绍
布局文件
布局文件放置两个按钮,一个录制音频按钮,点击开始录制,再次点击停止录制;一个播放按钮,点击播放,再次点击停止播放,代码如下:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="${relativePackage}.${activityClass}" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_above="@+id/record_autio"
- android:text="@string/hello_world"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="20dp"
- android:id="@+id/system_time"/>
- <Button
- android:id="@+id/record_autio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="点击录音" />
- <Button
- android:id="@+id/play_autio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/record_autio"
- android:layout_centerHorizontal="true"
- android:text="点击播放" />
- </RelativeLayout>
MainActivity设计
MainActivity的代码比较简单,直接看就可以了,在设计上尽量让代码之间的耦合性降低,写了onRecord()和onPlay()方法,根据传入的value分别执行startRecording()、stopRecording()方法,在按钮点击后处理状态的变化,代码如下:
- package cn.teachcourse.activity;
- import android.app.Activity;
- import android.media.MediaPlayer;
- import android.media.MediaRecorder;
- import android.os.Bundle;
- import android.os.Environment;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.TextView;
- import java.io.File;
- import java.io.IOException;
- public class MainActivity extends Activity implements OnClickListener {
- private static final String LOG_TAG = "AudioRecordTest";
- private Button mRecordButton;
- private Button mPlayButton;
- private TextView mSysTime_TV;
- private String mSavePath=null;
- private File mRootPath;
- private MediaRecorder mMediaRecorder;
- private MediaPlayer mPlayer;
- boolean mStartRecording=true;
- boolean mStartPlaying=true;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- mRootPath = Environment.getExternalStorageDirectory();
- mSavePath=mRootPath.getAbsolutePath()+ "/recordAudio.3gp";
- }
- private void initView() {
- mRecordButton = (Button) findViewById(R.id.record_autio);
- mPlayButton = (Button) findViewById(R.id.play_autio);
- mSysTime_TV = (TextView) findViewById(R.id.system_time);
- mRecordButton.setOnClickListener(this);
- mPlayButton.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.play_autio:
- onPlay(mStartPlaying);
- if(mStartPlaying){
- mPlayButton.setText("正在播放。。。");
- }else{
- mPlayButton.setText("点击播放");
- }
- mStartPlaying=!mStartPlaying;
- break;
- case R.id.record_autio:
- onRecord(mStartRecording);
- if(mStartRecording){
- mRecordButton.setText("正在录音。。。");
- }else{
- mRecordButton.setText("点击录音");
- }
- mStartRecording=!mStartRecording;
- break;
- }
- }
- private void onRecord(boolean start) {
- if(start){
- startRecording();
- }else{
- stopRecording();
- }
- }
- private void onPlay(boolean start) {
- if(start){
- startPlaying();
- }else{
- stopPlaying();
- }
- }
- private void stopPlaying() {
- mPlayer.release();
- mPlayer = null;
- }
- private void startPlaying() {
- mPlayer = new MediaPlayer();
- try {
- mPlayer.setDataSource(mSavePath);
- mPlayer.prepare();
- mPlayer.start();
- } catch (IOException e) {
- Log.e(LOG_TAG, "prepare() failed");
- }
- }
- private void startRecording() {
- mMediaRecorder = new MediaRecorder();
- mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mMediaRecorder.setOutputFile(mSavePath);
- try {
- mMediaRecorder.prepare();
- } catch (IOException e) {
- Log.e(LOG_TAG, "prepare() failed");
- e.printStackTrace();
- }
- mMediaRecorder.start();
- }
- private void stopRecording() {
- mMediaRecorder.stop();
- mMediaRecorder.release();
- mMediaRecorder = null;
- mSysTime_TV.setText("保存的文件:"+mSavePath);
- }
- @Override
- protected void onPause() {
- super.onPause();
- if (mMediaRecorder != null) {
- mMediaRecorder.release();
- mMediaRecorder = null;
- }
- if (mPlayer != null) {
- mPlayer.release();
- mPlayer = null;
- }
- }
- }
测试效果
封装API
getMaxAmplitude()方法介绍
MediaRecorder里面有提供的getMaxAmplitude ()方法,该方法返回上次调用setMaxAmplitude()采集到的最大振幅,一个int整数,如下图:
获取振幅的强弱,可以设置类似微信语音的效果,根据说话声音振幅强弱的动画显示图标,测试效果
需要注意的,指定保存录音文件时,如果当前路径下的文件夹不存在,首先执行文件夹的创建,然后再保存录音文件,保存未指定setOutputFile(mSavePath)中的mSavePath,无法录音。
MediaUtil封装类工具
封装好需要调用的MediaRecorder方法,比如共同的代码封装到start()方法中,停止录音封装到stop()方法中,获取振幅大小封装到getAmplitude()方法,采用单例的设计模式,代码如下:
- package cn.teachcourse.api;
- import java.io.File;
- import java.io.IOException;
- import android.os.Environment;
- import android.media.MediaRecorder;
- /**
- * Created by postmaster@teachcourse.cn on 2016/3/1.
- */
- public class MediaUtilAPI {
- private transient static MediaUtilAPI instance = null;
- public static synchronized MediaUtilAPI getInstance() {
- if (instance == null) {
- instance = new MediaUtilAPI();
- }
- return instance;
- }
- private File file;
- private MediaRecorder mRecorder = null;
- public void start(String name) {
- if (!Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return;
- }
- file = new File(android.os.Environment.getExternalStorageDirectory()
- + "/" + name);
- if (mRecorder == null) {
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setAudioSamplingRate(8000);
- mRecorder.setAudioEncodingBitRate(16);
- mRecorder.setAudioChannels(1);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(file.getAbsolutePath());
- try {
- mRecorder.prepare();
- mRecorder.start();
- } catch (IllegalStateException e) {
- System.out.print(e.getMessage());
- } catch (IOException e) {
- System.out.print(e.getMessage());
- }
- }
- }
- public void stop() {
- if (mRecorder != null) {
- try {
- mRecorder.setOnErrorListener(null);
- mRecorder.stop();
- mRecorder.release();
- mRecorder = null;
- } catch (RuntimeException e) {
- e.printStackTrace();
- }
- }
- }
- public int getAmplitude() {
- if (mRecorder != null)
- return mRecorder.getMaxAmplitude();
- else
- return 0;
- }
- }
类工具使用介绍
按钮添加一个长按事件,在按钮的状态显示录音强弱的图标,按钮松开状态录音结束并且图标消失,如下代码:
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- saveRecordFileNameLong= SystemClock.currentThreadTimeMillis();
- mMediaRecorder.start(saveRecordFileNameLong + ".amr");
- mAudioViewState.setVisibility(View.VISIBLE);
- getAmplitude();
- Log.e(LOG_TAG, "长按按钮:------------------->");
- break;
- case MotionEvent.ACTION_UP:
- mMediaRecorder.stop();
- mAudioViewState.setVisibility(View.GONE);
- break;
- }
- return false;
- }
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- }
- };
- private void getAmplitude() {
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- int mAmplitudeValue = mMediaRecorder.getAmplitude();
- updateViewByAmplitudeValue(mAmplitudeValue);
- mHandler.postDelayed(this, 300);
- }
- }, 300);
- }
MediaRecorder录制音频的MediaUtilApi工具封装完成,想要实现类似微信录音、QQ语音、易信语音或人人语音的功能,修改updateViewByAmplitudeValue中的代码、同时修改布局文件,感觉也不是特么困难的事情吧!!
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/1514.html ,谢谢支持!