看到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的文件,把它发送出去即可咯。