由於寫論文需要,需要用手機加速度采集數據,關於android加速度傳感器的介紹網上一抓一大把,但大多都是大同小異,跟官網文檔差不多。自己寫了個取加速度傳感器的APK,發現數據有點不對勁,原理屏幕一關后,系統就自動把各種傳感器給停掉了,網上找了很久,發現一些可用的資源。
1、查看手機是否支持鎖屏后繼續運行傳感器
有些手機可以支持后台取傳感器數據,有些手機不行,這與硬件廠商具體實現有關,像GPS這些傳感器都是很耗電的,廠商也是出於電源管理的考慮,這里是一個不完全列表,總結哪些軟件支持屏幕關閉后依然運行傳感器。這里更有一款APK(Accelerometer Frequency)專門查看你的手機是否支持。
如果你的手機不支持,那還是不要折騰了,換了設備試試。
2、實現方法
我主要參考了
1)http://blog.kozaxinan.com/2012/08/using-accelerometer-when-screen-off_16.html
星期天我按他們的方法實現了一下,主要思想就是申請鎖屏后CPU不休眠:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); wl.acquire(); .. wl.release();
我把service寫成activity的一個內部類,而我把申請電源管理的命令放在了service的Oncreate()方法里,之前一直納悶,明明我的手機檢測支持的,鎖屏后還是沒有取數據,而且連接USB時,鎖屏后繼續取加速度傳感器數據,而拔掉USB后就停了,到處找原因,后來才發現service的OnCreate()方法沒執行,坑了我。
丑又丑點,我把電源管理申請放在了Activity的onCreate()方法中,結果可行了,把代碼放上來。
1 public class AccleratePersist extends Activity { 2 private static final String TAG = "AccleratePersist"; 3 private static final int DELAY = SensorManager.SENSOR_DELAY_NORMAL; 4 private static boolean STOP = true;// 開始暫停按鈕 5 6 private SensorManager mSensorManager; 7 private WakeLock mWakeLock; 8 private TextView accView;// 顯示加速度值 9 private StringBuilder builder = new StringBuilder(); 10 private long lastTimestamp = 0; 11 12 private PersistService mySerivece; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 accView = (TextView) this.findViewById(R.id.accValue); 19 final Button stopButton = (Button) this.findViewById(R.id.stopButton);// 停止測量按鈕 20 final Button clearButton = (Button) this.findViewById(R.id.clear); // 清除數據 21 22 View.OnClickListener onClickListener = new View.OnClickListener() { 23 24 @Override 25 public void onClick(View view) { 26 if (view == stopButton) { 27 STOP = !STOP; 28 setMeasure(); 29 } else if (view == clearButton) { 30 builder = new StringBuilder(); 31 accView.setText(""); 32 } 33 } 34 35 @SuppressLint("Wakelock") 36 private void setMeasure() { 37 if (STOP) {// 停止鍵按下后,取消監聽,是否電源 38 stopButton.setText("繼續"); 39 mSensorManager.unregisterListener(mySerivece); 40 mWakeLock.release(); 41 } else { 42 stopButton.setText("停止"); 43 mWakeLock.acquire();// 屏幕熄后,CPU繼續運行 44 mSensorManager 45 .registerListener( 46 mySerivece, 47 mSensorManager 48 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 49 DELAY); 50 } 51 } 52 53 }; 54 clearButton.setOnClickListener(onClickListener); 55 stopButton.setOnClickListener(onClickListener); 56 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 57 mySerivece = new PersistService(); 58 PowerManager manager = (PowerManager) getSystemService(Context.POWER_SERVICE); 59 mWakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);// CPU保存運行 60 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);// 屏幕熄掉后依然運行 61 filter.addAction(Intent.ACTION_SCREEN_OFF); 62 registerReceiver(mySerivece.mReceiver, filter); 63 } 64 65 class PersistService extends Service implements SensorEventListener { 66 67 private float[] accValue = new float[3]; 68 69 public BroadcastReceiver mReceiver = new BroadcastReceiver() { 70 @Override 71 public void onReceive(Context context, Intent intent) { 72 73 if (!STOP 74 && !intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 75 return; 76 } 77 if (mSensorManager != null) {//取消監聽后重寫監聽,以保持后台運行 78 mSensorManager.unregisterListener(PersistService.this); 79 mSensorManager 80 .registerListener( 81 PersistService.this, 82 mSensorManager 83 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 84 SensorManager.SENSOR_DELAY_NORMAL); 85 } 86 87 } 88 89 }; 90 91 public void onAccuracyChanged(Sensor sensor, int accuracy) { 92 Log.i(TAG, "PersistService.onAccuracyChanged()."); 93 } 94 95 public void onSensorChanged(SensorEvent sensorEvent) { 96 if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 97 Log.i(TAG, "PersistService.TYPE_ACCELEROMETER."); 98 accValue = sensorEvent.values; 99 for (int i = 0; i < 3; i++) { 100 builder.append((int) accValue[i]); 101 builder.append(","); 102 } 103 builder.append((sensorEvent.timestamp - lastTimestamp) / 1000000);// 采樣時間差 104 builder.append("\n"); 105 accView.setText(builder.toString()); 106 lastTimestamp = sensorEvent.timestamp; 107 } 108 109 } 110 @Override 111 public IBinder onBind(Intent intent) { 112 // TODO Auto-generated method stub 113 return null; 114 } 115 116 } 117 }
記得加一個權限: <uses-permission android:name="android.permission.WAKE_LOCK" />
有問題歡迎交流。