此demo涉及到麦克风 动画 以及线程的使用:
开启麦克风录制声音:
为实现分贝测试, 需要对周围声音进行录制, 新建MicActivity 类, 使用MediaRecorder(视频/ 音频 录制类)来气麦克风录制音频, 并使用File 创建文件将音频保存到手机, 使用AnimationDrawable 用于显示录音的动画效果:
public class MicActivity extends AppCompatActivity {
private MediaRecorder mediaRecorder; //麦克风
private File mAudiofile, mSampleDir; //录音文件保存
private ImageView iv_wave_left,iv_wave_right; //声音动画图片
private AnimationDrawable ad_left, ad_right; //左右动画属性
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mic);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); //保持屏幕不暗
initView();
}
private void initView() {
iv_wave_left = (ImageView) findViewById(R.id.iv_record_wave_left);
iv_wave_right = (ImageView) findViewById(R.id.iv_record_wave_right);
ad_left = (AnimationDrawable) iv_wave_left.getBackground(); //动画效果
ad_right = (AnimationDrawable) iv_wave_right.getBackground();
ad_left.start();
ad_right.start(); //开启动画
}
@Override
protected void onStart() {
super.onStart();
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //姻缘为麦克风
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR); //音频文件的编码
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //设置audio的格式
try {
mSampleDir = Environment.getExternalStorageDirectory(); //获取手机内存路径
//用IM+ 系统当前时间为文件名建立 .amr的文件, 文件路径为mSampleDir
mAudiofile = File.createTempFile("IM" + System.currentTimeMillis(), ".arm", mSampleDir);
}catch (IOException e){
e.printStackTrace();
}
mediaRecorder.setOutputFile(mAudiofile.getAbsolutePath()); //设置声音输出文件的路径
try {
mediaRecorder.prepare(); //准备录制
}catch (Exception e){
e.printStackTrace();
}
mediaRecorder.start(); //开始录制
}
//返回功能
public void onBack(){
MicActivity.this.finish(); //关闭当前页面
}
}
将声音转换为分贝值:
前面已经实现了声音的录制, 现在实现分贝的显示, 首先需要自定义Thread 使用该线程将麦克风录制的声音转换为分贝并显示出来。
class MicrophoneThread extends Thread{ //测量当前分贝值通知UI修改
final float minAngle = (float) Math.PI * 4 / 11;
float angle; //分贝值
@Override
public void run() {
while (true){
angle = 100 * minAngle * mediaRecorder.getMaxAmplitude() / 32768;
if (angle > 1000){
angle = 100;
}
//构造方法的字符格式在这里如果不足两位,会补0
DecimalFormat decimalFormat = new DecimalFormat("0.00");
String p = decimalFormat.format(angle); //format返回的是字符串, 分贝值
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
设置全局对象:
private MicrophoneThread microphoneThread = new MicrophoneThread(); //线程用于实时录制环境声音
在onStart() 方法中加入
microphoneThread.start(); //开启线程声音转换为分贝值
通过发送消息 实现更新页面:
使用Handler 接收消息更新UI, 从而更新当前页面的分贝值。 需要对控件进行声明:
private TextView textView1; //用于显示分贝值
private MHandler mHandler = new MHandler(); //接收消息修改分贝值
class MHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1: //返回消息1
textView1.setText(msg.obj.toString()); //修改分贝值
break;
}
}
}
初始化TextView, 用于显示当前分贝值, 在init() 中实例化:
textView1 = (TextView) findViewById(R.id.textView1);
接着发送当前分贝值给Handler, 更新当前页面分贝值:
在麦克风线程中添加代码:
String p = decimalFormat.format(angle); //format返回的是字符串, 分贝值
Message message = new Message();
message.what = 1;
message.obj = p;
mHandler.sendMessage(message); //发送当前分贝值
实现主界面向分贝测试仪界面跳转:
textView = (TextView) findViewById(R.id.text);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MicActivity.class);
startActivity(intent);
}
});
}
