看到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的文件,把它发送出去即可咯。
最后 记得权限:
<!-- 录音权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />