最近做了一个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 }