前言
手机中内置的传感器是一种微型的物理设备,它能够探测、感受到外界的信号,并按一定规律转换成我们所需要的信息。我们使用的手机上通常会支持多种类型的传感器,比如:
- 1.光照传感器
- 2.加速度传感器
- 3.地磁传感器
- 4.压力传感器
- 5.温度传感器
- …
市场上很多应用都应用到了传感器,比如赛车游戏中,通过旋转设备类控制赛车的行驶方向,从而模拟手握方向盘的感觉。又比如微信的摇一摇,手机指南针等…
不过,虽然 Android 系统支持十余种传感器的类型,但是手机里的传感器设备却是有限的,基本上不会有哪部手机能够支持全部的传感器功能。接下来,我们着重介绍一些常用的传感器。
光照传感器
光照传感器在应用中还是很常见的,通过传感器来感应实际环境中的光照强度来对手机的亮度相应的调整,以此来保证不管是在强光下,还是在弱光下,手机屏幕均能够看得清。
用法
直接上代码:
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private SensorManager mSensorManager;
private TextView mLightLevelTV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLightLevelTV = (TextView) findViewById(R.id.light_level);
// sensorManager是所有传感器的管理器
mSensorManager = (SensorManager) getSystemService(
Context.SENSOR_SERVICE);
// 光照传感器
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
mSensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
private SensorEventListener listener = new SensorEventListener() {
/**
* 当传感器侦测到的数值发生变化时,调用此方法
*/
@Override
public void onSensorChanged(SensorEvent event) {
// event参数中包含一个values数组,所有的传感器信息都存放在这里
// values数组中第一个下标的值就是当前的光照强度
float value = event.values[0];
mLightLevelTV.setText("Current light level is " + value + " lx");
}
/**
* 当传感器进度发生变化时,调用此方法
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
// 注意:当你不使用传感器时,一定要调用unregisterListener(),将使用的资源释放掉
if (mSensorManager != null) {
mSensorManager.unregisterListener(listener);
}
}
}
效果图:
加速度传感器
它是一种用于描述物体运动速度改变快慢的物理量,以 m/s 2 为单位。而 Android 中的加速度传感器则是提供了一种机制,使得我们能够在应用程序中获取到手机当前的加速度信息,合理利用这些信息就可以开发出一些比较好玩的功能。
用法
我们来写一个微信摇一摇的demo。
实现思路:
只需检测手机在x,y,z轴上的加速度即可,若达到了预定值,我们即可认为用户摇动了手机,由于重力加速度的存在,这个之必定是大于9.8m/s2,下面的demo中我们设定为15m/s2.
代码:
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
private SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// sensorManager是所有传感器的管理器
mSensorManager = (SensorManager) getSystemService(
Context.SENSOR_SERVICE);
// 加速度传感器
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
// 加速度的临界值
private static final float THRESHOLD = 15;
private SensorEventListener listener = new SensorEventListener() {
/**
* 当传感器侦测到的数值发生变化时,调用此方法
*/
@Override
public void onSensorChanged(SensorEvent event) {
// event参数中包含一个values数组,所有的传感器信息都存放在这里
// values数组中会有三个值,分别代表手机在x轴,y轴和z轴上的加速度信息(参照下图)
// 注意:由于地形引力的存在,始终有一个重力加速度,大约为9.8m/m2
// 加速度可能回事负值,所以要取他们的绝对值
float xValue = Math.abs(event.values[0]);
float yValue = Math.abs(event.values[1]);
float zValue = Math.abs(event.values[2]);
if (xValue >= THRESHOLD || yValue >= THRESHOLD || zValue >= THRESHOLD) {
// 若有一条坐标上的加速度大于临界值,则认为是摇动了手机
Toast.makeText(MainActivity.this, "摇一摇", Toast.LENGTH_LONG).show();
}
}
/**
* 当传感器进度发生变化时,调用此方法
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
// 注意:当你不使用传感器时,一定要调用unregisterListener(),将使用的资源释放掉
if (mSensorManager != null) {
mSensorManager.unregisterListener(listener);
}
}
}
手机方向参照图:
方向传感器
方向传感器的使用场景要比其他的传感器更为广泛,它能够准确地判断出手机在各个方向的旋转角度,利用这些角度就可以编写出像指南针、地平仪等有用的工具。
接下来我们将用它来制作一个指南针demo:
实现原理:
检测手机绕z轴的旋转角度,对这个值进行处理即可。
代码:
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
public class MainActivity extends Activity {
private SensorManager mSensorManager;
private ImageView mCompassIV;
private float mLastRotateDegree;
/** 旋转指南针 */
public static final int ROTATE_COMPASS = 0;
public Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ROTATE_COMPASS:
float rotateDegree = (float) msg.obj;
if (Math.abs(rotateDegree - mLastRotateDegree) > 1) {
// 参数说明
// 第一个参数:起始角度
// 第二个参数:旋转的终止角度
// 后面四个,用于指定旋转的中心点
RotateAnimation animation = new RotateAnimation(
mLastRotateDegree,
rotateDegree,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
animation.setFillAfter(true);
mCompassIV.startAnimation(animation);
mLastRotateDegree = rotateDegree;
}
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCompassIV = (ImageView) findViewById(R.id.compass_img);
// sensorManager是所有传感器的管理器
mSensorManager = (SensorManager) getSystemService(
Context.SENSOR_SERVICE);
// 方向传感器
// 注意:根据Sensor.TYPE_ORIENTATION获取已经过时,不推荐使用
// 方向实际上是根据加速度传感器和地磁传感器共同计算得来的,这也是目前推荐的方式
// Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
Sensor accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor magneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// 由于方向传感器对于精度要求较高,我们这里使用 SENSOR_DELAY_GAME
mSensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
}
private SensorEventListener listener = new SensorEventListener() {
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
/**
* 当传感器侦测到的数值发生变化时,调用此方法
*/
@Override
public void onSensorChanged(SensorEvent event) {
// 判断传感器类型,另外,event的values数组分别记录着加速加速度传感器
// 和地磁传感器输出的值
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 加速度传感器
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];
// 将得到的accelerometerValues和magneticValues传入getRotationMatrix()中
// 即可得到一个包含旋转矩阵的R数组
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
// 得到R数组后,调用getOrientation()来计算手机的旋转数据,数据放在上面声明的values数组中
// values[0]记录着z轴旋转的弧度,values[1]记录着x轴旋转的弧度,values[2]记录着y轴旋转的弧度,
SensorManager.getOrientation(R, values);
// values[0]中放置的是弧度,我们需要调用Math.toDegrees(),将其转换成角度
Log.d("sensor", "values[0] is " + Math.toDegrees(values[0]));
// values[0]的取值范围是-180度到180度,其中正负180度表示正南方向,0度表示正北方向
// -90表示正西方向,90度表示正东方向
// 将计算出的旋转角度取反,用于旋转指南针背景图
float rotateDegree = -(float) Math.toDegrees(values[0]);
// 发送消息,更新视图
sendRotateCompassMessage(rotateDegree);
}
/**
* 当传感器进度发生变化时,调用此方法
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
/**
* 发送旋转指南针消息
* @param rotateDegree
*/
private void sendRotateCompassMessage(float rotateDegree) {
Message msg = new Message();
msg.what = ROTATE_COMPASS;
msg.obj = rotateDegree;
handler.sendMessage(msg);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注意:当你不使用传感器时,一定要调用unregisterListener(),将使用的资源释放掉
if (mSensorManager != null) {
mSensorManager.unregisterListener(listener);
}
}
}
后台打印的日志:
实际效果图: