看了程序人生 网站的

  • 编程高手的编程感悟 深有感触,好像也是一个android 程序员写的,推荐大家也看看。话不多说,还是言归正传吧。

一、前言

我很喜欢电脑,可是笔记本还是太大,笔记本电脑再小还是要弄个小包背起来的,智能手机则不同,它完全就是一个手机,可以随意装在一个口袋里随身携带。因此我在2002年左右时最喜欢玩装备是Dell的PDA,2007年的时候最喜欢玩的是N73,而在2010年最喜欢玩的则是Milestone。眼见着手机的功能越来越强,时至今日智能手机甚至在某些方面已经强过了台式机和笔记本。本节课讲的就是智能手机强过台式机和笔记本的地方:传感器。

  2008年的时候我很喜欢我的小白笔记本Macbook,喜欢玩它的一个小软件,一拍桌子,笔记本感受到了震动,它就转换了一个桌面出来,这让我像个小孩子一样没事就拍拍桌子。这一功能这得益于苹果笔记本内置有传感器。

  我不知道iPhone手机是不是第一个把各种各样的传感器运用在手机上的,不过我知道iPhone是把传感器运用在手机上最成功的第一个。随后的Android系统也内置了大量的传感器,这让Android系统手机和普通的诺基亚智能机和Windows CE智能机相比牛气了许多,在拥有了Milestone之后,我的N73就被仍在抽屉的角落里了。

  从Android1.5开始,系统内置了对多达八种传感器的支持,他们分别是:加速度传感器(accelerometer)、陀螺仪(gyroscope)、环境光照传感器(light)、磁力传感器(magnetic field)、方向传感器(orientation)、压力传感器(pressure)、距离传感器(proximity)和温度传感器(temperature)。

  利用这些传感器我们可以制作出各种有趣的应用程序和游戏。譬如在口袋里晃一晃手机,手机就开始神不知鬼不觉的录音,不要着急这个很容易做,我们在本文的结尾就一起制作这个小应用。

  本讲的学习方式还是在实战中学习,需要提醒的是模拟器中无法模拟传感器,因此你需要准备一款Android真机才能运行本讲的例子。

  二、实例:手机传感器清单

我们还是先看程序后解释。

1、创建一个项目 Lesson37_HelloSensor ,主Activity名字叫 mainActivity.java。

2、UI布局文件main.xml的内容如下:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
  3. <textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="" android:id="@+id/TextView01">
  4. </textview></linearlayout>

3、mainActivity.java的内容如下:

Java代码
  1. package basic.android.lesson37;
  2. import java.util.List;
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.hardware.Sensor;
  6. import android.hardware.SensorManager;
  7. import android.os.Bundle;
  8. import android.widget.TextView;
  9. public class MainActivity extends Activity {
  10. /** Called when the activity is first created. */
  11. @Override
  12. public void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.main);
  15. //准备显示信息的UI组建
  16. final TextView tx1 = (TextView) findViewById(R.id.TextView01);
  17. //从系统服务中获得传感器管理器
  18. SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  19. //从传感器管理器中获得全部的传感器列表
  20. List<sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);
  21. //显示有多少个传感器
  22. tx1.setText("经检测该手机有" + allSensors.size() + "个传感器,他们分别是:\n");
  23. //显示每个传感器的具体信息
  24. for (Sensor s : allSensors) {
  25. String tempString = "\n" + "  设备名称:" + s.getName() + "\n" + "  设备版本:" + s.getVersion() + "\n" + "  供应商:"
  26. + s.getVendor() + "\n";
  27. switch (s.getType()) {
  28. case Sensor.TYPE_ACCELEROMETER:
  29. tx1.setText(tx1.getText().toString() + s.getType() + " 加速度传感器accelerometer" + tempString);
  30. break;
  31. case Sensor.TYPE_GYROSCOPE:
  32. tx1.setText(tx1.getText().toString() + s.getType() + " 陀螺仪传感器gyroscope" + tempString);
  33. break;
  34. case Sensor.TYPE_LIGHT:
  35. tx1.setText(tx1.getText().toString() + s.getType() + " 环境光线传感器light" + tempString);
  36. break;
  37. case Sensor.TYPE_MAGNETIC_FIELD:
  38. tx1.setText(tx1.getText().toString() + s.getType() + " 电磁场传感器magnetic field" + tempString);
  39. break;
  40. case Sensor.TYPE_ORIENTATION:
  41. tx1.setText(tx1.getText().toString() + s.getType() + " 方向传感器orientation" + tempString);
  42. break;
  43. case Sensor.TYPE_PRESSURE:
  44. tx1.setText(tx1.getText().toString() + s.getType() + " 压力传感器pressure" + tempString);
  45. break;
  46. case Sensor.TYPE_PROXIMITY:
  47. tx1.setText(tx1.getText().toString() + s.getType() + " 距离传感器proximity" + tempString);
  48. break;
  49. case Sensor.TYPE_TEMPERATURE:
  50. tx1.setText(tx1.getText().toString() + s.getType() + " 温度传感器temperature" + tempString);
  51. break;
  52. default:
  53. tx1.setText(tx1.getText().toString() + s.getType() + " 未知传感器" + tempString);
  54. break;
  55. }
  56. }
  57. }
  58. }</sensor>

4、连接真机Milestone,编译并运行程序,显示结果如下:

5、结合上面的程序我们做一些解释。

1)Android所有的传感器都归传感器管理器 SensorManager 管理,获取传感器管理器的方法很简单:

String service_name = Context.SENSOR_SERVICE;

SensorManager sensorManager = (SensorManager)getSystemService(service_name);

2)现阶段Android支持的传感器有8种,它们分别是:

传感器类型常量
内部整数值
中文名称
Sensor.TYPE_ACCELEROMETER
1
加速度传感器
Sensor.TYPE_MAGNETIC_FIELD
2
磁力传感器
Sensor.TYPE_ORIENTATION
3
方向传感器
Sensor.TYPE_GYROSCOPE
4
陀螺仪传感器
Sensor.TYPE_LIGHT
5
环境光照传感器
Sensor.TYPE_PRESSURE
6
压力传感器
Sensor.TYPE_TEMPERATURE
7
温度传感器
Sensor.TYPE_PROXIMITY
8 距离传感器

3)从传感器管理器中获取其中某个或者某些传感器的方法有如下三种:

第一种:获取某种传感器的默认传感器

Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

第二种:获取某种传感器的列表

List<Sensor> pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE);

第三种:获取所有传感器的列表,我们这个例子就用的第三种

List<Sensor> allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

4)对于某一个传感器,它的一些具体信息的获取方法可以见下表:

方法
描述
getMaximumRange()
最大取值范围
getName()
设备名称
getPower()
功率
getResolution()
精度
getType()
传感器类型
getVentor()
设备供应商
getVersion()
设备版本号

三、实例:窈窈录音器

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

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

1、新建一个项目 Lesson37_YYRecorder ,主文件叫 MainActivity.java 。

2、这里只贴出于28讲不同的 MainActivity.java  的代码,请注意看注释:

Java代码
  1. package basic.android.lesson37;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.Calendar;
  5. import java.util.Locale;
  6. import android.app.Activity;
  7. import android.content.Context;
  8. import android.hardware.Sensor;
  9. import android.hardware.SensorEvent;
  10. import android.hardware.SensorEventListener;
  11. import android.hardware.SensorManager;
  12. import android.media.MediaRecorder;
  13. import android.os.Bundle;
  14. import android.text.format.DateFormat;
  15. import android.view.View;
  16. import android.widget.Button;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. public class MainActivity extends Activity {
  20. //录音和停止按钮
  21. private Button recordButton;
  22. private Button stopButton;
  23. //检测摇动相关变量
  24. private long initTime = 0;
  25. private long lastTime = 0;
  26. private long curTime = 0;
  27. private long duration = 0;
  28. private float last_x = 0.0f;
  29. private float last_y = 0.0f;
  30. private float last_z = 0.0f;
  31. private float shake = 0.0f;
  32. private float totalShake = 0.0f;
  33. //媒体录音器对象
  34. private MediaRecorder mr;
  35. //是否正在录音
  36. private boolean isRecoding = false;
  37. @Override
  38. public void onCreate(Bundle savedInstanceState) {
  39. super.onCreate(savedInstanceState);
  40. setContentView(R.layout.main);
  41. // UI组件
  42. recordButton = (Button) this.findViewById(R.id.Button01);
  43. stopButton = (Button) this.findViewById(R.id.Button02);
  44. final TextView tx1 = (TextView) this.findViewById(R.id.TextView01);
  45. // 录音按钮点击事件
  46. recordButton.setOnClickListener(new View.OnClickListener() {
  47. @Override
  48. public void onClick(View v) {
  49. //如果没有在录音,那么点击按钮可以开始录音
  50. if(!isRecoding){
  51. startRecord();
  52. }
  53. }
  54. });
  55. // 停止按钮点击事件
  56. stopButton.setOnClickListener(new View.OnClickListener() {
  57. @Override
  58. public void onClick(View v) {
  59. initShake();
  60. //如果正在录音,那么可以停止录音
  61. if (mr != null) {
  62. mr.stop();
  63. mr.release();
  64. mr = null;
  65. recordButton.setText("录音");
  66. Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show();
  67. isRecoding = false;
  68. }
  69. }
  70. });
  71. // 获取传感器管理器
  72. SensorManager sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  73. // 获取加速度传感器
  74. Sensor acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  75. // 定义传感器事件监听器
  76. SensorEventListener acceleromererListener = new SensorEventListener() {
  77. @Override
  78. public void onAccuracyChanged(Sensor sensor, int accuracy) {
  79. //什么也不干
  80. }
  81. //传感器数据变动事件
  82. @Override
  83. public void onSensorChanged(SensorEvent event) {
  84. //如果没有开始录音的话可以监听是否有摇动事件,如果有摇动事件可以开始录音
  85. if(!isRecoding){
  86. //获取加速度传感器的三个参数
  87. float x = event.values[SensorManager.DATA_X];
  88. float y = event.values[SensorManager.DATA_Y];
  89. float z = event.values[SensorManager.DATA_Z];
  90. //获取当前时刻的毫秒数
  91. curTime = System.currentTimeMillis();
  92. //100毫秒检测一次
  93. if ((curTime - lastTime) > 100) {
  94. duration = (curTime - lastTime);
  95. // 看是不是刚开始晃动
  96. if (last_x == 0.0f && last_y == 0.0f && last_z == 0.0f) {
  97. //last_x、last_y、last_z同时为0时,表示刚刚开始记录
  98. initTime = System.currentTimeMillis();
  99. } else {
  100. // 单次晃动幅度
  101. shake = (Math.abs(x - last_x) + Math.abs(y - last_y) + Math.abs(z - last_z)) / duration * 100;
  102. }
  103. //把每次的晃动幅度相加,得到总体晃动幅度
  104. totalShake += shake;
  105. // 判断是否为摇动,这是我自己写的标准,不准确,只是用来做教学示例,别误会了^_^
  106. if (totalShake > 10 && totalShake / (curTime - initTime) * 1000 > 10) {
  107. startRecord();
  108. initShake();
  109. }
  110. tx1.setText("总体晃动幅度="+totalShake+ "\n平均晃动幅度="+totalShake / (curTime - initTime) * 1000 );
  111. }
  112. last_x = x;
  113. last_y = y;
  114. last_z = z;
  115. lastTime = curTime;
  116. }
  117. }
  118. };
  119. //在传感器管理器中注册监听器
  120. sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL);
  121. }
  122. // 开始录音
  123. public void startRecord() {
  124. //把正在录音的标志设为真
  125. isRecoding = true;
  126. //存放文件
  127. File file = new File("/sdcard/" + "YY"
  128. + new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".amr");
  129. Toast.makeText(getApplicationContext(), "正在录音,录音文件在" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
  130. // 创建录音对象
  131. mr = new MediaRecorder();
  132. // 从麦克风源进行录音
  133. mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
  134. // 设置输出格式
  135. mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
  136. // 设置编码格式
  137. mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
  138. // 设置输出文件
  139. mr.setOutputFile(file.getAbsolutePath());
  140. try {
  141. // 创建文件
  142. file.createNewFile();
  143. // 准备录制
  144. mr.prepare();
  145. } catch (IllegalStateException e) {
  146. e.printStackTrace();
  147. } catch (IOException e) {
  148. e.printStackTrace();
  149. }
  150. // 开始录制
  151. mr.start();
  152. recordButton.setText("录音中……");
  153. }
  154. //摇动初始化
  155. public void initShake() {
  156. lastTime = 0;
  157. duration = 0;
  158. curTime = 0;
  159. initTime = 0;
  160. last_x = 0.0f;
  161. last_y = 0.0f;
  162. last_z = 0.0f;
  163. shake = 0.0f;
  164. totalShake = 0.0f;
  165. }
  166. }

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

晃动机器,开始录音。

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

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

Android传感器编程带实例的更多相关文章

  1. Android传感器编程带实例(转)

    源:http://www.cnblogs.com/xiaochao1234/p/3894751.html 看了程序人生 网站的 编程高手的编程感悟 深有感触,好像也是一个android 程序员写的,推 ...

  2. android 传感器应用

    本章讲述Android开发中,传感器应用相关的知识点. 1.功能需求 做一个基于传感器的水平尺应用. 2.软件实现

  3. 《Android传感器高级编程》

    <Android传感器高级编程> 基本信息 原书名:Professional Android Sensor Programming 原出版社: Wrox 作者: (美)米内特(Greg M ...

  4. 《android传感器高级编程》译者序

    翻看手机中的应用,就能发现大多数应用都已经使用了传感器.让微信彻底火起来的“附近的人”和“摇一摇”.碰一碰交换信息的Bump.各种运动记录app.神奇的“磁力探测仪”.火爆的游戏Temple Run… ...

  5. Qt on Android 核心编程

    Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著   ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 4 ...

  6. 《Qt on Android核心编程》介绍

    <Qt on Android核心编程>最终尘埃落定.付梓印刷了. 2014-11-02更新:china-pub的预售链接出来了.折扣非常低哦. 封面 看看封面的效果吧,历经几版,最终就成了 ...

  7. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  8. Android开发入门经典实例

    开发实例概述 今天带大家做一个简单的Android App,这个App会显示创新工程实践老师们的照片和信息,不妨先看一看效果: 虽然这个App非常简单,但是涉及到了Android开发中的一些关键知识, ...

  9. Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

随机推荐

  1. ASP.NET MVC+Bootstrap个人博客之打造清新分页Helper(三)

    有点另类,分页直接是在后台拼接好html,然后发送到前台的: 1. 分页容器: <div class="pagination"> <ul> //****** ...

  2. 2014年acm亚洲区域赛·鞍山站

    今天北京赛站的比赛也结束了···看了一天的直播之后意识到鞍山站的比赛都过去了一个多月了···这一个月比较萎靡···整天都在睡觉写报告画工图中度过··· 鞍山比哈尔滨还是暖和很多的···就是山上有奇怪的 ...

  3. LightOJ 1427 -Repository(ac自动机)

    题意: 求每个模式串在母串中出现的次数 #include <map> #include <set> #include <list> #include <cma ...

  4. poj 1505 Copying Books

    http://poj.org/problem?id=1505 Copying Books Time Limit: 3000MS   Memory Limit: 10000K Total Submiss ...

  5. js获取浏览器基本信息:document.body.clientWidth/clientHeight/scrollWidth/scrollTop。(转)

    js获取浏览器基本信息:document.body.clientWidth/clientHeight/scrollWidth/scrollTop. 分类: js.jquery.ext.js技术2011 ...

  6. Chrome多线程模型

    为什么使用多线程? Chrome的多线程模型主要解决什么问题? 如何实现该问题的解决? 1. 解决问题 Chrome有很多线程,这是为了保持UI线程(主线程)的高响应度,防止被其他费时的操作阻碍从而影 ...

  7. ArcMap10.1无法保存编辑的内容

    问题描述:在arcMap10.1中编辑SDE库中要素,保存编辑内容时报错: 无法保存编辑内容.基础DBMS错误[ORA-29877:failed in the execution of the ODC ...

  8. linux网络编程笔记——UDP

    目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ...

  9. Spark SQL概念学习系列之为什么使用 Spark SQL?(二)

    简单地说,Shark 的下一代技术 是Spark SQL. 由于 Shark 底层依赖于 Hive,这个架构的优势是对传统 Hive 用户可以将 Shark 无缝集成进现有系统运行查询负载. 但是也看 ...

  10. Xcode 的正确打开方式——Debugging

    程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不可避免地需要使用 Xcode.这篇博客就主要介绍了 Xcode 中几种能够大幅提升代码调试效率的方式. “If debuggi ...