您的位置:首页 > 移动开发 > Android开发

Android MediaRecorder实现暂停断点录音功能

2014-02-27 08:34 751 查看
Android MediaRecorder实现暂停断点录音功能

最近研究了下MediaRecorder的录音功能,发现暂停之后,继续录音这个功能,网上参考的资料比较少,现在将自己的学习成果分享大家:

基本原理如下:MediaRecorder通过MIC录音,系统没有自带的pause功能,每次暂停录音,都会结束本次的录音。现在本人的设计思路是:MediaRecorder录音暂停时,保存这段所录下的音频A,继续录音后,再次暂停,保留录音音频B;以此类推直到最终的录音结束时,依次读取之前保存的A、B……的录音文件,并将其合并在一起。涉及的技术:文件的保存读取、音频的合并等

音频的合并:设置MediaRecorder的音频输出格式mMediaRecorder01.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);

mMediaRecorder01 .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);输出的是amr格式。amr的音频文件的文件头,相对来说是固定的6个字节的固定字符,A.amr文件和B.amr文件的合并,只需将B以字节流读取,去掉前6个字节,和A的字节流合并后保存,就实现了音频合并,不涉及复杂的音频编码问题。(MediaRecorder的音频输出格式比较多,有jpgg、MP3等之类的格式,合成的原理大同小异,只需要注意他们的音频文件头的格式就可以了。)

资源代码:

http://download.csdn.net/detail/wanli_smile/4410240

有图有真相:









[java] view
plaincopy

public class EX07 extends Activity {

private ImageButton myButton1;

private ImageButton myButton2;

private ImageButton myButton3;

private ImageButton myButton4;

private Button myButton;

private ListView myListView1;

private String strTempFile = "YYT_";

private File myRecAudioFile;

/**录音保存路径**/

private File myRecAudioDir;

private File myPlayFile;

private MediaRecorder mMediaRecorder01;

private int mMinute;

private boolean xx=true;

/**存放音频文件列表**/

private ArrayList<String> recordFiles;

private ArrayAdapter<String> adapter;

private TextView myTextView1;

/**文件存在**/

private boolean sdcardExit;

/**是否停止录音**/

private boolean isStopRecord;

/**按钮背景图片的标志位**/

private boolean sigle = false;

private String length1 = null;

private final String SUFFIX=".amr";

/**暂停按钮**/

Button buttonpause;

/**记录需要合成的几段amr语音文件**/

private ArrayList<String> list;

int second=0;

int minute=0;

/**计时器**/

Timer timer;

/**是否暂停标志位**/

private boolean isPause;

/**在暂停状态中**/

private boolean inThePause;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

//暂停标志位 为false

isPause=false;

//暂停状态标志位

inThePause=false;

//初始化list

list=new ArrayList<String>();

//四个按钮

myButton1 = (ImageButton) findViewById(R.id.ImageButton01);

myButton2 = (ImageButton) findViewById(R.id.ImageButton02);

myButton3 = (ImageButton) findViewById(R.id.ImageButton03);

myButton4 = (ImageButton) findViewById(R.id.ImageButton04);

myButton = (Button) findViewById(R.id.myButton);

buttonpause=(Button)findViewById(R.id.mypuase);

myListView1 = (ListView) findViewById(R.id.ListView01);

myTextView1 = (TextView) findViewById(R.id.TextView01);

myButton2.setEnabled(false);

myButton3.setEnabled(false);

myButton4.setEnabled(false);

myPlayFile=null;

// 判断sd Card是否插入

sdcardExit = Environment.getExternalStorageState().equals(

android.os.Environment.MEDIA_MOUNTED);

// 取得sd card路径作为录音文件的位置

if (sdcardExit){

String pathStr = Environment.getExternalStorageDirectory().getPath()+"/YYT";

myRecAudioDir= new File(pathStr);

if(!myRecAudioDir.exists()){

myRecAudioDir.mkdirs();

Log.v("录音", "创建录音文件!" + myRecAudioDir.exists());

}

// Environment.getExternalStorageDirectory().getPath() + "/" + PREFIX + "/";

}

// 取得sd card 目录里的.arm文件

getRecordFiles();

adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_list_item_1, recordFiles);

// 将ArrayAdater添加ListView对象中

myListView1.setAdapter(adapter);

// 录音

myButton1.setOnClickListener(new ImageButton.OnClickListener() {

@Override

public void onClick(View v) {

second=0;

minute=0;

list.clear();

// Calendar c=Calendar.getInstance();

// int mMinute1=c.get(Calendar.MINUTE);

sigle = true;

// TODO Auto-generated method stub

start();

if (sigle = false) {

myButton1.setBackgroundResource(R.drawable.record_hover1);

} else {

myButton1.setBackgroundResource(R.drawable.record_dis1);

myButton2.setBackgroundResource(R.drawable.stop_hover2);

myButton3.setBackgroundResource(R.drawable.play_hover1);

myButton4.setBackgroundResource(R.drawable.delete_hover);

}

}

});

// 停止

myButton2.setOnClickListener(new ImageButton.OnClickListener() {

@Override

public void onClick(View v) {

xx=false;

sigle = true;

timer.cancel();

// TODO Auto-generated method stub

//这里写暂停处理的 文件!加上list里面 语音合成起来

if(isPause){

//在暂停状态按下结束键,处理list就可以了

if(inThePause){

getInputCollection(list, false);

}

//在正在录音时,处理list里面的和正在录音的语音

else{

list.add(myRecAudioFile.getPath());

recodeStop();

getInputCollection(list, true);

}

//还原标志位

isPause=false;

inThePause=false;

buttonpause.setText("暂停录音");

// adapter.add(myRecAudioFile.getName());

}

//若录音没有经过任何暂停

else{

if (myRecAudioFile != null) {

// 停止录音

mMediaRecorder01.stop();

mMediaRecorder01.release();

mMediaRecorder01 = null;

// 将录音频文件给Adapter

adapter.add(myRecAudioFile.getName());

DecimalFormat df = new DecimalFormat("#.000");

if (myRecAudioFile.length() <= 1024*1024) {

//length1 = (myRecAudioFile.length() / 1024.0)+"";

length1=df.format(myRecAudioFile.length() / 1024.0)+"K";

} else {

//length1 = (myRecAudioFile.length() / 1024.0 / 1024)+"";

//DecimalFormat df = new DecimalFormat("#.000");

length1=df.format(myRecAudioFile.length() / 1024.0 / 1024)+"M";

}

System.out.println(length1);

myTextView1.setText("停 止" + myRecAudioFile.getName()

+ "文件大小为:" + length1);

myButton2.setEnabled(false);

}

}

if (sigle = false) {

myButton2.setBackgroundResource(R.drawable.stop_hover2);

} else {

myButton1.setBackgroundResource(R.drawable.record_hover1);

myButton2.setBackgroundResource(R.drawable.stop1);

myButton3.setBackgroundResource(R.drawable.play_hover1);

myButton4.setBackgroundResource(R.drawable.delete_hover);

}

//停止录音了

isStopRecord = true;

}

});

// 播放

myButton3.setOnClickListener(new ImageButton.OnClickListener() {

@Override

public void onClick(View v) {

sigle = true;

// TODO Auto-generated method stub

if (myPlayFile != null && myPlayFile.exists()) {

// 打开播放程序

openFile(myPlayFile);

} else {

Toast.makeText(EX07.this, "你选的是一个空文件", Toast.LENGTH_LONG)

.show();

Log.d("没有选择文件","没有选择文件");

}

if (sigle = false) {

myButton3.setBackgroundResource(R.drawable.play_hover1);

} else {

myButton1.setBackgroundResource(R.drawable.record_hover1);

myButton2.setBackgroundResource(R.drawable.stop_hover2);

myButton3.setBackgroundResource(R.drawable.play1);

myButton4.setBackgroundResource(R.drawable.delete_hover);

}

}

});

// 删除

myButton4.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

sigle = true;

// TODO Auto-generated method stub

if (myPlayFile != null) {

// 先将Adapter删除文件名

adapter.remove(myPlayFile.getName());

// 删除文件

if (myPlayFile.exists())

myPlayFile.delete();

myTextView1.setText("完成删除!");

}

if (sigle = false) {

myButton4.setBackgroundResource(R.drawable.delete_hover);

} else {

myButton1.setBackgroundResource(R.drawable.record_hover1);

myButton2.setBackgroundResource(R.drawable.stop_hover2);

myButton3.setBackgroundResource(R.drawable.play_hover1);

myButton4.setBackgroundResource(R.drawable.delete_dis);

}

}

});

/**

* 暂停按钮,记录之前保存的语音文件

*/

buttonpause.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

isPause=true;

//已经暂停过了,再次点击按钮 开始录音,录音状态在录音中

if(inThePause){

buttonpause.setText("暂停录音");

start();

inThePause=false;

}

//正在录音,点击暂停,现在录音状态为暂停

else{

//当前正在录音的文件名,全程

list.add(myRecAudioFile.getPath());

inThePause=true;

recodeStop();

//start();

buttonpause.setText("继续录音");

//计时停止

timer.cancel();

}

}

});

myListView1

.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> arg, View arg1,

int arg2, long arg3) {

// TODO Auto-generated method stub

// 当有单点击文件名时将删除按钮及播放按钮Enable

myButton3.setEnabled(true);

myButton4.setEnabled(true);

myPlayFile = new File(myRecAudioDir.getAbsolutePath()

+ File.separator

+ ((TextView) arg1).getText().toString());

DecimalFormat df = new DecimalFormat("#.000");

if (myPlayFile.length() <= 1024*1024) {

length1=df.format(myPlayFile.length() / 1024.0)+"K";

} else {

length1=df.format(myPlayFile.length() / 1024.0/1024)+"M";

}

myTextView1.setText("你选的是"

+ ((TextView) arg1).getText().toString()

+ "文件大小为:" + length1);

Toast.makeText(EX07.this,"你选的是" + (((TextView) arg1).getText())+ "文件大小为:" + length1,

Toast.LENGTH_LONG).show();

}

});

myButton.setOnClickListener(new Button.OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

showSize show = new showSize();

String text = show.showsize();

Toast.makeText(EX07.this, text, Toast.LENGTH_LONG).show();

}

});

}

protected void recodeStop() {

if (mMediaRecorder01 != null && !isStopRecord) {

// 停止录音

mMediaRecorder01.stop();

mMediaRecorder01.release();

mMediaRecorder01 = null;

}

timer.cancel();

}

/**

* activity的生命周期,stop时关闭录音资源

*/

@Override

protected void onStop() {

// TODO Auto-generated method stub

if (mMediaRecorder01 != null && !isStopRecord) {

// 停止录音

mMediaRecorder01.stop();

mMediaRecorder01.release();

mMediaRecorder01 = null;

}

super.onStop();

}

/**

* 获取目录下的所有音频文件

*/

private void getRecordFiles() {

// TODO Auto-generated method stub

recordFiles = new ArrayList<String>();

if (sdcardExit) {

File files[] = myRecAudioDir.listFiles();

if (files != null) {

for (int i = 0; i < files.length; i++) {

if (files[i].getName().indexOf(".") >= 0) { // 只取.amr 文件

String fileS = files[i].getName().substring(

files[i].getName().indexOf("."));

if (fileS.toLowerCase().equals(".mp3")

|| fileS.toLowerCase().equals(".amr")

|| fileS.toLowerCase().equals(".mp4"))

recordFiles.add(files[i].getName());

}

}

}

}

}

// 打开录音播放程序

private void openFile(File f) {

Intent intent = new Intent();

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction(android.content.Intent.ACTION_VIEW);

String type = getMIMEType(f);

intent.setDataAndType(Uri.fromFile(f), type);

startActivity(intent);

// Uri uri=Uri.fromFile(f);

// MediaPlayer mediaPlayer=MediaPlayer.create(this, uri);

// try {

// mediaPlayer.prepare();

// } catch (IllegalStateException e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// } catch (IOException e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }

// mediaPlayer.start();

}

private String getMIMEType(File f) {

String end = f.getName().substring(f.getName().lastIndexOf(".") + 1,

f.getName().length()).toLowerCase();

String type = "";

if (end.equals("mp3") || end.equals("aac") || end.equals("amr")

|| end.equals("mpeg") || end.equals("mp4")) {

type = "audio";

} else if (end.equals("jpg") || end.equals("gif") || end.equals("png")

|| end.equals("jpeg")) {

type = "image";

} else {

type = "*";

}

type += "/";

return type;

}

private void start(){

TimerTask timerTask=new TimerTask() {

@Override

public void run() {

// TODO Auto-generated method stub

second++;

if(second>=60){

second=0;

minute++;

}

handler.sendEmptyMessage(1);

}

};

timer=new Timer();

timer.schedule(timerTask, 1000,1000);

try {

if (!sdcardExit) {

Toast.makeText(EX07.this, "请插入SD card",

Toast.LENGTH_LONG).show();

return;

}

String mMinute1=getTime();

Toast.makeText(EX07.this, "当前时间是:"+mMinute1,Toast.LENGTH_LONG).show();

// 创建音频文件

// myRecAudioFile = File.createTempFile(mMinute1, ".amr",

// myRecAudioDir);

myRecAudioFile=new File(myRecAudioDir,mMinute1+SUFFIX);

mMediaRecorder01 = new MediaRecorder();

// 设置录音为麦克风

mMediaRecorder01

.setAudioSource(MediaRecorder.AudioSource.MIC);

mMediaRecorder01

.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);

mMediaRecorder01

.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

//录音文件保存这里

mMediaRecorder01.setOutputFile(myRecAudioFile

.getAbsolutePath());

mMediaRecorder01.prepare();

mMediaRecorder01.start();

// mMediaRecorder01.getMaxAmplitude();

// mMediaRecorder01.getAudioSourceMax();

mMediaRecorder01.setOnInfoListener(new OnInfoListener() {

@Override

public void onInfo(MediaRecorder mr, int what, int extra) {

// TODO Auto-generated method stub

int a=mr.getMaxAmplitude();

Toast.makeText(EX07.this, a, 500).show();

}

});

myTextView1.setText("录音中......");

myButton2.setEnabled(true);

myButton3.setEnabled(false);

myButton4.setEnabled(false);

isStopRecord = false;

} catch (IOException e) {

e.printStackTrace();

}

}

private String getTime(){

SimpleDateFormat formatter = new SimpleDateFormat ("yyyy年MM月dd日HH:mm:ss");

Date curDate=new Date(System.currentTimeMillis());//获取当前时间

String time = formatter.format(curDate);

System.out.println("当前时间");

return time;

}

Handler handler=new Handler(){

@Override

public void handleMessage(Message msg) {

// TODO Auto-generated method stub

super.handleMessage(msg);

myTextView1.setText("录音时间:"+minute+":"+second);

}

};

/**

* @param isAddLastRecord 是否需要添加list之外的最新录音,一起合并

* @return 将合并的流用字符保存

*/

public void getInputCollection(List list,boolean isAddLastRecord){

String mMinute1=getTime();

Toast.makeText(EX07.this, "当前时间是:"+mMinute1,Toast.LENGTH_LONG).show();

// 创建音频文件,合并的文件放这里

File file1=new File(myRecAudioDir,mMinute1+SUFFIX);

FileOutputStream fileOutputStream = null;

if(!file1.exists()){

try {

file1.createNewFile();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

try {

fileOutputStream=new FileOutputStream(file1);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//list里面为暂停录音 所产生的 几段录音文件的名字,中间几段文件的减去前面的6个字节头文件

for(int i=0;i<list.size();i++){

File file=new File((String) list.get(i));

Log.d("list的长度", list.size()+"");

try {

FileInputStream fileInputStream=new FileInputStream(file);

byte []myByte=new byte[fileInputStream.available()];

//文件长度

int length = myByte.length;

//头文件

if(i==0){

while(fileInputStream.read(myByte)!=-1){

fileOutputStream.write(myByte, 0,length);

}

}

//之后的文件,去掉头文件就可以了

else{

while(fileInputStream.read(myByte)!=-1){

fileOutputStream.write(myByte, 6, length-6);

}

}

fileOutputStream.flush();

fileInputStream.close();

System.out.println("合成文件长度:"+file1.length());

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

//结束后关闭流

try {

fileOutputStream.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//加上当前正在录音的这一段

// if(isAddLastRecord){

//

//

// //刚刚录音的

// try {

// FileInputStream fileInputStream=new FileInputStream(myRecAudioFile);

// byte []myByte=new byte[fileInputStream.available()];

// System.out.println(fileInputStream.available()+"");

// while(fileInputStream.read(myByte)!=-1){

// //outputStream.

// fileOutputStream.write(myByte, 6, (fileInputStream.available()-6));

// }

//

// fileOutputStream.flush();

// fileInputStream.close();

// fileOutputStream.close();

// System.out.println("合成文件长度:"+file1.length());

// } catch (Exception e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }

//

// }

//合成一个文件后,删除之前暂停录音所保存的零碎合成文件

deleteListRecord(isAddLastRecord);

//

adapter.add(file1.getName());

}

private void deleteListRecord(boolean isAddLastRecord){

for(int i=0;i<list.size();i++){

File file=new File((String) list.get(i));

if(file.exists()){

file.delete();

}

}

//正在暂停后,继续录音的这一段音频文件

if(isAddLastRecord){

myRecAudioFile.delete();

}

}

}

转: http://blog.csdn.net/wanli_smile/article/details/7715030
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: