提到手机上的传感器大家应该都不陌生,比如说方向传感器、陀螺仪、重力传感器、光线传感器等。现在的手机基本集成少说有十几种传感器,面向将来的人工智能,这块知识也是我们必备的。

传感器分类

Android 平台支持三大类传感器:

  • 动态传感器
    这类传感器测量三个轴向上的加速力和旋转力。包含加速度传感器重力传感器陀螺仪旋转矢量传感器
  • 环境传感器
    这类传感器测量各种环境参数,如环境气温、气压、照度和湿度。这个类别中包含气压计光度计温度计
  • 位置传感器
    这类传感器测量设备的物理位置。这个类别中包含屏幕方向传感器磁力计(电子罗盘)

传感器使用

Android平台上google已经为我们提供了一套很方便的传感器框架,我们只需在这个框架下定义自己要用的传感器并实现其逻辑即可。

传感器框架是 android.hardware 软件包的一部分,开发使用过程中主要用到了以下类和接口:

  1. SensorManager
  2. Sensor
  3. SensorEventListener
  4. SensorEvent

第一步:获取传感器管理对象

SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

第二步:指定传感器目标类型

// 获取传感器的类型(TYPE_ACCELEROMETER:加速度传感器)
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

这里指定的传感器类型有很多种,这里暂且列举一些最常用的传感器:

  • Sensor.TYPE_ACCELEROMETER: 三轴加速度传感器
  • Sensor.TYPE_ORIENTATION:方向传感器
  • Sensor.TYPE_GYROSCOPE:陀螺仪传感器
  • Sensor.TYPE_MAGNETIC_FIELD:磁力传感器
  • Sensor.TYPE_GRAVITY:重力传感器
  • Sensor.TYPE_LINEAR_ACCELERATION:线性加速度传感器
  • Sensor.TYPE_AMBIENT_TEMPERATURE:温度传感器
  • Sensor.TYPE_LIGHT:光传感器
  • Sensor.TYPE_PRESSURE:压力传感器
  • Sensor.TYPE_ALL:所有类型的传感器,通过getSensorList返回所有支持的传感器列表。

第三步:注册传感器监听

SensorEventListener mListener = new SensorEventListener() {// 当传感器的值改变的时候回调该方法@Overridepublic void onSensorChanged(SensorEvent event) {// Do something with this sensor value.// The light sensor returns a single value.// Many sensors return 3 values, one for each axis.}// 当传感器精度发生改变时回调该方法@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// Do something here if sensor accuracy changes.}
}mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);

其中registerListener最后一个参数是指定传感器获取数据的频率,有以下四种形式:

  1. SensorManager.SENSOR_DELAY_NORMAL,正常频率,一般对实时性要求不高的应用适合使用这种频率。
  2. SensorManager.SENSOR_DELAY_FASTEST,最快,延迟最小,同时也最消耗资源,一般只有特别依赖传感器的应用使用该频率,否则不推荐。
  3. SensorManager.SENSOR_DELAY_GAME,适合游戏的频率,一般有实时性要求的应用适合使用这种频率。
  4. SensorManager.SENSOR_DELAY_UI,适合普通应用的频率,这种模式比较省电,而且系统开销小,但延迟大,因此只适合普通小程序使用。

一旦传感器监测到环境数据变化,便会回调两个实现方法:

  • onSensorChanged(SensorEvent event):传感器报告了新值。
    内部的SensorEvent 对象包含关于新传感器数据的信息,包括:数据的准确度、生成数据的传感器、生成数据的时间戳以及传感器记录的新数据,系统可能会频繁调用,切记请勿阻塞 onSensorChanged() 方法

  • onAccuracyChanged(Sensor sensor, int accuracy):传感器的准确度发生了变化。
    当传感器精度发生变化时onAccuracyChanged被触发。第一参数是发生变化的sensor对象,第二个参数是传感器的新精度(准确度)。精度有以下四种:

    • SENSOR_STATUS_ACCURACY_LOW:低精度值
    • SENSOR_STATUS_ACCURACY_MEDIUM:平均精度值
    • SENSOR_STATUS_ACCURACY_HIGH:高精度值
    • SENSOR_STATUS_UNRELIABLE:精度值不可靠

第四步:解注册传感器监听

mSensorManager.unregisterListener(mListener)

传感器几乎是非常消耗资源的,最佳的做法是始终停用不需要的传感器,特别是在活动处于暂停状态时。如果不这样做,可能会在几小时内将电池电量耗尽。

第三步和第四步开发过程中一般是相呼应的,我们常常在onResume中进行注册,在onPause中进行解注册,也可根据业务需要自行确定时机。

运行时检测传感器

有时我们不能确定当前设备是否包含我们所需的传感器,所以在运行时我们需要做一个判断:

Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
if(sensor != null){// Success! There's a pressure sensor.
}else{// Failure! No pressure sensor.
}

如果您要在 Google Play 上发布应用,您可以在清单文件中使用 <uses-feature> 元素,以对不具备适合您应用的传感器配置的设备屏蔽您的应用,以下清单示例条目会对没有加速度计的设备屏蔽应用:

<uses-feature android:name="android.hardware.sensor.accelerometer"android:required="true" />

传感器坐标系

大部分传感器都是以三轴坐标来表示数据值。对于大多数传感器,当设备处于默认屏幕方向(平板和手机就有可能不一样)时,会相对于设备屏幕来定义坐标系,如下图:

以下传感器使用此坐标系:

  • 加速度传感器
  • 重力传感器
  • 陀螺仪
  • 线性加速度传感器
  • 地磁场传感器

记着,传感器的坐标系是始终跟随设备的。

小栗子

下边就是通过三轴加速度传感器实现一个计步器功能,代码来源于网络,个人稍加注释:

public class StepDetector implements SensorEventListener{private final static String TAG = "StepDetector";private float   mLimit = 10;private float   mLastValues[] = new float[3*2];private float   mScale[] = new float[2];private float   mYOffset;private float   mLastDirections[] = new float[3*2];private float   mLastExtremes[][] = { new float[3*2], new float[3*2] };private float   mLastDiff[] = new float[3*2];private int     mLastMatch = -1;private ArrayList<StepListener> mStepListeners = new ArrayList<StepListener>();public StepDetector() {// 手机屏幕的高int h = 480;// 中心点,y轴的偏移量mYOffset = h * 0.5f;// 获取重力相关参数mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));}public void setSensitivity(float sensitivity) {//灵敏度 1.97  2.96  4.44  6.66  10.00  15.00  22.50  33.75  50.62mLimit = sensitivity; }public void addStepListener(StepListener sl) {mStepListeners.add(sl);}//public void onSensorChanged(int sensor, float[] values) {public void onSensorChanged(SensorEvent event) {Sensor sensor = event.sensor; synchronized (this) {int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;if (j == 1) {//三个方向上的速度和float vSum = 0;for (int i=0 ; i<3 ; i++) {final float v = mYOffset + event.values[i] * mScale[j];vSum += v;}int k = 0;//平均速度float v = vSum / 3;float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));if (direction == - mLastDirections[k]) {// Direction changedint extType = (direction > 0 ? 0 : 1); // minumum or maximum?mLastExtremes[extType][k] = mLastValues[k];float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);//运动太慢,忽略if (diff > mLimit) {boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);boolean isNotContra = (mLastMatch != 1 - extType);//判断有效的一步 if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {Log.i(TAG, "step");for (StepListener stepListener : mStepListeners) {stepListener.onStep();}mLastMatch = extType;}else {mLastMatch = -1;}}mLastDiff[k] = diff;}mLastDirections[k] = direction;mLastValues[k] = v;}}}public void onAccuracyChanged(Sensor sensor, int accuracy) {// TODO Auto-generated method stub}
}

参考

  • https://developer.android.com/guide/topics/sensors/sensors_overview

淦!玩一玩Android传感器相关推荐

  1. 玩转java(Android)注解

    2019独角兽企业重金招聘Python工程师标准>>> 玩转java(Android)注解 1. java标准(原生)注解概览 Java API 中,在java.lang.java. ...

  2. Google 已经实现即点即玩,国内 Android 何时跟上?

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 犹记得在两年前的 Google I/O 上,Google 推出了能够即点即用的 Instan ...

  3. 玩一玩Android下载框架

    前言 继上篇<不一样的HTTP缓存体验>已经有一段时间了,一直没写教学型文章不是因为太忙,想了很久不知道以什么为主题,有个哥们看了我的开源项目CrazyDaily,好像对下载挺感兴趣,那我 ...

  4. 7x android 8,荣耀畅玩7X升级Android 8.0!内测开启

    原标题:荣耀畅玩7X升级Android 8.0!内测开启 [手机中国 新闻]2月26日,荣耀畅玩7X正式开启升级"奥利奥"Android 8.0之路,部分花粉已收到Beta版本内测 ...

  5. Android传感器-开发指南

    大部分Android平台的设备都带有多个传感器,使你能监视其方位和运动状态的变化.很多设备还有其它类型的传感器,让你能感知周围的环境条件,比如温度.压力.湿度和光线.你可以利用Android的传感器框 ...

  6. Egret QQ玩一玩适配【踩坑日记】

    需要申明一点,这是我接过最坑的渠道了,各种神奇的问题,首先是接口比较奇怪而且新旧版本搞得很混乱,其次是平台底层实现性能差而且很多限制.此外,这里需要理清楚一个概念:QQ 玩一玩 和 QQ 玩吧 并非同 ...

  7. QQ玩一玩(轻游戏)开发环境搭建与调试

    玩一玩开发环境搭建与调试 前言 Android 调试 下载Android Studio 配置环境变量 进入用户当前目录 设置环境变量 设置生效 检查配置是否正常 下载特殊版测试Q 调试时Android ...

  8. QQ玩一玩(轻游戏)入门到放弃?

    姓名:Javen Email:javendev@126.com Github:https://github.com/Javen205 Gitee:https://gitee.com/Javen205 ...

  9. 玩一玩登录鉴权与生命周期

    登录与鉴权 玩一玩平台登录是依赖于QQ服务号,类似微信公众号的授权登录,只是玩一玩平台在后台自动获取用户对应的openId. 下面是详细的流程 游戏加载流程 游戏加载主要分为两个阶段,准备阶段 是由手 ...

  10. 玩一玩游戏之Hello World

    环境搭建 下载引擎代码 Hello World 修改配置文件 需求实现 运行测试 手Q中测试 环境搭建 由于目前玩一玩开发平台仅支持Mac,所以你需要一台Mac电脑或者黑苹果(但不推荐) 1.注册苹果 ...

最新文章

  1. scrum看板工具做问题跟踪
  2. 90行代码!大一学生自学编程,自创搜题网站,已在GitHub开源
  3. 扎格伯克败走加密货币:2亿美元打包变卖技术,核心团队出走殆尽,发币计划仅2年就从入门到放弃...
  4. 人人可以理解的区块链100问——比特币可以用于支付吗?
  5. 使用Synchronized块同步方法
  6. UGUI_不添加摄像机解决UI与UI特效叠层
  7. a data source instance has not been supplied for the datasource 'dataset1'. rdlc
  8. 三、操作系统——生产者-消费者问题(两个同步一个互斥)
  9. 随笔 - C/C++
  10. servlet输出中文乱码
  11. c语言程序原版PDF,正式版C语言程序设计.pdf
  12. 数学建模方法——斯皮尔曼相关系数及其显著性检验 (Spearman’s correlation coefficient for ranked data)
  13. 周爱民:详解架构的核心原则
  14. 【机器学习|数学基础】Mathematics for Machine Learning系列之线性代数(5):克拉默法则
  15. Latex常见数学符号写法
  16. 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
  17. 2018互联网实习秋招回顾(BATM+MS+Intel+NE+DJI)
  18. 关于数据驱动消费金融业务的几点看法
  19. 康耐视智能相机IO操作笔记
  20. SharePoint Silverlight Clock 时钟

热门文章

  1. 前后端分离项目Nginx部署
  2. graphpad prism横坐标怎么设置不显示数值_Graphpad Prism能不能画九象限图?
  3. word 行 底色 底纹
  4. vscode 设置背景图片
  5. 取消b站充电鸣谢!!!
  6. pos机的热敏纸尺寸
  7. Vue小字典-vue基础
  8. web前端设计与开发大作业(四)----主页导航界面
  9. VSCode中设置Python语言自动格式化的方案
  10. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java基于Web的小区物业管理系统2xjhe