Android相关

传感器

2019-07-17  本文已影响19人  Anwfly

知识要点:

1、传感器的简介及分类

1.1传感器的概述及应用场景
1.2传感器分类介绍

2、方向传感器获取参数的实现

2.1 SensorEvent类
2.2 SensorEventListener接口
2.3 SensorManager
2.4 每种传感器对应的常量值

案例:微信摇一摇、指南针

目标要求:

1、了解传感器在开发中的使用

2、了解传感器开发场景

3、掌握方向传感器获取参数

一.Android的三大类传感器

 Android传感器按大方向划分大致有三类传感器:动作(Motion)传感器、环境(Environmental)传感器、位置(Position)传感器。

  1. 动作传感器
    这类传感器在三个轴(x、y、z)上测量加速度和旋转角度。包括如下几个传感器:加速(accelerometer)传感器、重力(gravity)传感器、陀螺仪(gyroscope)传感器、旋转向量(rotational vector )传感器

    下面来看一下传感器世界的坐标系: 20180115223132900.png
  2. 环境传感器
    这类传感器可以测量不同环境的参数,例如,周围环境的空气温度和压强、光照强度和湿度。包括如下几个传感器:

湿度(barometer)传感器、光线(photometer)传感器、温度(thermometer)传感器

  1. 位置传感器
    这类传感器可以测量设备的物理位置。包括如下几个传感器:方向(orientation)传感器、磁力(magnetometer)传感器

了解后我们就开始进入传感器的编程工作了,接下来我们看一下Android为我们提供的传感器框架(Android sensor framework,简称ASF)。

二.Android传感器框架

 Android SDK为我们提供了ASF,可以用来访问当前Android设备内置的传感器。ASF提供了很多类和接口,帮助我们完成各种与传感器有关的任务。例如:

1)确定当前Android设备内置了哪些传感器。
2)确定某一个传感器的技术指标。
3)获取传感器传回来的数据,以及定义传感器回传数据的精度。
4)注册和注销传感器事件监听器,这些监听器用于监听传感器的变化,通常从传感器回传的数据需要利用这些监听器完成。

ASF允许我们访问很多传感器类型,这些传感器有一些是基于硬件的传感器,还有一些是基于软件的传感器。基于硬件的传感器就是直接以芯片形式嵌入到Android设备中,这些传感器直接从外部环境获取数据。基于软件的传感器并不是实际的硬件芯片,基于软件的传感器传回的数据本质上也来自于基于硬件的传感器,只是这些数据通常会经过二次加工。所以基于软件的传感器也可以称为虚拟(virtual)传感器或合成(synthetic)传感器。

Android对每个设备的传感器都进行了抽象,其中SensorManger类用来控制传感器,Sensor用来描述具体的传感器,SensorEventListener用来监听传感器值的改变。

(1)SensorManager类

用于创建sensor service的实例。该类提供了很多用于访问和枚举传感器,注册和注销传感器监听器的方法。而且还提供了与传感器精度、扫描频率、校正有关的常量。

(2)Sensor类

Sensor类为我们提供了一些用于获取传感器技术参数的方法。如版本、类型、生产商等。例如所有传感器的TYPE类型如下:

Sensor类为我们提供了一些用于获取传感器技术参数的方法。如版本、类型、生产商等。例如所有传感器的TYPE类型如下:

序号 传感器 Sensor类中定义的TYPE常量
1 加速度传感器 TYPE_ACCELEROMETER
2 温度传感器 TYPE_AMBIENT_TEMPERATURE
3 陀螺仪传感器 TYPE_GYROSCOPE
4 光线传感器 TYPE_LIGHT
5 磁场传感器 TYPE_MAGNETIC_FIELD
6 压力传感器 TYPE_PRESSURE
7 临近传感器 TYPE_PROXIMITY
8 湿度传感器 TYPE_RELATIVE_HUMIDITY
9 方向传感器 TYPE_ORIENTATION
10 重力传感器 TYPE_GRAVITY
11 线性加速传感器 TYPE_LINEAR_ACCELERATION
12 旋转向量传感器 TYPE_ROTATION_VECTOR

注意:1-8是硬件传感器,9是软件传感器,其中方向传感器的数据来自重力和磁场传感器,10-12是硬件或软件传感器。

(3)SensorEvent类

系统使用该类创建传感器事件对象。该对象可以提供与传感器事件有关的信息。传感器事件对象包括的信息有原始的传感器回传数据、传感器类型、数据的精度以及触发事件的时间。

(4)SensorEventListener接口

该接口包含两个回调方法,当传感器的回传值或精度发生变化时,系统会调用这两个回调方法。

/**
 * 传感器精度变化时回调
 */
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/**
 * 传感器数据变化时回调
 */
@Override
public void onSensorChanged(SensorEvent event) {
}

三.获取传感器技术参数

下来我们编写代码来获取一下自己手机的传感器技术参数。

//获取传感器SensorManager对象
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
    tvSensors.append(sensor.getName() + "\n");
}

各种传感器的使用:

1.加速度传感器

在这这之前先了解一下手机传感器世界的三维坐标

20180115223132900.png
//创建一个SensorManager来获取系统的传感器服务
sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
/*
 * 最常用的一个方法 注册事件
 * 参数1 :SensorEventListener监听器
 * 参数2 :Sensor 一个服务可能有多个Sensor实现,此处调用getDefaultSensor获取默认的Sensor
 * 参数3 :模式 可选数据变化的刷新频率,多少微秒取一次。
 * */
//加速度传感器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);

接下来我们只要监听这个传感器值的变化,然后更新textView的值就好了

@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        float X_lateral = sensorEvent.values[0];
        float Y_longitudinal = sensorEvent.values[1];
        float Z_vertical = sensorEvent.values[2];
        mtextViewx.setText(X_lateral + "");
        mtextViewy.setText(Y_longitudinal + "");
        mtextViewz.setText(Z_vertical + "");
    }
}

在activity变为不可见的时候,传感器依然在工作,这样很耗电,所以我们根据需求可以在onStop方法里面停掉传感器的工作

@Override
public void onStop() {
    sm.unregisterListener(this);
    super.onStop();
}
  1. 磁场传感器

和加速度计一样,为sensormanager监听磁场变化即可,把手机放在电脑旁边时候可以清楚看到数值的变化

// 为磁场传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
else if(sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
    float X_lateral = sensorEvent.values[0];
    float Y_longitudinal = sensorEvent.values[1];
    float Z_vertical = sensorEvent.values[2];
    mtextView1.setText("x轴的磁场强度\n"+ X_lateral );
    mtextView2.setText("y轴的磁场强度\n"+ Y_longitudinal );
    mtextView3.setText("z轴的磁场强度\n"+ Z_vertical );
}

3.方向传感器

这个可以用来做指南针之类的,绕z轴转过的角度为0时大概指向正北。这个TYPE_ORIENTATION接口不够精确已经过时了,可以使用旋转矩阵来代替。这里绕z轴转过的角度是value[0],看源码可得

// 为方向传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
else if(sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION){
    float X_lateral = sensorEvent.values[0];
    float Y_longitudinal = sensorEvent.values[1];
    float Z_vertical = sensorEvent.values[2];
    mtextView4.setText("绕z轴转过的角度\n"+ X_lateral );
    mtextView5.setText("绕x轴转过的角度\n"+ Y_longitudinal );
    mtextView6.setText("绕y轴转过的角度\n"+ Z_vertical );
}

4.陀螺仪传感器

// 为陀螺仪传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
else if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){
    //需要将弧度转为角度
    float X = (float)Math.toDegrees(sensorEvent.values[0]);
    float Y = (float)Math.toDegrees(sensorEvent.values[1]);
    float Z = (float)Math.toDegrees(sensorEvent.values[2]);
    mtextView7.setText("绕x轴转过的角速度\n"+ X );
    mtextView8.setText("绕y轴转过的角速度\n"+ Y );
    mtextView9.setText("绕z轴转过的角速度\n"+ Z );
}

5.重力传感器

就是把重力加速度分解到xyz三个方向上

// 为重力传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_GRAVITY), SensorManager.SENSOR_DELAY_NORMAL);
else if(sensorEvent.sensor.getType() == Sensor.TYPE_GRAVITY){
    float X = sensorEvent.values[0];
    float Y = sensorEvent.values[1];
    float Z = sensorEvent.values[2];
    mtextViewgx.setText("x方向的重力加速度\n"+ X );
    mtextViewgy.setText("Y方向的重力加速度\n"+ Y );
    mtextViewgz.setText("Z方向的重力加速度\n"+ Z );

6.线性加速度传感器

就是去掉重力加速度后各个方向的加速度

// 为线性加速度传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_NORMAL);
else if(sensorEvent.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){
    float X = sensorEvent.values[0];
    float Y = sensorEvent.values[1];
    float Z = sensorEvent.values[2];
    mtextViewlx.setText("x方向的线性加速度\n"+ X );
    mtextViewly.setText("Y方向的线性加速度\n"+ Y );
    mtextViewlz.setText("Z方向的线性加速度\n"+ Z );
}

7.温度传感器

这里的TYPE_TEMPERATURE已经过时,测出来的是cpu的温度,所以测出来的数值有点大,如果测环境温度的话应该使用

// 为温度传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_TEMPERATURE), SensorManager.SENSOR_DELAY_NORMAL);

else if(sensorEvent.sensor.getType() == Sensor.TYPE_TEMPERATURE){
    float X = sensorEvent.values[0];
    mtextView10.setText("温度为"+ X );
}

8.光传感器

// 为光传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_LIGHT), SensorManager.SENSOR_DELAY_NORMAL);

else if(sensorEvent.sensor.getType() == Sensor.TYPE_LIGHT){
    float X = sensorEvent.values[0];
    mtextView11.setText("光强度为为"+ X );
}

9.距离传感器

可以控制手机打电话时候息屏,如果使用光线传感器的话在黑夜中打电话就自动息屏了

// 为距离传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_DELAY_NORMAL);

else if(sensorEvent.sensor.getType() == Sensor.TYPE_PROXIMITY){
    float X = sensorEvent.values[0];
    mtextView12.setText("距离为"+ X );
}

10.压力传感器

// 为压力传感器注册监听器
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_PRESSURE), SensorManager.SENSOR_DELAY_NORMAL);

else if(sensorEvent.sensor.getType() == Sensor.TYPE_PRESSURE){
    float X = sensorEvent.values[0];
    mtextView13.setText("压强为"+ X );

11.计步传感器

有两个接口,一个Counter统计的是总步数,而DETECTOR为该计步是否有效,有效的话就置1

// 计步统计
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_NORMAL);
// 单次计步
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR), SensorManager.SENSOR_DELAY_NORMAL);

else if(sensorEvent.sensor.getType() == Sensor.TYPE_STEP_COUNTER){
    float X = sensorEvent.values[0];
    mtextView14.setText("COUNTER:"+ X );
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_STEP_DETECTOR){
    //检测到走动时值为1
    float X = sensorEvent.values[0];
    mtextView15.setText("DECTOR:"+ X );
}

四.微信摇一摇

1.在onStart() 方法中获取传感器的SensorManager

@Override
protected void onStart() {
    super.onStart();
    //获取 SensorManager 负责管理传感器
    mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
    if (mSensorManager != null) {
        //获取加速度传感器
        mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (mAccelerometerSensor != null) {
            mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_UI);
        }
    }
}

2.紧接着我们就要在Stop中注销传感器

@Override
protected void onStop() {
    // 务必要在pause中注销 mSensorManager
    // 否则会造成界面退出后摇一摇依旧生效的bug
    if (mSensorManager != null) {
        mSensorManager.unregisterListener(this);
    }
    super.onStop();
}

3.在step1中的注册监听事件方法中, 我们传入了当前Activity对象, 故让其实现回调接口, 得到以下方法

@Override
public void onSensorChanged(SensorEvent event) {
    int type = event.sensor.getType();

    if (type == Sensor.TYPE_ACCELEROMETER) {
        //获取三个方向值
        float[] values = event.values;
        float x = values[0];
        float y = values[1];
        float z = values[2];

        if ((Math.abs(x) > 17 || Math.abs(y) > 17 || Math
                .abs(z) > 17) && !isShake) {
            // TODO: 2016/10/19 实现摇动逻辑, 摇动后进行震动和声音
        }
    }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

4.振动和声音

震动权限:<uses-permission android:name="android.permission.VIBRATE"/>

MediaPlayer player = MediaPlayer.create(this, R.raw.weichat_audio);
player.start();

//获取Vibrator震动服务
mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
//方式1
mVibrator.vibrate(1000);//振动一秒
//方式2
//这里使用的是一个长整型数组,数组的a[0]表示静止的时间,a[1]代表的是震动的时间,然后数组的a[2]表示静止的时间,a[3]代表的是震动的时间……依次类推下去,然后这里的代码有一点小小的改变:
long[] patter = {1000, 1000, 2000, 50};
mVibrator.vibrate(patter, 0);
上一篇 下一篇

猜你喜欢

热点阅读