常用传感器介绍与用法
Android平台支持三个大类的传感器
- Motion sensors(运动传感器)
这些传感器测量加速力,并沿三个轴的旋转力。此类别包括加速度计,重力感应器, 陀螺仪和旋转矢量传感器。
- Environmental sensors (环境传感器)
这些传感器测量各种环境参数,例如环境空气温度和压力,照明和湿度。此类别包括气压计,光度计,和温度计。
- Position sensors (位置传感器)
这些传感器测量设备的物理位置。这个类别包括方向传感器和磁力计。
传感器实现流程
第一步:得到SensorManager
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
第二步:注册传感器
Sensor sensor = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (null != sensor)
mSensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_NORMAL);
说下registerListener的三个参数。
第一个参数
传感器数据变化的监听器
我们需要去实现SensorEventListener接口,他里面有两个回调方法,
@Override
public void onSensorChanged(SensorEvent event) {
//当传感器的数值发生变化时调用
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//传感器的精度发生变化时调用
}
第二个参数
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
1
第三个参数
传感器数据更新数据的速度
有以下四个值可选,他们的速度是递增的
SENSOR_DELAY_UI
SENSOR_DELAY_NORMAL
SENSOR_DELAY_GAME
SENSOR_DELAY_FASTEST
传感器的注销
//注销所有传感器对象
public voidunregisterListener(SensorEventListener listener)
//注销指定的传感器对象
public voidunregisterListener(SensorEventListener listener, Sensor sensor)
先给个简单的实践监听亮度
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mLight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
if (null != mLight)
mSensorManager.registerListener(this, mLight,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
Log.e("传感器的精度",accuracy+"");
}
@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];
Log.e("====",lux+"");
Toast.makeText(MainActivity.this,"=="+lux,Toast.LENGTH_SHORT).show();
// 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);
}
}
Android传感器类型表
加速度传感器:TYPE_ACCELEROMETER
以m/s2测量它设备所有三个物理轴线方向(x,y,和z)加速度。
周围温度传感器:TYPE_AMBIENT_TEMPERATURE
检测周围空气温度。
重力传感器:TYPE_GRAVITY
测量重力
陀螺仪传感器:TYPE_GYROSCOPE
以rad/s测量设备三个物理轴线方向(x,y,和z)。旋转速度。
光照传感器:TYPE_LIGHT
以lx测量周围的光线级别。
线性加速度传感器:TYPE_LINEAR_ACCELERATION
检测沿着一个轴向的加速度。
磁力传感器:TYPE_MAGNETIC_FIELD
测量周围的三个物理轴线方向的磁场。
方向传感器: TYPE_ORIENTATION
测量设备所有三个物理轴线方向(x,y和x)的旋转角度。
压力传感器:TYPE_PRESSURE
测量周围空气气压
接近传感器:TYPE_PROXIMITY
检测物体与手机的距离
相对湿度传感器:TYPE_RELATIVE_HUMIDITY
检测周围空气相对湿度
旋转矢量传感器:TYPE_ROTATION_VECTOR
用于检测运动和检测旋转。
温度传感器: TYPE_TEMPERATURE
检测设备的温度
处理不同的传感器配置
Android没有为设备指定一个标准的传感器配置,这意味着设备厂商可以将任何它们想要的传感器配置安装到他们的的Android设备。造成一个结果,设备包含了在大范围配置的各种传感器。例如,Motorola Xoom有一个压力传感器,但是Samsung Nexus S没有。同样,Xoom和Nexus S有陀螺仪,但是HTC Nexus One没有。如果你的应用程序依赖于一个指定类型的传感器看,你必须确保这个传感器在设备上存在,以至于你的应用程序能成功运行。你有两个选择来确保一个给定的传感器在设备上存在:
- 在运行时检测传感器,并酌情启动或禁用应用程序的功能。
使用Google Play过滤器来规定制定传感器配置的设备。
在运行时检测传感器
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
// Success! There's a pressure sensor.
}
else {
// Failure! No pressure sensor.
}
使用Google Play过滤器来指定特定的传感器配置
如果你在Google Play中发布你的应用程序,你能在你的清单文件中使用元素来过滤没有你的应用程序相应的传感器配置的设备。元素有多个硬件描述符,让你基于是否存在指定的传感器来过滤应用程序。你能列举的传感器包括:加速度,气压,罗盘(磁场),陀螺仪,光线,和趋近。下面是一个示例清单实例,来过滤没有加速度传感器的应用程序。
<uses-feature android:name="android.hardware.sensor.accelerometer"
android:required="true" />
下面算是抄袭的例子吧就是一个指南针的实现
其实获取方向本应该很简单的事情,在文章一中看到 有个TYPE_ORIENTATION 关键字,说明可以直接获取设备的移动方向,但是最新版的SDK加上了这么一句话“TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. ”也就是说,这种方式已经被取消,要开发者使用 SensorManager.getOrientation()来获取原来的数据。
所以今天的主角是这两方法
//获取旋转矩阵
SensorManager.getRotationMatrix(R, null, accelerometerValues,
magneticValues);
//获取方向
SensorManager.getOrientation(R, values);
先说下getOrientation
通常我们并不需要获取这个函数的返回值,这个方法会根据参数R[]的数据填充values[]而后者就是我们想要的。
R[] 是一个旋转矩阵,用来保存磁场和加速度的数据,大家可以理解未加工的方向数据吧
R通过下面的getRotationMatrix方法获取,这个方法也是用来填充R[]
getRotationMatrix的参数吧
第一个就是我们需要填充的R数组,大小是9
第二个是是一个转换矩阵,将磁场数据转换进实际的重力坐标中 一般默认情况下可以设置为null
第三个是一个大小为3的数组,表示从加速度感应器获取来的数据 在onSensorChanged中
第四个是一个大小为3的数组,表示从磁场感应器获取来的数据 在onSensorChanged中
android给我们提供的方向数据是一个float型的数组,包含三个方向的值 如图
当你的手机水平放置时,被默认为静置状态,即XY角度均为0
values[0] 表示Z轴的角度:方向角,我们平时判断的东西南北就是看这个数据的。
values[1] 表示X轴的角度:俯仰角 即由静止状态开始,前后翻转
values[2] 表示Y轴的角度:翻转角 即由静止状态开始,左右翻转
下面是封装好的
package com.example.admin.chuanganqi;
//values[0]->Z轴、values[1]->X轴、values[2]->Y轴
//使用前请进行转换,因为获取到的值是弧度,示例如下
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
/**
* Created by admin on 2017/3/17.
*/
public class DirectionSensorUtils implements SensorEventListener {
private SensorManager sensorManager;
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
float lastRotateDegree;
private ImageView compassImg;//指南针背景图
public DirectionSensorUtils(Context context , ImageView compassImg) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
this.compassImg = compassImg;
}
//注册传感器
public void registerSensor(){
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_ACCELEROMETER);
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, accelerometerSensor,
SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, magneticSensor,
SensorManager.SENSOR_DELAY_GAME);
}
//解除传感器注册
public void unregisterSensor(){
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// 判断当前是加速度传感器还是地磁传感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 通过clone()获取不同的values引用
accelerometerValues = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticValues = event.values.clone();
}
//获取地磁与加速度传感器组合的旋转矩阵
float[] R = new float[9];
float[] values = new float[3];
//获取旋转矩阵
SensorManager.getRotationMatrix(R, null, accelerometerValues,
magneticValues);
//获取方向
SensorManager.getOrientation(R, values);
// Math.toDegrees(values[0]);
// Math.toDegrees(values[1]);
// Math.toDegrees(values[2]);
String TAG="方向:";
if(values[0] >= -5 && values[0] < 5){
Log.i(TAG, "正北");
}
else if(values[0] >= 5 && values[0] < 85){
Log.i(TAG, "东北");
}
else if(values[0] >= 85 && values[0] <=95){
Log.i(TAG, "正东");
}
else if(values[0] >= 95 && values[0] <175){
Log.i(TAG, "东南");
}
else if((values[0] >= 175 && values[0] <= 180) || (values[0]) >= -180 && values[0] < -175){
Log.i(TAG, "正南");
}
else if(values[0] >= -175 && values[0] <-95){
Log.i(TAG, "西南");
}
else if(values[0] >= -95 && values[0] < -85){
Log.i(TAG, "正西");
}
else if(values[0] >= -85 && values[0] <-5){
Log.i(TAG, "西北");
}
handleEvent(values);
}
public void handleEvent(float[] values){
// 这里实现了一个指南针 这里得先转换下角度
float rotateDegree = -(float) Math.toDegrees(values[0]);
if (Math.abs(rotateDegree - lastRotateDegree) > 1) {
RotateAnimation animation = new RotateAnimation
(lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.
RELATIVE_TO_SELF, 0.5f);
animation.setFillAfter(true);
compassImg.startAnimation(animation);
lastRotateDegree = rotateDegree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}