【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实现录音对讲功能

时间: 2024-10-13 23:33:29

【Android】利用MediaRecorder实现录音对讲功能的相关文章

我的Android进阶之旅------&gt;Android利用Sensor(传感器)实现水平仪功能的小例

这里介绍的水平仪,指的是比较传统的气泡水平仪,在一个透明圆盘内充满液体,液体中留有一个气泡,当一端翘起时,该气泡就会浮向翘起的一端. 利用方向传感器返回的第一个参数,实现了一个指南针小应用. 我的Android进阶之旅------>Android利用Sensor(传感器)实现指南针功能 (地址:http://blog.csdn.net/ouyang_peng/article/details/8801204) 接下来,我们利用返回的第二.三个参数实现该水平仪.因为第二个参数,反映底部翘起的角度(当

Android简单的利用MediaRecorder进行录音的实例代码

MainActivity.java package com.example.soundrecord_demo; import java.io.IOException; import android.media.MediaRecorder; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.Vie

Android 利用Service实现下载网络图片至sdk卡

1 package com.example.myapp5; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.widget.Button; 8 /** 9 * Android 利用service实现下载图片功能 10 * @author shaobn 11 * @date

Android开发--仿微信语音对讲录音

自微信出现以来取得了很好的成绩,语音对讲的实现更加方便了人与人之间的交流.今天来实践一下微信的语音对讲的录音实现,这个也比较容易实现.在此,我将该按钮封装成为一个控件,并通过策略模式的方式实现录音和界面的解耦合,以方便我们在实际情况中对录音方法的不同需求(例如想要实现wav格式的编码时我们也就不能再使用MediaRecorder,而只能使用AudioRecord进行处理). 效果图: 实现思路 1.在微信中我们可以看到实现语音对讲的是通过点按按钮来完成的,因此在这里我选择重新自己的控件使其继承自

Android 使用MediaRecorder录音

package com.example.HyyRecord; import android.app.Activity; import android.content.Intent; import android.media.MediaRecorder; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.view.View; import java.io.F

利用 Android 系统原生 API 实现分享功能

利用 Android 系统原生 API 实现分享功能 这篇文章提供一个封装好的 Share2 库供大家参考. GitHub 项目地址:Share2 大家知道,要调用 Android 系统内建的分享功能,主要有三步流程: 创建一个 Intent ,指定其 Action 为 Intent.ACTION_SEND,表示要创建一个发送指定内容的隐式意图. 然后指定需要发送的内容和类型,设置分享的文本内容或文件的Uri,以及文件的类型,便于是支持该类型内容的应用打开. 最后向系统发送隐式意图,开启系统分享

【Android】20.4 录音

分类:C#.Android.VS2015: 创建日期:2016-03-13 一.简介 利用Android提供的MediaRecorder类可直接录制音频. 1.权限要求 录制音频和视频需要下面的权限: <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNA

Android多媒体-MediaRecorder 录制音视频

不多说,直接上代码,有详细注释 MyAudioRecord.java import java.io.File; import java.io.IOException; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaRecorder

Android开发实践:WIFI连接功能的封装

在上一篇文章<Android开发实践:WIFI扫描功能的封装>介绍了如何利用Andriod的API实现WIFI的扫描,本文则重点讲述一下如何连接WIFI吧,在此,也给出一个封装WIFI连接过程的类,提供简单的接口以供在各个代码工程中复用. 与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果.该回调接口的定义如下: public interface WifiConnectListener { public void OnWifiConne