Android系统提供了对传感器的支持,如果手机设备的硬件提供了这些传感器,Android应用可以通过传感器来获取设备的外界条件,包括手机设备的运行状态、当前摆放方向、外界的磁场、温度和压力等。Android系统提供了驱动程序去管理这些传感器硬件,当传感器感知到外部环境发生改变时,Android系统负责管理这些传感器数据。
使用传感器的步骤分为5步:
SensorManager提供的注册传感器的方法为registerListener(SensorEventListener listener, Sensor sensor, int rate),该方法的三个参数说明如下:
在onSensorChanged(SensorEvent event)方法中有一个参数event,通过event可以获取传感器的类型以及传感器的数据。
* <h4>{@link android.hardware.Sensor#TYPE_ACCELEROMETER
* Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2)
* <ul>
* <li> values[0]: Acceleration minus Gx on the x-axis </li>
* <li> values[1]: Acceleration minus Gy on the y-axis </li>
* <li> values[2]: Acceleration minus Gz on the z-axis </li>
* </ul>
* <p>
* A sensor of this type measures the acceleration applied to the device
* (<b>Ad</b>). Conceptually, it does so by measuring forces applied to the
* sensor itself (<b>Fs</b>) using the relation:
* </p>
* <b><center>Ad = - ∑Fs / mass</center></b>
* <p>
* In particular, the force of gravity is always influencing the measured
* acceleration:
* </p>
* <b><center>Ad = -g - ∑F / mass</center></b>
* <p>
* For this reason, when the device is sitting on a table (and obviously not
* accelerating), the accelerometer reads a magnitude of <b>g</b> = 9.81
* m/s^2
* </p>
* <p>
* Similarly, when the device is in free-fall and therefore dangerously
* accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a
* magnitude of 0 m/s^2.
* </p>
* <p>
* It should be apparent that in order to measure the real acceleration of
* the device, the contribution of the force of gravity must be eliminated.
* This can be achieved by applying a <i>high-pass</i> filter. Conversely, a
* <i>low-pass</i> filter can be used to isolate the force of gravity.
* </p>
* <pre class="prettyprint">
* public void onSensorChanged(SensorEvent event)
* {
* // alpha is calculated as t / (t + dT)
* // with t, the low-pass filter's time-constant
* // and dT, the event delivery rate
* final float alpha = 0.8;
* gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
* gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
* gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
* linear_acceleration[0] = event.values[0] - gravity[0];
* linear_acceleration[1] = event.values[1] - gravity[1];
* linear_acceleration[2] = event.values[2] - gravity[2];
* }
* </pre>
* <p>
* <u>Examples</u>:
* <ul>
* <li>When the device lies flat on a table and is pushed on its left side
* toward the right, the x acceleration value is positive.</li>
* <li>When the device lies flat on a table, the acceleration value is
* +9.81, which correspond to the acceleration of the device (0 m/s^2) minus
* the force of gravity (-9.81 m/s^2).</li>
* <li>When the device lies flat on a table and is pushed toward the sky
* with an acceleration of A m/s^2, the acceleration value is equal to
* A+9.81 which correspond to the acceleration of the device (+A m/s^2)
* minus the force of gravity (-9.81 m/s^2).</li>
* </ul>
从加速度传感器源代码中可以看出,values[0]表示x轴上的加速度,values[1]表示y轴上的加速度,values[2]表示z轴上的加速度。
因为并非所有手机都支持所有传感器,不用系统引入的传感器不同,所以在使用之前有必要判断一下,、从而提高性能。
判断是否有传感器有两种方法:
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (sensor != null){
//传感器存在
}else{
//传感器不存在
}
<use-feature
name = "android.hardware.sensor.orientation"
android:required = "true"/>
利用方向传感器,界面中的图片向手机旋转的反方向旋转。代码如下:
public class MainActivity extends AppCompatActivity implements SensorEventListener{
private ImageView mIvSensor;
private Sensor mSensor;
private SensorManager mSensorManager;
private float mDegress = 0f;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvSensor = (ImageView) findViewById(R.id.iv_sensor);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI); //rate suitable for the user interface
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){
float degree = - event.values[0];
RotateAnimation rotateAnimation = new RotateAnimation(mDegress, degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(100);
mIvSensor.startAnimation(rotateAnimation);
mDegress = degree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//TODO:当传感器精度发生变化时
}
}
演示效果:
orientation_sensor_demo.gif