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();
        }
    }
}
时间: 2024-10-10 19:22:48

Android MediaRecorder实现暂停断点录音功能的相关文章

Android 实现能够暂停的录音功能

转载请注明出处:http://blog.csdn.net/yegongheng/article/details/40624267 好久没更新博客了,着实有点惭愧,以后不管工作是忙是闲都得坚持更新博客,持之以恒地做下去! 正式进入主题,今天我分享一个在工作中过程中遇到的一个技术难点以及我解决该难点的方案,该问题困扰了我许久,通过不断地研究和翻阅资料,终于在满足工作需求的情况下将该问题解决,希望我的经验能够对读者有所帮助.我们知道Android ApI提供了MediaRecorder和AudioRe

Android 能够暂停的录音功能

Android ApI提供了MediaRecorder和AudioRecord两个类给开发者来很方便地实现音视频的录制(前者可以实现音频和视频的录制,后者只能实 现音频的录制).这两个类都提供了start()和stop()方法用于开始和结束音频或视频的录制,但令人费解的是这两个类都没有提供pause()方 法用于暂停录制音视频,因为在实际应用当中,暂停录制的功能是非常有必要的Android 实现能够暂停的录音功能 需实现音频录制的暂停功能,并且生成的音频文件格式必须是m4a格式 为什么项目中音频

使用Android studio如何开展断点调试

熟悉android开发的童鞋应该对Android studio都不陌生,它是android开发中最常用的开发环境之一,在程序开发中,我们常常需要进行断点调试,那在android studio中,如何开展断点调试呢?那下面我们就一起来看看具体的方法和步骤吧. 在开展断点调试前,你需要先编译好要调试的程序,然后按照下面的步骤,开展调试工作. 1.设置断点 选定要设置断点的代码行,并在行号的区域后面单击鼠标左键即可. 2.开启调试会话 点击红色箭头指向的小虫子,开始进入调试环节. IDE下方出现Deb

android MediaRecorder录制音频

使用MediaRecorder录制音频步骤: 创建MediaRecorder对象 调用MediaRecorder的setAudioSource()方法设置声音来源,一般传入MediaRecorder.AudioSource.MIC参数指定录制来自麦克风的声音 调用MediaRecorder对象的setOutputFormat()设置所录制的音频 文件的格式 调用MediaRecorder对象的setAudioEncoder() ,setAudioEncodingBitRate(int bitRa

Android MediaRecorder录音与播放

上一篇讲到了使用意图录音,这篇文章将使用MediaRecorder类来录音,从而提供更多的灵活性. 效果图: 源代码奉上: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" andr

Android MediaRecorder

MediaRecorder recorder; Camera camera; SurfaceView preview; SurfaceHolder holder; boolean isRecording = false; String TAG = "Evolution Camera"; int frameRate = 30; public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_

Android/java http多线程断点下载(附源码)

先看下项目结构: http多线程断点下载涉及到 数据库,多线程和http请求等几个模块,东西不是很多,想弄清楚也不是很困难,接下来我和大家分享下我的做法. 一.先看MainActivity.java 成员变量,主要是一些下载过程的变量和handler private String path = "http://192.168.1.3:8080/wanmei/yama.apk"; private String sdcardPath; private int threadNum = 5;

android studio学习----调试---断点调试

Android Studio调试其实也非常方便,一般问题直接通过AS的DDMS的Logcat就可以搞定.AS支持类似Eclipse的DDMS的所有功能.这里要说的是疑难问题的调试方式,即断点调试. 首先先编译好要调试的程序. 如上图2所示在行号处点击设置断点.然后如1所示点击开启调试会话. 如上图所示,IDE下方出现Debug视图,1指向的是现在调试程序停留的代码行,2区域是程序的方法调用栈区.在这个区域中显示了程序执行到断点处所调用过的所用方法,越下面的方法被调用的越早.由此顺序想必有些And

利用 android mediaRecorder c++类进行视频编码

本例中media source为camera.(学习的平台是android sdk6.0) 调用关系图: startRecording: recorder = New MediaRecorder(String16()); classMediaRecorder : public BnMediaRecorderClient, public virtualIMediaDeathNotifier 在创建mediaRecorder的时侯,我们先获取IMediaPlayerService指针,然后再创建IM