上接《Android传感器编程入门(二)》
三、实例:窈窈录音器
通过上面的例子我们学会了如何获得某种类型的传感器,下面我通过一个实例来学会如何使用某一个类型的传感器。我们这里使用加速度传感器来实现这样一个功能:开启我们的录音程序放在你的口袋或者提包里,需要录音的时候把衣服整理一下,或者把提包挪动个位置,那么此时手机就会感受到变化从而开始录音。由此达到神不知鬼不觉的录音效果。说起来似乎有点神,其实做起来很简单,让我们开始吧。
简单的录音程序已经在第28讲的时候做过了,我们在28讲程序的基础上写本讲的代码。
1、新建一个项目 Lesson37_YYRecorder , 主文件叫 MainActivity.java ,具体信息都可以参见第二十八讲的“窈窈录音”的例子。
001
- package basic.android.lesson37;
- 002
- 003
- import java.io.File;
- 004
- import java.io.IOException;
- 005
- import java.util.Calendar;
- 006
- import java.util.Locale;
- 007
- 008
- import android.app.Activity;
- 009
- import android.content.Context;
- 010
- import android.hardware.Sensor;
- 011
- import android.hardware.SensorEvent;
- 012
- import android.hardware.SensorEventListener;
- 013
- import android.hardware.SensorManager;
- 014
- import android.media.MediaRecorder;
- 015
- import android.os.Bundle;
- 016
- import android.text.format.DateFormat;
- 017
- import android.view.View;
- 018
- import android.widget.Button;
- 019
- import android.widget.TextView;
- 020
- import android.widget.Toast;
- 021
- 022
- public class MainActivity extends Activity {
- 023
- 024
- //录音和停止按钮
- 025
- private Button recordButton;
- 026
- private Button stopButton;
- 027
- 028
- //检测摇动相关变量
- 029
- private long initTime = 0;
- 030
- private long lastTime = 0;
- 031
- private long curTime = 0;
- 032
- private long duration = 0;
- 033
- 034
- private float last_x = 0.0f;
- 035
- private float last_y = 0.0f;
- 036
- private float last_z = 0.0f;
- 037
- 038
- private float shake = 0.0f;
- 039
- private float totalShake = 0.0f;
- 040
- 041
- //媒体录音器对象
- 042
- private MediaRecorder mr;
- 043
- 044
- //是否正在录音
- 045
- private boolean isRecoding = false;
- 046
- 047
- @Override
- 048
- public void onCreate(Bundle savedInstanceState) {
- 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
- final TextView tx1 = (TextView) this.findViewById(R.id.TextView01);
- 056
- 057
- // 录音按钮点击事件
- 058
- recordButton.setOnClickListener(new View.OnClickListener() {
- 059
- 060
- @Override
- 061
- public void onClick(View v) {
- 062
- //如果没有在录音,那么点击按钮可以开始录音
- 063
- if(!isRecoding){
- 064
- startRecord();
- 065
- }
- 066
- }
- 067
- });
- 068
- 069
- // 停止按钮点击事件
- 070
- stopButton.setOnClickListener(new View.OnClickListener() {
- 071
- 072
- @Override
- 073
- public void onClick(View v) {
- 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
- SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
- 090
- // 获取加速度传感器
- 091
- Sensor acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- 092
- 093
- // 定义传感器事件监听器
- 094
- SensorEventListener acceleromererListener = new SensorEventListener() {
- 095
- 096
- @Override
- 097
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- 098
- //什么也不干
- 099
- }
- 100
- 101
- //传感器数据变动事件
- 102
- @Override
- 103
- public void onSensorChanged(SensorEvent event) {
- 104
- 105
- //如果没有开始录音的话可以监听是否有摇动事件,如果有摇动事件可以开始录音
- 106
- if(!isRecoding){
- 107
- //获取加速度传感器的三个参数
- 108
- float x = event.values[SensorManager.DATA_X];
- 109
- float y = event.values[SensorManager.DATA_Y];
- 110
- float z = 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
- public void startRecord() {
- 157
- //把正在录音的标志设为真
- 158
- isRecoding = true;
- 159
- //存放文件
- 160
- File file = new File("/sdcard/" + "YY"
- 161
- + new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".amr");
- 162
- 163
- Toast.makeText(getApplicationContext(), "正在录音,录音文件在" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
- 164
- 165
- // 创建录音对象
- 166
- mr = new MediaRecorder();
- 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 (IllegalStateException e) {
- 186
- e.printStackTrace();
- 187
- } catch (IOException e) {
- 188
- e.printStackTrace();
- 189
- }
- 190
- // 开始录制
- 191
- mr.start();
- 192
- recordButton.setText("录音中……");
- 193
- }
- 194
- 195
- //摇动初始化
- 196
- public void initShake() {
- 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维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。
好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。
转载于:https://blog.51cto.com/zhangyan1158/453445