跳转至

安卓传感器开发实验的准备

传感器是物联网感知层的核心组成部分,通过调用传感器,我们可以从环境中感知各种类型的信息。为了使读者更直观地理解传感器的功能与特点,设计了基于安卓手机的传感器调用实验使同学们能够有直观的感受,也为未来的开发打下基础。

总体上这部分的参考资料很多,建议大家多找不同的参考资料,其中最好的参考资料是Android提供的官方文档,内容都很详细。

基于传感器进行追踪,我们专门写了一个综述的论文,对现在的工作进行了总结,大家可以作为参考。论文如下:

Zhipeng Song,Zhichao Cao,Zhenjiang Li,Jiliang Wang,Yunhao Liu. Inertial Motion Tracking on Mobile and Wearable Devices: Recent Advancements and Challenges. Tsinghua Science and Technology, 2021, 26(5): 692-705.

1. 手机传感器

现代智能手机为了实现多样化的功能,往往配备了大量的传感器,本节先向大家简要介绍智能手机中常用的几种传感器

图. 智能手机中常见的传感器

1.1. 光线感应器(Ambient Light Sensor)

光线传感器根据环境入射光线调整手机屏幕的亮度。在明亮的户外,屏幕会自动调到最亮的状态;而当在黑暗环境里,屏幕亮度会相应降低。

1.2. 距离感应器(Proximity Sensor)

距离传感器由一个红外LED灯和一个红外辐射探测器组成。距离传感器位于手机听筒的附近,其工作原理是:红外LED灯发送红外光,经物体反射后,被红外辐射探测器接收,根据收发延时计算传感器到物体的距离。

1.3. 重力传感器

重力传感器,通过压电效应来实现。重力传感器内部包含一块重物和一块压电片。当传感器受到来自某一方向的压力,与压力方向正交的另外两个方向将产生一定电压。根据电压大小,即可计受力方向的压力大小。

1.4. 加速度传感器

加速度传感器的原理与重力传感器类似,当物体由加速度发生速度变化时,传感器由于惯性产生沿运动方向的压力,根据压力可以反推出加速度的大小。加速度传感器是多个维度测算的,主要测算一些瞬时加速或减速的动作。

1.5. 指纹传感器

指纹传感器的主要功能是实现指纹自动采集,市场上的指纹传感器主要分为两类:光学指纹传感器和半导体指纹传感器。前者利用光的折射和反射原理,根据反射光线的明暗还原手指表面凹凸不平的纹路;后者使用电容或电感元件,根据凹接触点和凸接触点电容/电感数值的不同,还原手指表面纹理。

1.6. 陀螺仪传感器(Gyroscope)

目前手机中常用的陀螺仪传感器是三轴陀螺仪,可追踪6个方向的位移变化。

1.7. 磁场传感器(MagneTIsm Sensor)

磁场传感器是利用磁阻来测量平面磁场,从而检测出磁场强度以及方向位置。一般用在常见的指南针或是地图导航中,帮助手机用户实现准确定位。

1.8. GPS位置传感器

GPS模块主要作用是通过天线来接收到卫星的坐标信息帮用户定位。

1.9. 气压传感器

当气压发生变化时,电阻或电容的测算数值都发生改变,根据这一特性,可以通过测算电阻或电容监测气压变化。根据感应元件不同,气压传感器可以分为变容式气压传感器和变阻式气压传感器。

1.10. 温度传感器

手机中常用的温度传感器是用于检测手机电池的温度变化,根据电池温度对手机工作模式进行调整。同时,利用手机的温度传感器也可以看出手机的发热程度。

1.11. 霍尔传感器

霍尔传感器与磁场传感器类似,霍尔传感器可以将变化的磁场转化为输出电压,从而在导体两端产生电势差。霍尔传感器常用于实现手机保护套功能,当合上保护套时手机会自动锁屏,打开保护套之后设备又会自动解锁。

2. 安卓传感器开发

Android系统提供了对传感器的支持,只要手机配备了相应的传感器硬件,我们就可以通过代码读取传感器的数值,从而获取手机外部的状态,例如手机的摆放状态、外界的磁场、温度和压力等等。

针对市场上常见的大部分传感器,Android系统都提供了相应的调用接口,因此对开发者来说,传感器开发十分简单:只需要注册监听器,接收回调的数据即可。下面以手机自带的加速度传感器为例,详细介绍传感器的开发步骤。

2.1 加速度传感器的开发与使用

  • 第一步: 获取传感器管理对象SensorManager 实例,SensorManager 是系统所有传感器的管理器,安卓中所有对传感的调用都要通过SensorManager 完成。
private final SensorManager mSensorManager;
// 在onCreate()中获取SensorManager实例
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    ...
}

利用SensorManager还可以搜索当前手机上安装的全部传感器列表:

List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
  • 第二步: 从SensorManager中获取传感器目标传感器实例(本例中为TYPE_ACCELEROMETER:加速度传感器)
private final Sensor mAccelerometer;
// 在onCreate()中获取SensorManager实例
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    mAccelerometer = mSensorManager.getDefaultSensor(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:压力传感器

  • 第三步: 为传感器注册监听器,监听传感器传回的数据。注意此处应该在onResume()函数中注册监听,因为onResume()函数调用后对应的Activity才会被切换到前台。过早注册监听器将使传感器过早的处于工作状态,既浪费电池电量,又可能造成传感器的竞争使用。
private final TestSensorListener mSensorListener;
// 在onCreate()中初始化监听器,监听器在第四步中重写
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    mSensorListener = new TestSensorListener();
    ...
}

// 在onResume()中注册监听器
@Override
protected void onResume() {
    super.onResume();
    mSensorManager.registerListener(mSensorListener, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}

附上registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs)函数的三个参数说明:

listener:监听传感器时间的监听器,该监听器需要实现SensorEventListener接口

sensor:传感器对象

samplingPeriodUs:指定获取传感器频率,一共有如下几种:

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

此外还需要注意,当Activity被停止或被切到后台时(即当onPause()被调用时),需要销毁之前注册的监听器,释放传感器资源。

@Override
protected void onPause() {
    super.onPause();
    // 注销监听函数
    mSensorManager.unregisterListener(mSensorListener);
}
  • 第四步: 重写监听器,自定义回调函数,当传感器读数发生变化时将变化后的读数显示出来。传感器底层驱动所做的工作是读传感器芯片上的寄存器,因此onSensorChanged()函数的触发条件是传感器芯片寄存器中的数据发生变化。
class TestSensorListener implements SensorEventListener {
    @Override
    public void onSensorChanged(SensorEvent event) {
        // 读取加速度传感器数值,values数组0,1,2分别对应x,y,z轴的加速度
        Log.i(TAG, "onSensorChanged: " + event.values[0] + ", " + event.values[1] + ", " + event.values[2]);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        Log.i(TAG, "onAccuracyChanged");
    }

}

加速度传感器实验程序的运行结果如下图所示,可以发现沿垂直地心方向总是存在一个重力加速度。

图. 加速度传感器实验效果