【Android】利用MediaRecorder实现录音对讲功能

看到QQ,微信都有对讲功能,多高大上啊,咋们也来弄一个看看效果。。





这就是效果啦!然后贴代码:

package cn.com.zte.uc.ui;


import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Dialog;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import cn.com.zte.uc.R;
import cn.com.zte.uc.utils.MediaUtils;

public class RecorderDialog extends Dialog {
	
	private static final long MAX_DURATION = 60000;
	
	private static final long SECOND = 1000;

	private TextView tv;
	
	private View v;
	
	private Timer time;
	
	private MyTimerTask task;
	
	private MediaRecorder recorder;
	
	private long duration;
	
	private int[] values = {R.drawable.bg_recorder_value_0, R.drawable.bg_recorder_value_1,
			R.drawable.bg_recorder_value_2, R.drawable.bg_recorder_value_3, R.drawable.bg_recorder_value_4,
			R.drawable.bg_recorder_value_5, R.drawable.bg_recorder_value_6, R.drawable.bg_recorder_value_7, 
			R.drawable.bg_recorder_value_8};
	
	public RecorderDialog(Context context) {
		super(context, R.style.style_dialog);
		setContentView(R.layout.dlg_recorder);
		time = new Timer();
		tv = (TextView) findViewById(R.id.tv_duration);
		v = findViewById(R.id.ll_rec);
	}
	
	public void show(String path) {
		tv.setText("60\"");
		setDuration(0);
		recorder = MediaUtils.getRecorder(path);
		try {
			recorder.prepare();
			recorder.start();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		task = new MyTimerTask();
		time.schedule(task, SECOND, 100);
		super.show();
	}
	
	public void show() {
		
	}
	
	@Override
	public void dismiss() {
		if(!isShowing()) {
			return;
		}
		super.dismiss();
		try{
			task.cancel();
			recorder.stop();
			recorder.release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public int getDuration() {
		return (int)(duration/SECOND);
	}

	public void setDuration(int duration) {
		this.duration = duration * SECOND;
	}

	class MyTimerTask extends TimerTask {
		@Override
		public void run() {
			
			int ratio = recorder.getMaxAmplitude() / 600;
			int db = 0;// 分贝 也可以理解为定义的音量大小
			if (ratio > 1)
			db = (int) (20 * Math.log10(ratio));//db就是我们需要取得的音量的值。
			//(int) (20 * Math.log10(ratio))振幅和音量大小的公式
			//BASE的值由自己测试获得,我是怎么获取这个值得呢?
			//开启麦克风,不对麦克风说话,而由周围噪声获取的值  大概在300到600之间  我取得是600这个基准值。
			handler.sendEmptyMessage(db/5);
		}
		
	}
	
	Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			if(msg.what >= values.length) {
				msg.what = values.length - 1;
			}
			v.setBackgroundResource(values[msg.what]);
			if(duration == MAX_DURATION) {
				dismiss();
			} else {
				duration += 100;
			}
			System.out.println(duration);
			tv.setText((MAX_DURATION - duration)/SECOND + "\"");
		};
	};
}

还有一个工具类:

/*
 * 媒体 相关工具类
 * 封宸落宇
 */
package cn.com.zte.uc.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import android.media.MediaRecorder;
import android.util.Log;
import cn.com.zte.uc.constant.Constants;

public class MediaUtils {
	/**
	 * 获取一个mediaRecorder对象,输出amr文件到path
	 * 
	 * @param path
	 * @return
	 */
	public static MediaRecorder getRecorder(String path) {
		MediaRecorder recorder = new MediaRecorder();
		File file = new File(Constants.SDCARD_PATH + "RECORD" + File.separator);
		if (!file.exists()) {
			file.mkdirs();
		}
		file = new File(path);
		if (file.exists()) {
			file.delete();
		}
		try {
			file.createNewFile();
		} catch (IOException e) {
			Log.e("recorder", "create new MediaRecorder file error!");
		}
		recorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 录制的声音的来源
		recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
		recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
		recorder.setOutputFile(file.getAbsolutePath());
		recorder.setAudioSamplingRate(8000);
		recorder.setAudioEncodingBitRate(16);
		return recorder;
	}

	/**
	 * 使用SD卡上的录音
	 * 
	 * @throws FileNotFoundException
	 * 
	 */
	public static byte[] loadSDCardRecordFile(String path)
			throws FileNotFoundException {
		if (StringUtils.isEmpty(path)) {
			return null;
		}
		byte[] img = null;
		File file = new File(path);
		if (file.exists()) {
			byte[] temp = new byte[4096];
			FileInputStream fos = null;
			ByteArrayOutputStream out = null;
			try {
				fos = new FileInputStream(file);
				out = new ByteArrayOutputStream();
				int size = 0;
				while ((size = fos.read(temp)) != -1) {
					out.write(temp, 0, size);
				}
				img = out.toByteArray();
			} catch (Exception e) {
				Log.e("recorder", "io error!");
			} finally {
				try {
					if (fos != null) {
						fos.close();
					}
					if (out != null) {
						out.close();
					}
				} catch (IOException e) {
					Log.e("recorder", "io error!");
				}
			}
		}

		return img;
	}
	/**
	 * 得到amr文件的时长
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public static long getAmrDuration(String path) throws IOException {
		File file = new File(path);
		long duration = -1;
		int[] packedSize = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0,
				0, 0 };
		RandomAccessFile randomAccessFile = null;
		try {
			randomAccessFile = new RandomAccessFile(file, "rw");
			long length = file.length();// 文件的长度
			int pos = 6;// 设置初始位置
			int frameCount = 0;// 初始帧数
			int packedPos = -1;
			byte[] datas = new byte[1];// 初始数据值
			while (pos <= length) {
				randomAccessFile.seek(pos);
				if (randomAccessFile.read(datas, 0, 1) != 1) {
					duration = length > 0 ? ((length - 6) / 650) : 0;
					break;
				}
				packedPos = (datas[0] >> 3) & 0x0F;
				pos += packedSize[packedPos] + 1;
				frameCount++;
			}
			duration += frameCount * 20;// 帧数*20
		} finally {
			if (randomAccessFile != null) {
				randomAccessFile.close();
			}
		}
		return duration;
	}
}

好两个最为关键的类上来了,再就是怎么调用呢?

@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					recordPath = Constants.CACHE_SDCARD_PATH + System.currentTimeMillis() + ".amr";
					dlg.show(recordPath);
					break;
				case MotionEvent.ACTION_UP:
					dlg.dismiss();
					break;
				}
				return false;
			}

其中 dlg就是一个上面定义的录音对话框:

private RecorderDialog dlg; //录音对话框
dlg = new RecorderDialog(this); //在activity中实例化


其中 R.drawable.bg_recorder_value_XXXX  是一系列图片,在声音变化图片就会更换。


录音完成会在recordPath下生成一个.amr的文件,把它发送出去即可咯。


【Android】利用MediaRecorder实现录音对讲功能,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。