zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }

     

     

  • 相关阅读:
    mysql in 的另一种替换方法
    js 的一些总结
    医院收费系统 一点的简单总结
    物流系统
    mysqldump备份还原和mysqldump导入导出语句大全详解
    android 环境待建遇到的问题
    EXT CheckboxSelectionModel 多选效果
    Ext Grid动态生成Column的实现方式
    Javascript对象继承(原型继承法)
    ExtJS中grid的JsonStore、Ext.PagingToolbar带条件查询问题
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/4211028.html
Copyright © 2011-2022 走看看