Android Developer Sensor Overview(翻译)

来源:互联网 发布:mac怎么升级至os10.11 编辑:程序博客网 时间:2024/06/05 21:18

Sensors Overview

Android平台支持以下几种类别的Sensors:
1. 运动传感器(Motion Sensor)
这类传感器沿三维空间轴测量重力和旋转力, 包括 acceleraters,gravity传感器,(Rotation vector)旋转矢量传感器等
2. 环境传感器(Environmental sensors)
这类传感器测量各种环境参数,例如环境空气温度和压力,照明和湿度。
3. 位置传感器(position Sensor)
这类传感器测量设备的物理地址,包括方向传感器( orientation)和磁力计( magnetometer)

通过Android framework层,你可以获取可用的Sensor的Raw data。
Sensor framework层提供了一些类和接口以便于开发者实现各种需求,比如,你可以完成以下实现:
1. 选择设备上的哪个sensor可用
2. 制定一个独立的sensor所具备的功能属性,比如,最大测量范围,制造商,功耗需求,解析度(resolution)等
3. 获取raw data并且定义数据采集的最小速率
4. 注册或者注销用来监听sensor变化的sensor event listener

本文是Android平台上sensor的overview,同时也介绍了sensor framework相关内容

Introduction to Sensors

通过Android framework层可以操作多种类型的sensors。这些sensor可分为两类:hardware-based和software-based。
Hardware-based sensors是内嵌在板子中的物理模块,通过直接测量环境参数来获取数据,比如acceleration,
geomagnetic(地磁),angular(角度)的改变。
Software-based sensors不是物理设备,它们模拟硬件sensor,通过采集一个或者多个硬件sensor的数据来生成属于自己的数据。
通常被称为虚拟传感器(virtual sensors)或者合成传感器(synthetic sensors),比如,线性加速度传感器和重力传感器。
表1总结了Android平台支持的sensors

很少有Android设备支持每一种sensor。例如,大多数手持设备和平板有acc和mag传感器,但是很少有设备具备压力传感器和温度传感器(这一段存疑)。

Table 1. Sensor types supported by the Android platform.
这里写图片描述
这里写图片描述

Sensor Framework

通过Android framework层可以获取sensor raw data。Sensor framework是android.hardware package的一部分,包含了以下类和接口:

SensorManager

frameworks/native/include/gui/SensorManager.h

 46 class SensorManager : 47     public ASensorManager, 48     public Singleton<SensorManager> 49 { 50 public: 51     SensorManager(); 52     ~SensorManager(); 53 54     ssize_t getSensorList(Sensor const* const** list) const; 55     Sensor const* getDefaultSensor(int type); 56     sp<SensorEventQueue> createEventQueue(); 57 58 private: 59     // DeathRecipient interface 60     void sensorManagerDied(); 61 62     status_t assertStateLocked() const; 63 64 private: 65     mutable Mutex mLock; 66     mutable sp<ISensorServer> mSensorServer; 67     mutable Sensor const** mSensorList; 68     mutable Vector<Sensor> mSensors; 69     mutable sp<IBinder::DeathRecipient> mDeathObserver; 70 };

可以用这个类创建一个Sensor service的实例。该类提供了多种方法可以用来获取并列出Sensor列表,注册和注销Sensor event listener,获取方向信息。
该类也提供了几种Sensor常量用来report传感器的准确度,设置数据采集速率,校准sensor等

Sensor

这个类用来创建一个sensor实例。该类提供多种方法用来明确一个sensor所具备的功能。

SensorEvent

这个类用来创建一个sensor event对象,该对象提供了关于sensor event的相关信息。一个sensor event对象包含以下信息:
sensor raw data,产生该事件的sensor type,数据的准确性,event发生的时间戳等

SensorEventListener

当sensor数据发生改变和sensor 准确性发生改变时,可以通过该接口创建两个callback方法接收到notification

在一个典型的应用中,可以利用上述的API实现以下两个基本任务:
1. 识别sensor和明确sensor的功能
如果应用的某些功能依赖于具体的sensor类型和功能,那么识别sensor类型和功能就很必要。
例如,你想识别设备上所有的sensor并且disable哪些不存在的sensor所支持的功能。
同样,你可能想识别某一类型的所有sensor,以便于选择对应用性能最优化的sensor。
2. 监听sensor事件(sensor event)
监听sensor事件,换句话说,即如何获取sensor raw data。每当sensor测量的数据发生改变就会产生一个sensor event。
一个sensor event提供了以下四种信息:触发事件的sensor name,触发事件的时间戳,事件的准确度,raw data

Identifying Sensors

sensor framework提供了几种方法用来确定设备上有哪些sensor,同时让开发者明确sensor的一些属性和功能,
比如maximum range,resolution,power requirements等。

为了识别设备上的sensor,首先需要得到一个sensor service的引用,为了得到sensor service,需要通过调用getSystemService来
创建一个SensorManager类的实例,传入的参数为SENSOR_SERVICE,例如:

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

然后调用getSensorList(),来获取一个list,列出了设备上所有的Sensor,例如

List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);

如果想列出给定type的所有Sensor,可以将上述参数改为TYPE_GYROSCOPE,TYPE_LINEAR_ACCELERATION,TYPE_GRAVITY等。
通过调用getDefaultSensor()方法,传入某一Sensor的类型,可以确定该类型的Sensor是否存在于设备上。如果设备上存在同一类型的多个Sensor,
其中的某一个Sensor必须被设置为default Sensor。如果某一类型的Sensor不存在default Sensor,该函数返回NULL,同时说明这个设备上不存在该类型的Sensor。
以下code用于check是否存在mag Sensor:

private SensorManager mSensorManager;...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){  // Success! There's a magnetometer.  }else {  // Failure! No magnetometer.  }

Sensor Capabilities

通过Sensor类可以确定Sensor的功能属性
getResolution()和getMaximumRange()方法可以得到Sensor的resolution和最大测量范围,getPower()方法可以用来得到Sensor的power requirement。

有的时候app需要针对不同厂商和不同版本的Sensor进行不同的处理和优化,可以调用getVendor()和getVersion()方法。
在下面的例子中,我们将尝试找到vendor为Google.Inc,版本为3的gravity,如果不存在,那么尝试使用acc Sensor

private SensorManager mSensorManager;private Sensor mSensor;...mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mSensor = null;if (mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){  List<Sensor> gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GRAVITY);  for(int i=0; i<gravSensors.size(); i++) {    if ((gravSensors.get(i).getVendor().contains("Google Inc.")) &&       (gravSensors.get(i).getVersion() == 3)){      // Use the version 3 gravity sensor.      mSensor = gravSensors.get(i);    }  }}if (mSensor == null){  // Use the accelerometer.  if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  }  else{    // Sorry, there are no accelerometers on your device.    // You can't play this game.  }}

另一个比较有用的方法是getMinDelay,该方法返回Sensor测量数据的最小时间间隔。若返回值非0,说明该Sensor是一个streaming Sensor(流传感器),若返回NULL,说明只有当数据发生改变时该sensor才上报,不是流传感器。通过该方法可以确定sensor上报数据的最大速率,通过该方法可判断当前sensor的速率是否满足app的需求。

注意:传感器的最大数据采集速率不一定是framework层传递到app的速率,sensor framework通过sensor event上报数据,并且其他因素也会影响app接收sensor event的速率。

Monitoring Sensor Events

为了监听raw data,需要通过SensorEventListener实现两个callback 方法,它们是onAccuracyChanged()和onSensorChanged().

当发生以下情况时,这两种方法会被调用:
1. Sensor的准确度发生了改变
发生这种情况时,调用onAccuracyChanged()方法,返回发生改变的Sensor object和新的准确度,准确度有四种状态:
SENSOR_STATUS_ACCURACY_LOW,SENSOR_STATIS_ACCURACY_MEDIUM,SENSOR_STATIS_ACCURACY_HIGH,
SENSOR_STATIS_ACCURACY_UNRELIABLE等
2. Sensor上报了一个新的value
这种情况下调用onSensorChanged()方法,该方法提供了一个SensorEvent object,该object包含了关于新Sensor data的以下信息:data的准确度,产生data的Sensor,产生data的时间戳,新data的数值

以下code展示了onSensorChanged()的使用方法,监听来自光传感器的数据

public class SensorActivity extends Activity implements SensorEventListener {  private SensorManager mSensorManager;  private Sensor mLight;  @Override  public final void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);    mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);  }  @Override  public final void onAccuracyChanged(Sensor sensor, int accuracy) {    // Do something here if sensor accuracy changes.  }  @Override  public final void onSensorChanged(SensorEvent event) {    // The light sensor returns a single value.    // Many sensors return 3 values, one for each axis.    float lux = event.values[0];    // Do something with this sensor value.  }  @Override  protected void onResume() {    super.onResume();    mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);  }  @Override  protected void onPause() {    super.onPause();    mSensorManager.unregisterListener(this);  }}

在这个例子中,调用registerListener时指定了默认的数据延迟(SENSOR_DELAY_NORMAL),该数据延迟(或者叫采样频率)控制了sensor event传递到app的时间间隔,这些数据通过onSensorChanged()传递。默认的数据延迟适应监测屏幕方向改变,被设置为200000ms,也可以指定其他数据延迟,比如SENSOR_DELAY_GAME(20000 ms delay),SENSOR_DELAY_UI(60000 ms),SENSOR_DELAY_FASTEST(0 delay),也可以设置为为指定的值。

这里指定的delay只是一个suggested delay,Android系统及其他应用可以修改这个值。从实践中来看,你应该指定一个满足需求的最大值(即满足需求的最小采样频率),因为系统通常会使用一个与之相比较小的值。用一个较大的delay可以减小处理器的负载并且省电。

Android中没有公共的接口用来确定framework层将event发送到APP的速率,不过你可以通过sensor event之间的时间戳来确定采样频率。设置过采样频率(data delay)以后不应该再做修改,如果修改,需要先unregister然后register sensor listener才能生效。

Sensor Coordinate System

通常,Sensor framework用一个标准的三轴坐标系来表示数值。对于大多数sensor,坐标系的方向是与设备保持默认方向时的屏幕相关的(如图1)。Acc,Gravity,Gyro,Linear Acc,Geomagnetic等sensor都使用该坐标系。
这里写图片描述
注意,当设备的屏幕方向改变时,轴不会交换,也就是说,当设备移动时,传感器的坐标系不会改变。
最后,如果应用程序将传感器数据与屏幕显示匹配,则需要使用getRotation()方法确定屏幕旋转,然后使用remapCoordinateSystem()方法将传感器坐标映射到屏幕坐标。 即使您的清单指定仅纵向显示,您仍需要执行此操作。

0 0
原创粉丝点击