原理:
分析抬手亮屏的过程,首先是抬手的动作,抬手的过程会产生一个加速度,然后是抬手后设备静止的状态,如果用户当前是想显示屏幕那么设备肯定处于一个接近水平的状态。有这两个过程基本可以确定用户是想点亮屏幕的。这两个过程的判断仅仅使用到加速度传感器,无须大部分设备会同时使用到的陀螺仪、磁力传感器等,对节省设备电量也有一定的帮助。
1.判断抬手的动作。首先介绍一下Android设备的自然方向,如下图所示:
对于典型的Android智能设备,当它平放在桌面上并且上部指向正北方时的方向就是其自然方向。传感器管理器可以报告所有三个坐标轴方向上的传感器变化。通过传感器事件监听器的传感器事件参数的values属性传入的值依次表示横向、纵向和垂直方向的加速度。我们可以设置一个大于9.8(重力加速度)的阈值,比如14,当三个方向有任何一个的值大于该阈值时判断用户抬手了。阈值设置得越大,用户触发此判断的抬手动作也需要越大。记录此时的时间,精确到毫秒。
2.判断用户查看设备的动作。可以知道设备处于水平方向时x轴和y轴的加速度为0,z轴加速度为9.8。因为我们抬手看设备的时候无法保证设备处于绝对水平的状态,所以应当适当放宽条件,比如:9 < z && -2 < x < 2&& -2 < y < 2。当设备满足此条件时判断用户是想查看设备的。记录此时的时间,精确到毫秒。
3.抬手亮屏。测试表明,抬手和查看设备这两个动作之间的时间间隔不会大于500毫秒,所以最后一步便是计算1和2所记录时间的差值,如果差值在500以内可以判断用户此次是抬手查看设备的动作,此时唤醒屏幕,并将1中的时间清零。如不清零在0.5秒的时间里设备是无法被熄屏的,这会对用户造成一定的困扰。
源码:
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
public class WakeLockActivity extends Activity {
private SensorManager sensorManager;
private PowerManager pm;
private PowerManager.WakeLock mWakelock;
private long shakeTime;//抬手时间
private long showTime;//平放手机时间
private Sensor accelerometer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
pm = (PowerManager)getSystemService(POWER_SERVICE);
mWakelock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.SCREEN_DIM_WAKE_LOCK, "WakeLock");
}
@Override
protected void onResume() {
super.onResume();
if (accelerometer == null) {
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_UI);
}
}
//重力感应监听
private SensorEventListener sensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
float x = values[0]; // x轴方向的重力加速度,向右为正
float y = values[1]; // y轴方向的重力加速度,向前为正
float z = values[2]; // z轴方向的重力加速度,向上为正
int medumValue = 14;
//判断是否抬手
if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) {
shakeTime = System.currentTimeMillis();
}
//判断是否平放手机
if(9 < z && -2 < x && x < 2 && -2 < y && y < 2){
showTime = System.currentTimeMillis();
if(0 < showTime - shakeTime && showTime - shakeTime < 500){
shakeTime = 0;
mWakelock.acquire();
mWakelock.release();
}
}
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
sensorManager.unregisterListener(sensorEventListener);
}
}
这里对mWakelock.release()作一下说明,该方法并不是熄屏,而是释放亮屏的锁,也就是说如果没有释放的话设备会一直处于亮屏状态。
记得添加权限:
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>