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

原帖:http://www.th7.cn/Program/Android/201210/107798.shtml


最近研究了下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等之类的格式,合成的原理大同小异,只需要注意他们的音频文件头的格式就可以了。)

 

 

 

有图有真相:

 

/

/

/

/

 

 

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); 
        buttοnpause=(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(); 
        } 
    } 
} 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值