1. 程式人生 > >Android加速度感測器 -- 擡手亮屏

Android加速度感測器 -- 擡手亮屏

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來喚醒螢幕來實現擡手亮屏