虽然 Android系统支持十余种传感器的类型,但是手机里的传感器设备却是有限的,基本上不会有哪部手机能够支持全部的传感器功能.
先来看一下几种常用的传感器:
光照传感器
光照传感器还是会比较常用到的,系统就有个自动调整屏幕亮度的功能。它会检测手机周围环境的光照强度,然后对手机屏幕的亮度进行相应地调整,以此保证不管是在强光还是弱光下,手机屏幕都能够看得清
来看下是如何使用的:
public class SensorActivity extends Activity {
/**
* 用于显示光照强度
*/
private TextView sensor;
/**
* SensorManager是系统所有传感器管理器
*/
private SensorManager sensormanager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
sensor = (TextView) findViewById(R.id.texts);
// 先通过getSystemService获取SensorManager的实例
sensormanager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 通过getDefaultSensor得到传感器的类型返回一个sensor的实例,此时的传感器sensor就代表光照传感器
Sensor sensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);
// 通过registerListener方法注册
/**
* 第一个参数就是SensorEventListener的实例 第二个参数就是Sensor的实例,第三个参数表示传感器输出信息的更新速率
* 共有SENSOR_DELAY_UI、 SENSOR_DELAY_NORMAL、 SENSOR_DELAY_GAME 和
* SENSOR_DELAY_FASTEST 这四种值可选 这个更新速率是依次递增的
*/
sensormanager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* 实现SensorEventListener接口实现对传感器输出的信号进行监听
*/
private SensorEventListener listener = new SensorEventListener() {
/**
* 当传感器数值发生变化的时候会调用此方法
*/
@Override
public void onSensorChanged(SensorEvent event) {
// values数组当中的下标值就是当前光照强度
// 所有传感器的输出信息都是方法event.values[]这个数组当中的
float evens = event.values[0];
sensor.setText("当前光照强度" + evens);
Log.i("运行到了吗", "" + evens);
}
/**
* 当传感器的精度发生变化的时候就调用这个方法
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (sensormanager != null) {
sensormanager.unregisterListener(listener);//释放资源
}
}
}
运行成功之后可以看到打印出来的信息:
有少部分手机没有光照传感器的就没有办法获取到这个值了。
加速度传感器
Android中的加速度传感器则是提供了一种机制,使得我们能够在应用程序中获取到手机当前的加速度信息, 合理利用这些信息就可以开发出一些比较好玩的功能。现在就实现一下像微信摇一摇那种功能.
每种传感器的用法都差不多,加速度传感器输出的信息同样也是存放在 SensorEvent的 values 数组中的,只不过此时的 values数组中会有三个值, 分别代表手机在 X轴、 Y轴和 Z 轴方向上的加速度信息。
X轴、Y轴、Z轴在空间坐标系上的含义如图 :
当手机竖立起来的时候这个加速度是作用在 Y轴上的,当手机横立起来的时候,这个加速度是作用在 X轴上的。当手机平放的时候,这个加速度是作用在 Z 轴上的。由于重力加速度的存在,即使手机在静止的情况下,某一个轴上的加速度也有可能达到9.8m/s2.
public class ShakeSensorActivity extends Activity{
private SensorManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
manager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);
//获取到加速度传感器
Sensor sensor=manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
manager.registerListener(listener, sensor,SensorManager.SENSOR_DELAY_NORMAL);
}
private SensorEventListener listener=new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
//加速度可能会是负值所以要取它们的绝对值
float x=Math.abs(event.values[0]);
float y=Math.abs(event.values[1]);
float z=Math.abs(event.values[2]);
//因为即使手机在静止的情况下,某一个轴上的加速度也有可能达到9.8m/s2所以这里要写一个比9.8大的比较合适的值来判断
if(x>30||y>30||z>30){
Toast.makeText(ShakeSensorActivity.this, "摇一摇", Toast.LENGTH_SHORT).show();
Log.i("ShakeSensorActivity","摇一摇");
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
protected void onDestroy() {
if(manager!=null){
manager.unregisterListener(listener);
}
};
}
运行成功后可以看到logcat输出信息:
方向传感器
获取方向传感器的实例:
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
但是Android已经废弃了 Sensor.TYPE_ORIENTATION 这种传感器类型.Android获取手机旋转的方向和角度是通过加速度传感器和地磁传感器共同计算得出的,这也是 Android目前推荐使用的方式。
制作简易指南针:
public class MainActivity extends Activity {
private SensorManager sensorManager;
private ImageView compassImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setViews();
//传感器管理器
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//加速度传感器
Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//地磁传感器
Sensor magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(sensorEventListener, magnetic, SensorManager.SENSOR_DELAY_GAME);
}
private void setViews() {
compassImg = (ImageView) findViewById(R.id.compass_img);
}
@Override
protected void onDestroy() {
super.onDestroy();
if(sensorManager != null){
sensorManager.unregisterListener(sensorEventListener);
}
}
//传感器变化监听器
private SensorEventListener sensorEventListener = new SensorEventListener() {
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
private float lastRotateDegree;
@Override
public void onSensorChanged(SensorEvent event) {
//判断当前是地磁还是加速度传感器
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];
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
SensorManager.getOrientation(R, values);
//Log.i("TAG", "values[0] is "+ Math.toDegrees(values[0]));
//将计算出的旋转角度取反,用于旋转指南针的背景图
float rotateDegree = -(float)Math.toDegrees(values[0]);
if(Math.abs(rotateDegree - lastRotateDegree) > 1){
//旋转补间动画
RotateAnimation rotateAnimation = new RotateAnimation(lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setFillAfter(true);
compassImg.startAnimation(rotateAnimation);
lastRotateDegree = rotateDegree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
}