Android 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);
        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();
        }
    }
}

 

 

原文地址:https://www.cnblogs.com/zhujiabin/p/4211028.html