最近研究了下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等之类的格式,合成的原理大同小异,只需要注意他们的音频文件头的格式就可以了。)资源代码:
免费下载地址在 http://linux.linuxidc.com/
用户名与密码都是www.linuxidc.com
具体下载目录在 /2012年资料/7月/4日/Android MediaRecorder实现暂停断点录音功能有图有真相:
- 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")
- &