原理:

分析抬手亮屏的过程,首先是抬手的动作,抬手的过程会产生一个加速度,然后是抬手后设备静止的状态,如果用户当前是想显示屏幕那么设备肯定处于一个接近水平的状态。有这两个过程基本可以确定用户是想点亮屏幕的。这两个过程的判断仅仅使用到加速度传感器,无须大部分设备会同时使用到的陀螺仪、磁力传感器等,对节省设备电量也有一定的帮助。

1.判断抬手的动作。首先介绍一下Android设备的自然方向,如下图所示:

android 唤醒 锁 安卓拿起手机唤醒屏幕_Math

对于典型的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>