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

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

    最近研究了下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://download.csdn.net/detail/wanli_smile/4410240

有图有真相:

 

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


 

技术交流群:

187651345

 

 

 

 

 

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值