上接《Android传感器编程入门(二)》

三、实例:窈窈录音器

通过上面的例子我们学会了如何获得某种类型的传感器,下面我通过一个实例来学会如何使用某一个类型的传感器。我们这里使用加速度传感器来实现这样一个功能:开启我们的录音程序放在你的口袋或者提包里,需要录音的时候把衣服整理一下,或者把提包挪动个位置,那么此时手机就会感受到变化从而开始录音。由此达到神不知鬼不觉的录音效果。说起来似乎有点神,其实做起来很简单,让我们开始吧。

简单的录音程序已经在第28讲的时候做过了,我们在28讲程序的基础上写本讲的代码。

1、新建一个项目 Lesson37_YYRecorder , 主文件叫 MainActivity.java ,具体信息都可以参见第二十八讲的“窈窈录音”的例子。

001

  1. packagebasic.android.lesson37;
  2. 002
  3. 003
  4. importjava.io.File;
  5. 004
  6. importjava.io.IOException;
  7. 005
  8. importjava.util.Calendar;
  9. 006
  10. importjava.util.Locale;
  11. 007
  12. 008
  13. importandroid.app.Activity;
  14. 009
  15. importandroid.content.Context;
  16. 010
  17. importandroid.hardware.Sensor;
  18. 011
  19. importandroid.hardware.SensorEvent;
  20. 012
  21. importandroid.hardware.SensorEventListener;
  22. 013
  23. importandroid.hardware.SensorManager;
  24. 014
  25. importandroid.media.MediaRecorder;
  26. 015
  27. importandroid.os.Bundle;
  28. 016
  29. importandroid.text.format.DateFormat;
  30. 017
  31. importandroid.view.View;
  32. 018
  33. importandroid.widget.Button;
  34. 019
  35. importandroid.widget.TextView;
  36. 020
  37. importandroid.widget.Toast;
  38. 021
  39. 022
  40. publicclassMainActivityextendsActivity{
  41. 023
  42. 024
  43. //录音和停止按钮
  44. 025
  45. privateButtonrecordButton;
  46. 026
  47. privateButtonstopButton;
  48. 027
  49. 028
  50. //检测摇动相关变量
  51. 029
  52. privatelonginitTime=0;
  53. 030
  54. privatelonglastTime=0;
  55. 031
  56. privatelongcurTime=0;
  57. 032
  58. privatelongduration=0;
  59. 033
  60. 034
  61. privatefloatlast_x=0.0f;
  62. 035
  63. privatefloatlast_y=0.0f;
  64. 036
  65. privatefloatlast_z=0.0f;
  66. 037
  67. 038
  68. privatefloatshake=0.0f;
  69. 039
  70. privatefloattotalShake=0.0f;
  71. 040
  72. 041
  73. //媒体录音器对象
  74. 042
  75. privateMediaRecordermr;
  76. 043
  77. 044
  78. //是否正在录音
  79. 045
  80. privatebooleanisRecoding=false;
  81. 046
  82. 047
  83. @Override
  84. 048
  85. publicvoidonCreate(BundlesavedInstanceState){
  86. 049
  87. super.onCreate(savedInstanceState);
  88. 050
  89. setContentView(R.layout.main);
  90. 051
  91. 052
  92. //UI组件
  93. 053
  94. recordButton=(Button)this.findViewById(R.id.Button01);
  95. 054
  96. stopButton=(Button)this.findViewById(R.id.Button02);
  97. 055
  98. finalTextViewtx1=(TextView)this.findViewById(R.id.TextView01);
  99. 056
  100. 057
  101. //录音按钮点击事件
  102. 058
  103. recordButton.setOnClickListener(newView.OnClickListener(){
  104. 059
  105. 060
  106. @Override
  107. 061
  108. publicvoidonClick(Viewv){
  109. 062
  110. //如果没有在录音,那么点击按钮可以开始录音
  111. 063
  112. if(!isRecoding){
  113. 064
  114. startRecord();
  115. 065
  116. }
  117. 066
  118. }
  119. 067
  120. });
  121. 068
  122. 069
  123. //停止按钮点击事件
  124. 070
  125. stopButton.setOnClickListener(newView.OnClickListener(){
  126. 071
  127. 072
  128. @Override
  129. 073
  130. publicvoidonClick(Viewv){
  131. 074
  132. initShake();
  133. 075
  134. //如果正在录音,那么可以停止录音
  135. 076
  136. if(mr!=null){
  137. 077
  138. mr.stop();
  139. 078
  140. mr.release();
  141. 079
  142. mr=null;
  143. 080
  144. recordButton.setText("录音");
  145. 081
  146. Toast.makeText(getApplicationContext(),"录音完毕",Toast.LENGTH_LONG).show();
  147. 082
  148. isRecoding=false;
  149. 083
  150. 084
  151. }
  152. 085
  153. }
  154. 086
  155. });
  156. 087
  157. 088
  158. //获取传感器管理器
  159. 089
  160. SensorManagersm=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
  161. 090
  162. //获取加速度传感器
  163. 091
  164. SensoracceleromererSensor=sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  165. 092
  166. 093
  167. //定义传感器事件监听器
  168. 094
  169. SensorEventListeneracceleromererListener=newSensorEventListener(){
  170. 095
  171. 096
  172. @Override
  173. 097
  174. publicvoidonAccuracyChanged(Sensorsensor,intaccuracy){
  175. 098
  176. //什么也不干
  177. 099
  178. }
  179. 100
  180. 101
  181. //传感器数据变动事件
  182. 102
  183. @Override
  184. 103
  185. publicvoidonSensorChanged(SensorEventevent){
  186. 104
  187. 105
  188. //如果没有开始录音的话可以监听是否有摇动事件,如果有摇动事件可以开始录音
  189. 106
  190. if(!isRecoding){
  191. 107
  192. //获取加速度传感器的三个参数
  193. 108
  194. floatx=event.values[SensorManager.DATA_X];
  195. 109
  196. floaty=event.values[SensorManager.DATA_Y];
  197. 110
  198. floatz=event.values[SensorManager.DATA_Z];
  199. 111
  200. 112
  201. //获取当前时刻的毫秒数
  202. 113
  203. curTime=System.currentTimeMillis();
  204. 114
  205. 115
  206. //100毫秒检测一次
  207. 116
  208. if((curTime-lastTime)>100){
  209. 117
  210. 118
  211. duration=(curTime-lastTime);
  212. 119
  213. 120
  214. //看是不是刚开始晃动
  215. 121
  216. if(last_x==0.0f&&last_y==0.0f&&last_z==0.0f){
  217. 122
  218. //last_x、last_y、last_z同时为0时,表示刚刚开始记录
  219. 123
  220. initTime=System.currentTimeMillis();
  221. 124
  222. }else{
  223. 125
  224. //单次晃动幅度
  225. 126
  226. shake=(Math.abs(x-last_x)+Math.abs(y-last_y)+Math.abs(z-last_z))/duration*100;
  227. 127
  228. }
  229. 128
  230. 129
  231. //把每次的晃动幅度相加,得到总体晃动幅度
  232. 130
  233. totalShake+=shake;
  234. 131
  235. 132
  236. //判断是否为摇动,这是我自己写的标准,不准确,只是用来做教学示例,别误会了^_^
  237. 133
  238. if(totalShake>10&&totalShake/(curTime-initTime)*1000>10){
  239. 134
  240. startRecord();
  241. 135
  242. initShake();
  243. 136
  244. }
  245. 137
  246. 138
  247. tx1.setText("总体晃动幅度="+totalShake+"\n平均晃动幅度="+totalShake/(curTime-initTime)*1000);
  248. 139
  249. }
  250. 140
  251. 141
  252. last_x=x;
  253. 142
  254. last_y=y;
  255. 143
  256. last_z=z;
  257. 144
  258. lastTime=curTime;
  259. 145
  260. }
  261. 146
  262. }
  263. 147
  264. 148
  265. };
  266. 149
  267. 150
  268. //在传感器管理器中注册监听器
  269. 151
  270. sm.registerListener(acceleromererListener,acceleromererSensor,SensorManager.SENSOR_DELAY_NORMAL);
  271. 152
  272. 153
  273. }
  274. 154
  275. 155
  276. //开始录音
  277. 156
  278. publicvoidstartRecord(){
  279. 157
  280. //把正在录音的标志设为真
  281. 158
  282. isRecoding=true;
  283. 159
  284. //存放文件
  285. 160
  286. Filefile=newFile("/sdcard/"+"YY"
  287. 161
  288. +newDateFormat().format("yyyyMMdd_hhmmss",Calendar.getInstance(Locale.CHINA))+".amr");
  289. 162
  290. 163
  291. Toast.makeText(getApplicationContext(),"正在录音,录音文件在"+file.getAbsolutePath(),Toast.LENGTH_LONG).show();
  292. 164
  293. 165
  294. //创建录音对象
  295. 166
  296. mr=newMediaRecorder();
  297. 167
  298. 168
  299. //从麦克风源进行录音
  300. 169
  301. mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
  302. 170
  303. 171
  304. //设置输出格式
  305. 172
  306. mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
  307. 173
  308. 174
  309. //设置编码格式
  310. 175
  311. mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
  312. 176
  313. 177
  314. //设置输出文件
  315. 178
  316. mr.setOutputFile(file.getAbsolutePath());
  317. 179
  318. 180
  319. try{
  320. 181
  321. //创建文件
  322. 182
  323. file.createNewFile();
  324. 183
  325. //准备录制
  326. 184
  327. mr.prepare();
  328. 185
  329. }catch(IllegalStateExceptione){
  330. 186
  331. e.printStackTrace();
  332. 187
  333. }catch(IOExceptione){
  334. 188
  335. e.printStackTrace();
  336. 189
  337. }
  338. 190
  339. //开始录制
  340. 191
  341. mr.start();
  342. 192
  343. recordButton.setText("录音中……");
  344. 193
  345. }
  346. 194
  347. 195
  348. //摇动初始化
  349. 196
  350. publicvoidinitShake(){
  351. 197
  352. lastTime=0;
  353. 198
  354. duration=0;
  355. 199
  356. curTime=0;
  357. 200
  358. initTime=0;
  359. 201
  360. last_x=0.0f;
  361. 202
  362. last_y=0.0f;
  363. 203
  364. last_z=0.0f;
  365. 204
  366. shake=0.0f;
  367. 205
  368. totalShake=0.0f;
  369. 206
  370. }
  371. }

3、连接真机Milestone,编译并运行程序:

晃动机器,开始录音

查看录音文件,效果还可以:

4、我们小结一下:

到Android2.2版本为止,系统并没有给开发者提供多少可用的包装好的传感器信息,只是提供了传感器发出的原始数据,这些原始数据存放在 event.values 的数组里,开发人员需要从这些裸数据总自行发掘有用的信息,譬如从加速度传感器的3维裸数据中获得摇动的判断(我的摇动判断很弱智,有时间再改吧……)。

好了本讲就先到这里,关于传感器有机会我们展开再谈,下次再见吧。

更多相关文章

  1. android 语音即时通讯之录音、播放实现
  2. Android(安卓)传感器概述
  3. Android(安卓)摇一摇开发——灵敏度优化
  4. android语音即时通讯之录音、播放功能实现代码
  5. Android传感器-开发指南
  6. 方向传感器
  7. android 音量总结
  8. FFmpeg 音频编码(PCM数据编码成AAC android)
  9. Android(安卓)传感器(Sensor)API教程 (二) 传感器事件

随机推荐

  1. Android(安卓)Studio系列-签名打包
  2. Android中选取并绑定AppWidget
  3. android 自定义 permission 权限
  4. Android(安卓)ActionBarSherlock的使用
  5. android焦点问题
  6. Android(安卓)Studio启动时出现unable to
  7. Android(安卓)开发中使用 SQLite 数据库
  8. android menu菜单
  9. AVD(android virtual device)路径设置
  10. 在Android上本机运行的服务器