Android MediaRecorder实现暂停断点录音功能
来源:互联网 发布:北京配眼镜 知乎 编辑:程序博客网 时间:2024/04/28 04:03
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
有图有真相:
- 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();
- }
- }
- }
- Android MediaRecorder实现暂停断点录音功能
- Android MediaRecorder实现暂停断点录音功能
- Android MediaRecorder实现暂停断点录音功能
- Android MediaRecorder实现暂停断点录音功能
- Android MediaRecorder实现暂停断点录音功能
- Android MediaRecorder实现暂停断点录音功能
- android mediarecord 实现暂停断点录音功能
- android mediarecord 实现暂停断点录音功能
- Android使用MediaRecorder实现录音功能
- Android使用MediaRecorder实现录音功能
- Android 实现能够暂停的录音功能
- Android 实现能够暂停的录音功能
- Android 实现能够暂停的录音功能
- MediaRecorder实现手机录音功能
- Android使用MediaRecorder实现录音功能相关知识
- 【Android】媒体——利用MediaRecorder实现录音对讲功能
- android MediaRecorder实现录音功能 显示时间 计时
- android使用MediaRecorder实现录音
- IOS下的ffmpeg解码
- Java事件机制---自定义事件
- android ndk环境搭建
- 在Ubuntu12.04 64位上编译hadoop2.2.0
- ACE学习一:ACE的体系结构
- Android MediaRecorder实现暂停断点录音功能
- Android GPS定位 获取经纬度
- Eigen 3.2.1相对上一次3.2.0有关键的一些bug修正
- eclipse 改xml大小
- MP3文件格式解析
- eclipse打开报"Failed to load the JNI shared library"解决方案
- 认识Tempdb----排除日常问题
- AMR文件格式分析
- Linux查看进程命令