Android传感器编程入门(三)
16lz
2021-01-26
上接《Android传感器编程入门(二)》
三、实例:窈窈录音器
通过上面的例子我们学会了如何获得某种类型的传感器,下面我通过一个实例来学会如何使用某一个类型的传感器。我们这里使用加速度传感器来实现这样一个功能:开启我们的录音程序放在你的口袋或者提包里,需要录音的时候把衣服整理一下,或者把提包挪动个位置,那么此时手机就会感受到变化从而开始录音。由此达到神不知鬼不觉的录音效果。说起来似乎有点神,其实做起来很简单,让我们开始吧。
简单的录音程序已经在第28讲的时候做过了,我们在28讲程序的基础上写本讲的代码。
1、新建一个项目 Lesson37_YYRecorder , 主文件叫 MainActivity.java ,具体信息都可以参见第二十八讲的“窈窈录音”的例子。
001
- packagebasic.android.lesson37;
- 002
- 003
- importjava.io.File;
- 004
- importjava.io.IOException;
- 005
- importjava.util.Calendar;
- 006
- importjava.util.Locale;
- 007
- 008
- importandroid.app.Activity;
- 009
- importandroid.content.Context;
- 010
- importandroid.hardware.Sensor;
- 011
- importandroid.hardware.SensorEvent;
- 012
- importandroid.hardware.SensorEventListener;
- 013
- importandroid.hardware.SensorManager;
- 014
- importandroid.media.MediaRecorder;
- 015
- importandroid.os.Bundle;
- 016
- importandroid.text.format.DateFormat;
- 017
- importandroid.view.View;
- 018
- importandroid.widget.Button;
- 019
- importandroid.widget.TextView;
- 020
- importandroid.widget.Toast;
- 021
- 022
- publicclassMainActivityextendsActivity{
- 023
- 024
- //录音和停止按钮
- 025
- privateButtonrecordButton;
- 026
- privateButtonstopButton;
- 027
- 028
- //检测摇动相关变量
- 029
- privatelonginitTime=0;
- 030
- privatelonglastTime=0;
- 031
- privatelongcurTime=0;
- 032
- privatelongduration=0;
- 033
- 034
- privatefloatlast_x=0.0f;
- 035
- privatefloatlast_y=0.0f;
- 036
- privatefloatlast_z=0.0f;
- 037
- 038
- privatefloatshake=0.0f;
- 039
- privatefloattotalShake=0.0f;
- 040
- 041
- //媒体录音器对象
- 042
- privateMediaRecordermr;
- 043
- 044
- //是否正在录音
- 045
- privatebooleanisRecoding=false;
- 046
- 047
- @Override
- 048
- publicvoidonCreate(BundlesavedInstanceState){
- 049
- super.onCreate(savedInstanceState);
- 050
- setContentView(R.layout.main);
- 051
- 052
- //UI组件
- 053
- recordButton=(Button)this.findViewById(R.id.Button01);
- 054
- stopButton=(Button)this.findViewById(R.id.Button02);
- 055
- finalTextViewtx1=(TextView)this.findViewById(R.id.TextView01);
- 056
- 057
- //录音按钮点击事件
- 058
- recordButton.setOnClickListener(newView.OnClickListener(){
- 059
- 060
- @Override
- 061
- publicvoidonClick(Viewv){
- 062
- //如果没有在录音,那么点击按钮可以开始录音
- 063
- if(!isRecoding){
- 064
- startRecord();
- 065
- }
- 066
- }
- 067
- });
- 068
- 069
- //停止按钮点击事件
- 070
- stopButton.setOnClickListener(newView.OnClickListener(){
- 071
- 072
- @Override
- 073
- publicvoidonClick(Viewv){
- 074
- initShake();
- 075
- //如果正在录音,那么可以停止录音
- 076
- if(mr!=null){
- 077
- mr.stop();
- 078
- mr.release();
- 079
- mr=null;
- 080
- recordButton.setText("录音");
- 081
- Toast.makeText(getApplicationContext(),"录音完毕",Toast.LENGTH_LONG).show();
- 082
- isRecoding=false;
- 083
- 084
- }
- 085
- }
- 086
- });
- 087
- 088
- //获取传感器管理器
- 089
- SensorManagersm=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
- 090
- //获取加速度传感器
- 091
- SensoracceleromererSensor=sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- 092
- 093
- //定义传感器事件监听器
- 094
- SensorEventListeneracceleromererListener=newSensorEventListener(){
- 095
- 096
- @Override
- 097
- publicvoidonAccuracyChanged(Sensorsensor,intaccuracy){
- 098
- //什么也不干
- 099
- }
- 100
- 101
- //传感器数据变动事件
- 102
- @Override
- 103
- publicvoidonSensorChanged(SensorEventevent){
- 104
- 105
- //如果没有开始录音的话可以监听是否有摇动事件,如果有摇动事件可以开始录音
- 106
- if(!isRecoding){
- 107
- //获取加速度传感器的三个参数
- 108
- floatx=event.values[SensorManager.DATA_X];
- 109
- floaty=event.values[SensorManager.DATA_Y];
- 110
- floatz=event.values[SensorManager.DATA_Z];
- 111
- 112
- //获取当前时刻的毫秒数
- 113
- curTime=System.currentTimeMillis();
- 114
- 115
- //100毫秒检测一次
- 116
- if((curTime-lastTime)>100){
- 117
- 118
- duration=(curTime-lastTime);
- 119
- 120
- //看是不是刚开始晃动
- 121
- if(last_x==0.0f&&last_y==0.0f&&last_z==0.0f){
- 122
- //last_x、last_y、last_z同时为0时,表示刚刚开始记录
- 123
- initTime=System.currentTimeMillis();
- 124
- }else{
- 125
- //单次晃动幅度
- 126
- shake=(Math.abs(x-last_x)+Math.abs(y-last_y)+Math.abs(z-last_z))/duration*100;
- 127
- }
- 128
- 129
- //把每次的晃动幅度相加,得到总体晃动幅度
- 130
- totalShake+=shake;
- 131
- 132
- //判断是否为摇动,这是我自己写的标准,不准确,只是用来做教学示例,别误会了^_^
- 133
- if(totalShake>10&&totalShake/(curTime-initTime)*1000>10){
- 134
- startRecord();
- 135
- initShake();
- 136
- }
- 137
- 138
- tx1.setText("总体晃动幅度="+totalShake+"\n平均晃动幅度="+totalShake/(curTime-initTime)*1000);
- 139
- }
- 140
- 141
- last_x=x;
- 142
- last_y=y;
- 143
- last_z=z;
- 144
- lastTime=curTime;
- 145
- }
- 146
- }
- 147
- 148
- };
- 149
- 150
- //在传感器管理器中注册监听器
- 151
- sm.registerListener(acceleromererListener,acceleromererSensor,SensorManager.SENSOR_DELAY_NORMAL);
- 152
- 153
- }
- 154
- 155
- //开始录音
- 156
- publicvoidstartRecord(){
- 157
- //把正在录音的标志设为真
- 158
- isRecoding=true;
- 159
- //存放文件
- 160
- Filefile=newFile("/sdcard/"+"YY"
- 161
- +newDateFormat().format("yyyyMMdd_hhmmss",Calendar.getInstance(Locale.CHINA))+".amr");
- 162
- 163
- Toast.makeText(getApplicationContext(),"正在录音,录音文件在"+file.getAbsolutePath(),Toast.LENGTH_LONG).show();
- 164
- 165
- //创建录音对象
- 166
- mr=newMediaRecorder();
- 167
- 168
- //从麦克风源进行录音
- 169
- mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
- 170
- 171
- //设置输出格式
- 172
- mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
- 173
- 174
- //设置编码格式
- 175
- mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
- 176
- 177
- //设置输出文件
- 178
- mr.setOutputFile(file.getAbsolutePath());
- 179
- 180
- try{
- 181
- //创建文件
- 182
- file.createNewFile();
- 183
- //准备录制
- 184
- mr.prepare();
- 185
- }catch(IllegalStateExceptione){
- 186
- e.printStackTrace();
- 187
- }catch(IOExceptione){
- 188
- e.printStackTrace();
- 189
- }
- 190
- //开始录制
- 191
- mr.start();
- 192
- recordButton.setText("录音中……");
- 193
- }
- 194
- 195
- //摇动初始化
- 196
- publicvoidinitShake(){
- 197
- lastTime=0;
- 198
- duration=0;
- 199
- curTime=0;
- 200
- initTime=0;
- 201
- last_x=0.0f;
- 202
- last_y=0.0f;
- 203
- last_z=0.0f;
- 204
- shake=0.0f;
- 205
- totalShake=0.0f;
- 206
- }
- }
3、连接真机Milestone,编译并运行程序:
晃动机器,开始录音
查看录音文件,效果还可以:
4、我们小结一下:
到Android2.2版本为止,系统并没有给开发者提供多少可用的包装好的传感器信息,只是提供了传感器发出的原始数据,这些原始数据存放在 event.values 的数组里,开发人员需要从这些裸数据总自行发掘有用的信息,譬如从加速度传感器的3维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。
好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。
更多相关文章
- android 语音即时通讯之录音、播放实现
- Android(安卓)传感器概述
- Android(安卓)摇一摇开发——灵敏度优化
- android语音即时通讯之录音、播放功能实现代码
- Android传感器-开发指南
- 方向传感器
- android 音量总结
- FFmpeg 音频编码(PCM数据编码成AAC android)
- Android(安卓)传感器(Sensor)API教程 (二) 传感器事件