android系统提供以下传感器供应用层使用,具体如下:
// android.hardware.Sensor
TYPE_ACCELEROMETER 1 // 加速度传感器
TYPE_MAGNETIC_FIELD 2 // 磁力传感器
TYPE_ORIENTATION 3 // 方向传感器
TYPE_GYROSCOPE 4 // 陀螺仪传感器
TYPE_LIGHT 5 // 光线感应传感器
TYPE_PRESSURE 6 // 压力传感器
TYPE_TEMPERATURE 7 // 温度传感器,目前已被TYPE_AMBIENT_TEMPERATURE替代
TYPE_PROXIMITY 8 // 近距离传感器
SENSOR_TYPE_GRAVITY 9 // 重力传感器
TYPE_LINEAR_ACCELERATION 10 // 线性加速度
TYPE_ROTATION_VECTOR 11 // 旋转矢量
TYPE_RELATIVE_HUMIDITY 12 // 湿度传感器
TYPE_AMBIENT_TEMPERATURE 13 // 温度传感器
TYPE_MAGNETIC_FIELD_UNCALIBRATED 14 // 未校准磁力传感器
TYPE_GAME_ROTATION_VECTOR 15
TYPE_GYROSCOPE_UNCALIBRATED 16
... ...
加速度传感器又称之为G-sensor,返回X、Y、Z三轴的加速度值, 该数值包含地心引力的影响,单位为m/s^2(米每二次方秒)
将手机平放在桌面,x轴默认为0,y轴默认0,z轴默认9.81
将手机朝下放在桌面,z轴为-9.81
将手机向左倾斜,x轴为正值
将手机向右倾斜,x轴为负值
将手机向上倾斜,y轴为正值
将手机向下倾斜,y轴为负值
分析抬手动作发现,抬手亮屏需要满足两个条件:
1.手机处于拿起移动状态
2.手机面向人眼处于倾斜状态
并且触发这两个条件的时间间隔约200ms以内
代码很简单,以下是全部代码
public class AwakeActivity extends Activity {
private static final String TAG = "ansen";
private SensorManager mSensorManager;
private PowerManager mPowerManager;
private Sensor mGravitySensor;
private PowerManager.WakeLock mWakelock;
private long shakeTime; // 手机触发拿起动作时间
private long showTime;
private float oldY = 0;
private float subY = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mWakelock = mPowerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "smartAwake");
mSensorManager.registerListener(mSensorEventListener, mGravitySensor, SensorManager.SENSOR_DELAY_NORMAL);
// mWakelock.acquire();
}
// 加速度传感器监听
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
smartAwake(event);
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
};
// 抬手亮屏逻辑
private void smartAwake(SensorEvent event) {
float[] values = event.values;
float x = values[0];
float y = values[1];
float z = values[2];
Log.i(TAG, "smartAwake x= " + x + " y= " + y + " z=" + z);
subY = y - oldY;
if (Math.abs(x) < 3 && y > 0 && z < 9) {
if(subY > 1){
shakeTime = System.currentTimeMillis();
Log.i(TAG, "1");
}
oldY = y;
}
if (Math.abs(x) < 3 && y > 4 && y < 9 && z > 2 && z < 9) {
showTime = System.currentTimeMillis();
Log.i(TAG, "2");
if (showTime - shakeTime >= 0 && showTime - shakeTime < 200) {
mWakelock.acquire();
mWakelock.release();
// mPowerManager.wakeUp(SystemClock.uptimeMillis(), "smartAwake");
Log.i(TAG, "smartAwake Awake");
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mSensorManager.unregisterListener(mSensorEventListener);
}
}
手机水平放置桌面,三轴值约为:X=0,Y=0,Z=9.8,判断手机是否处于水平状态触发的拿起动作代码为:
(Math.abs(x) < 3 && y > 0 && z < 9)
判断手机处于面向人眼倾斜状态代码如下:
(Math.abs(x) < 3 && y > 4 && y < 9 && z > 2 && z < 9)
其中Math.abs(x) < 3 代表手机X轴处于接近水平状态,Y轴的取值为手机向上倾斜的角度,Z轴同理;这里的(subY > 1)是避免触发1和2两个条件时 手机处于静止状态也能点亮屏幕
屏幕唤醒的代码为:
mPowerManager.wakeUp(SystemClock.uptimeMillis(), "smartAwake");
由于是@hide api,普通应用无法直接调用,因此这里通过mWakelock.acquire(),获取唤醒锁 同样在灭屏情况下能点亮屏幕.
最后记得添加权限:
<uses-permission android:name="android.permission.WAKE_LOCK">uses-permission>
建议手机插上USB的情况下测试 断开USB几分钟后加速度传感器可能会停止工作; 建议在系统环境下 在Service中执行,并且程序注册传感器监听时获取wakelock,再通过PowerManager的wakeUp来唤醒屏幕来实现抬手亮屏