传感器Sensor

传感器是Android用来感知周围环境以及运动信息的工具。因为具体的感应信息依赖于相关硬件,所以虽然Android提供了众多的感应器,但不是每部手机都能支持这么多感应器,恰恰相反,大多数安卓手机仅仅支持包括加速度在内的少数几个感应器。


传感器借助于硬件来监听环境改变的事件,从这个意义上来说,Android的事件都是由某个传感器触发,只不过这个触发来源可能是软件,也可能是屏幕,甚至可能是手机的sim卡。回顾一下之前的事件通信章节,我们会发现,原来它们在本质上跟传感器是类似的,比如说:
1、软件感应:UI事件(参见《 Android开发笔记(四十四)动态UI事件》)、媒体播放事件(参见《 Android开发笔记(五十七)录像录音与播放》)、浏览器加载、交互与下载事件(参见《 Android开发笔记(六十四)网页加载与HTML5框架》)。
2、屏幕感应:点击事件(参见《 Android开发笔记(四十三)点击事件》)、手势事件(参见《 Android开发笔记(四十五)手势事件》)、拖动条的拖动事件(参见《 Android开发笔记(五十八)铃声与震动》)。
3、sim卡感应:手机相关事件(参见《 Android开发笔记(四十六)手机相关事件》)。
4、摄像头感应:拍照事件(参见《 Android开发笔记(五十六)摄像头拍照》)。
5、麦克风感应:录音事件(参见《 Android开发笔记(五十七)录像录音与播放》)。


下面是目前Android支持的感应器类型:
1 TYPE_ACCELEROMETER //加速度
2 TYPE_MAGNETIC_FIELD //磁场
3 TYPE_ORIENTATION //方向,该类型已弃用,取而代之的是getOrientation方法
4 TYPE_GYROSCOPE //陀螺仪
5 TYPE_LIGHT //光线
6 TYPE_PRESSURE //压力
7 TYPE_TEMPERATURE //温度,该类型已弃用,取而代之的是TYPE_AMBIENT_TEMPERATURE
8 TYPE_PROXIMITY //距离
9 TYPE_GRAVITY //重力
10 TYPE_LINEAR_ACCELERATION //线性加速度
11 TYPE_ROTATION_VECTOR //旋转矢量
12 TYPE_RELATIVE_HUMIDITY //湿度
13 TYPE_AMBIENT_TEMPERATURE //环境温度
14 TYPE_MAGNETIC_FIELD_UNCALIBRATED //无标定磁场
15 TYPE_GAME_ROTATION_VECTOR //无标定旋转矢量
16 TYPE_GYROSCOPE_UNCALIBRATED //未校准陀螺仪
17 TYPE_SIGNIFICANT_MOTION //特殊动作
18 TYPE_STEP_DETECTOR //步行检测,用户每走一步就触发一次事件
19 TYPE_STEP_COUNTER //计步器,记录激活后的步伐数
20 TYPE_GEOMAGNETIC_ROTATION_VECTOR //地磁旋转矢量


加速度感应器/摇一摇

这个功能最有名的应用就是微信里的“摇一摇”了,用户通过摇晃手机来寻找周围的人;类似的业务还有摇奖、玩游戏等等。


下面以摇一摇的实现来演示传感器开发的步骤:

1、声明一个SensorManager对象,该对象从系统服务Context.SENSOR_SERVICE中获取实例;
2、编写一个传感器事件监听器,该监听器继承自SensorEventListener,同时需实现onSensorChanged和onAccuracyChanged两个方法。其中前一个方法在感应变化时触发,业务逻辑都在这边处理;后一个方法在精度改变时触发,一般无需处理。
3、重写onResume方法,在该方法中注册传感器监听事件,使用的是registerListener方法,该方法的第二个参数为Sensor类型,须调用SensorManager对象的getDefaultSensor来获取指定类型的传感器对象。例如摇一摇功能要注册加速度感应监听器,代码示例如下:
mSensroMgr.registerListener(this,mSensroMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
4、重写onPause方法,在该方法中注销传感器事件,代码示例如下:
mSensroMgr.unregisterListener(this);


下面是摇一摇功能的核心代码:

float[] values = event.values;if (sensorType == Sensor.TYPE_ACCELEROMETER) {if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 || Math.abs(values[2]) > 15)) {tv_shake.setText(getNowDateTime()+" 恭喜您摇一摇啦");//系统检测到摇一摇事件后,震动手机提示用户mVibrator.vibrate(500);}}



前置摄像头的感应

博主的手机比较廉价,支持的感应器不多,除了加速度之外,就只有光线与距离感应器了。不过很奇怪,距离感应器只能探测到0-1厘米的距离,不会探测到2厘米以上的距离。于是好好琢磨了下,发现只有遮挡手机上面扬声器与前置摄像头所在的位置,距离感应才会变化,遮挡屏幕其余地方,距离感应并无变化。同样的,光线感应也是如此,把手机上部遮住,光线强度一下就降得很低。据此,我推测,光线与距离很可能是依靠前置摄像头来感应,所以一旦遮住前置摄像头,光线与距离感应马上就被触发了。


代码示例

下面是摇一摇、光线与距离感应的效果截图:
Android开发笔记(五十九)巧用传感器_第1张图片


下面是传感器开发(摇一摇)的完整代码例子:
import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import android.app.Activity;import android.content.Context;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;import android.os.Vibrator;import android.util.Log;import android.widget.TextView;import com.example.exmcamera.R;public class SensorActivity extends Activity implements SensorEventListener {private static final String TAG = "SensorActivity";private TextView tv_sensor;private TextView tv_shake;private TextView tv_light;private TextView tv_distance;private SensorManager mSensroMgr;private Vibrator mVibrator;private String[] mSensorType = {"加速度", "磁场", "方向", "陀螺仪", "光线", "压力", "温度", "距离", "重力", "线性加速度", "旋转矢量", "湿度", "环境温度", "无标定磁场", "无标定旋转矢量", "未校准陀螺仪", "特殊动作", "步行检测", "计步器", "地磁旋转矢量"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sensor);tv_sensor = (TextView) findViewById(R.id.tv_sensor);tv_shake = (TextView) findViewById(R.id.tv_shake);tv_light = (TextView) findViewById(R.id.tv_light);tv_distance = (TextView) findViewById(R.id.tv_distance);mSensroMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);showSensorInfo();}private void showSensorInfo() {List<Sensor> sensorList = mSensroMgr.getSensorList(Sensor.TYPE_ALL);ArrayList<String> sensorNameList = new ArrayList<String>();String show_content = "当前支持的传感器包括:\n";for (Sensor sensor : sensorList) {sensorNameList.add(sensor.getName());String content = String.format("%s:%s\n", mSensorType[sensor.getType()-1], sensor.getName());show_content += content;}tv_sensor.setText(show_content);}private String getNowDateTime() {SimpleDateFormat s_format = new SimpleDateFormat("HH:mm:ss");Date d_date = new Date();String s_date = "";s_date = s_format.format(d_date);return s_date;}@Overrideprotected void onPause() {super.onPause();mSensroMgr.unregisterListener(this);}@Overrideprotected void onResume() {super.onResume();mSensroMgr.registerListener(this,mSensroMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);mSensroMgr.registerListener(this,mSensroMgr.getDefaultSensor(Sensor.TYPE_LIGHT),SensorManager.SENSOR_DELAY_NORMAL);mSensroMgr.registerListener(this,mSensroMgr.getDefaultSensor(Sensor.TYPE_PROXIMITY),SensorManager.SENSOR_DELAY_NORMAL);}  @Overridepublic void onSensorChanged(SensorEvent event) {int sensorType = event.sensor.getType();if (sensorType == Sensor.TYPE_ACCELEROMETER) {// values[0]:X轴,values[1]:Y轴,values[2]:Z轴float[] values = event.values;if (sensorType == Sensor.TYPE_ACCELEROMETER) {if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15 || Math.abs(values[2]) > 15)) {tv_shake.setText(getNowDateTime()+" 恭喜您摇一摇啦");//系统检测到摇一摇事件后,震动手机提示用户mVibrator.vibrate(500);}}} else if (sensorType == Sensor.TYPE_LIGHT) {float light_strength = event.values[0];tv_light.setText(getNowDateTime()+" 当前光线强度为"+light_strength);} else if (sensorType == Sensor.TYPE_PROXIMITY) {float distance = event.values[0];tv_distance.setText(getNowDateTime()+" 有不明物体接近!距离"+distance+"厘米");}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {//当传感器精度改变时回调该方法,一般无需处理}}





点此查看Android开发笔记的完整目录

更多相关文章

  1. android单选按钮事件
  2. Android学习之广播事件处理
  3. CyanogenMod 7 再把 Touchpad 的改造标竿推高,支持 WiFi、Market
  4. Android 4.0按键事件以及电源管理流程分析
  5. Android传感器融合
  6. android 软键盘Enter键事件处理

随机推荐

  1. 在Titanium中使用Android的Service
  2. 下载安装eclipse ADT插件:
  3. ClassNotFoundException解决方案总结
  4. Android设置透明状态栏,仿ios状态栏
  5. Android(安卓)SDK Manager 无法更新解决
  6. 【安卓项目】—— 口算测试APP(教程源自B
  7. android widget 之RadioGroup RadioButto
  8. Activity Window View的关系
  9. Android(安卓)6.0运行时权限申请,多权限申
  10. 直播软件开发Android项目之视频播放器