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

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

2015-01-08 15:09 639 查看
基本原理如下: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等之类的格式,合成的原理大同小异,只需要注意他们的音频文件头的格式就可以了。)



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();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: