最近做了一个Demo,监听手机中传感器的数据,并将数据保存到手机文件中,发现数据会有丢失的现象。
经过多次测试,发现系统进入深度休眠了,之后service会停止,虽然增加了service自动启动的功能,但是还会导致数据中断一段时间。如果屏幕一直亮着会比较耗电,所以亮屏这种方法直接Pass掉。那么怎么保证service一直运行不会中断呢?
1,PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);通过Context.getSystemService()
.方法获取PowerManager实例。
2,然后通过PowerManager的newWakeLock((int flags, String tag)来生成WakeLock实例。int Flags指示要获取哪种WakeLock,不同的Lock对cpu 、屏幕、键盘灯有不同影响。
3,获取WakeLock实例后通过acquire()获取相应的锁,然后进行其他业务逻辑的操作,最后使用release()释放(释放是必须的)。
关于int flags
各种锁的类型对CPU 、屏幕、键盘的影响:
PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
权限获取
要进行电源的操作需要在AndroidManifest.xml中声明该应用有设置电源管理的权限。
1 <uses-permission android:name="android.permission.WAKE_LOCK" />
另外WakeLock的设置是 Activiy 级别的,不是针对整个Application应用的。
在Android中,申请WakeLock可以让进程持续执行即使手机进入睡眠模式,在Service的onCreate()方法中加入以下代码,申请WakeLock:
1 WakeLock m_wklk; 2 3 @Override 4 public void onCreate() { 5 super.onCreate(); 6 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 7 m_wklk = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DeviceSensorService.class.getName()); 8 m_wklk.acquire(); 9 //……………… 10 }
申请了WakeLock要记得释放,否则手机可能无法进入休眠状态。在onDestroy()方法中加入:
1 public void onDestroy() { 2 3 if (m_wklk != null) { 4 m_wklk.release(); 5 m_wklk = null; 6 } 7 };
完整的监听sensor数据代码如下:
1 /** 2 * 加速度传感,陀螺仪,压力传感器,数据收集 3 * 4 */ 5 6 import java.text.SimpleDateFormat; 7 8 import android.app.Service; 9 import android.content.Context; 10 import android.content.Intent; 11 import android.hardware.Sensor; 12 import android.hardware.SensorEvent; 13 import android.hardware.SensorEventListener; 14 import android.hardware.SensorManager; 15 import android.os.IBinder; 16 import android.os.PowerManager; 17 import android.os.PowerManager.WakeLock; 18 import android.util.Log; 19 20 public class DeviceSensorService extends Service { 21 private static final String TAG = "DeviceSensorService"; 22 Sensor sensorAcc, sensoGyros, sensoPress; 23 SensorManager sm; 24 WakeLock m_wklk; 25 26 @Override 27 public void onCreate() { 28 super.onCreate(); 29 if (sm == null) { 30 sm = (SensorManager) getApplicationContext().getSystemService( 31 Context.SENSOR_SERVICE); 32 } 33 /*List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_GYROSCOPE); 34 if (sensors.size() > 0){ 35 Sensor sensor = sensors.get(0); 36 sm.registerListener(this, 37 sensor, SensorManager.SENSOR_DELAY_NORMAL); 38 }*/ 39 40 // 加速度感应器 41 Sensor sensorAcc = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 42 // 陀螺仪 43 Sensor sensoGyros = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 44 // 压力 45 Sensor sensoPress = sm.getDefaultSensor(Sensor.TYPE_PRESSURE); 46 47 /* 48 * 最常用的一个方法 注册事件 49 * 参数1 :SensorEventListener监听器 50 * 参数2 :Sensor 一个服务可能有多个Sensor实现,此处调用getDefaultSensor获取默认的Sensor 51 * 参数3 :模式 可选数据变化的刷新频率,采样率 52 * SENSOR_DELAY_FASTEST,100次左右 53 * SENSOR_DELAY_GAME,50次左右 54 * SENSOR_DELAY_UI,20次左右 55 * SENSOR_DELAY_NORMAL,5次左右 56 */ 57 sm.registerListener(mySensorListener, sensorAcc, 58 SensorManager.SENSOR_DELAY_NORMAL); //以普通采样率注册监听器 59 sm.registerListener(mySensorListener, sensoGyros, 60 SensorManager.SENSOR_DELAY_NORMAL); 61 sm.registerListener(mySensorListener, sensoPress, 62 SensorManager.SENSOR_DELAY_NORMAL); 63 64 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 65 m_wklk = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DeviceSensorService.class.getName()); 66 m_wklk.acquire(); 67 68 } 69 70 @Override 71 public IBinder onBind(Intent intent) { 72 return null; 73 } 74 75 @Override 76 public int onStartCommand(Intent intent, int flags, int startId) { 77 Log.i(TAG, "zhangjieqiong onStartCommand"); 78 // return super.onStartCommand(intent, flags, startId); 79 return Service.START_STICKY; 80 } 81 82 public void onDestroy() { 83 if (sm != null) { 84 sm.unregisterListener(mySensorListener); 85 mySensorListener = null; 86 } 87 if (m_wklk != null) { 88 m_wklk.release(); 89 m_wklk = null; 90 } 91 }; 92 93 /* 94 * SensorEventListener 接口的实现,需要实现两个方法 95 * 方法1 onSensorChanged 当数据变化的时候被触发调用 96 * 方法2 onAccuracyChanged 当获得数据的精度发生变化的时候被调用,比如突然无法获得数据时 97 */ 98 private SensorEventListener mySensorListener = new SensorEventListener() { 99 100 public void onSensorChanged(SensorEvent sensorEvent) { 101 synchronized (this) { 102 int type = sensorEvent.sensor.getType(); 103 104 SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS "); 105 String date = sDateFormat.format(new java.util.Date()); 106 107 switch (type) { 108 case Sensor.TYPE_ACCELEROMETER://加速度 109 // acc_count++; 110 float X_lateral = sensorEvent.values[0]; 111 float Y_longitudinal = sensorEvent.values[1]; 112 float Z_vertical = sensorEvent.values[2]; 113 MyLog.i("Accelerometer.txt", "Accelerometer", date + "," 114 + X_lateral + "," + Y_longitudinal + "," + Z_vertical 115 + ";"); 116 117 Log.i("sensor", "Accelerometer:"+ date + ", " 118 + X_lateral + "," + Y_longitudinal + "," + Z_vertical 119 + ";"); 120 121 break; 122 case Sensor.TYPE_GYROSCOPE://陀螺仪 123 // gyro_count++; 124 float X_laterals = sensorEvent.values[0]; 125 float Y_longitudinals = sensorEvent.values[1]; 126 float Z_verticals = sensorEvent.values[2]; 127 MyLog.i("Gyproscope.txt", "Gyproscope", date + "," 128 + X_laterals + "," + Y_longitudinals + "," 129 + Z_verticals + ";"); 130 Log.i("sensor", "Gyproscope:"+ date + ", " 131 + X_laterals + "," + Y_longitudinals + "," 132 + Z_verticals + ";"); 133 break; 134 case Sensor.TYPE_PRESSURE://压力 135 // pres_count++; 136 float X_lateralss = sensorEvent.values[0]; 137 MyLog.i("Pressure.txt", "Pressure", date + "," + X_lateralss 138 + ";"); 139 Log.i("sensor", "Pressure:"+ date + "," + X_lateralss 140 + ";"); 141 break; 142 default: 143 break; 144 } 145 } 146 } 147 148 public void onAccuracyChanged(Sensor sensor, int accuracy) { 149 Log.i("sensor", "onAccuracyChanged-----sensor"+ sensor + ",acc:" + accuracy); 150 151 } 152 }; 153 }
关于保存数据到文件可以参考上一篇博客:http://www.cnblogs.com/zjqlogs/p/5488798.html
注:这样处理会比较耗电。
参考:http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966611.html
参考:http://blog.sina.com.cn/s/blog_474928c90100xpg9.html