Android学习小记-----监听并保存传感器数据,让service后台运行(保持CPU运转

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

时间: 2024-12-17 21:15:15

Android学习小记-----监听并保存传感器数据,让service后台运行(保持CPU运转的相关文章

quick-cocos2d-x android返回键监听并实现原生退出对话框

这两天终于闲了一下,就顺手又把quick捡起来又学了学,一直都觉得quick比cocos2dx那套lua绑定要方便许多,今天试了下android返回键的监听,还是挺好弄的,所以就有了这篇. 首先说明一下使用的quick版本--2.2.5. 直接上代码 function MainScene:addBackEvent() if device.platform == "android" then self.touchLayer = display.newLayer() self.touchL

Android短信监听(三)——利用Loader实现短信监听

MainActivity如下: package cc.c; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; import android.database.Curs

Android短信监听(二)——利用ContentObserver实现短信监听

MainActivity如下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.app.Activity; /** *

Android短信监听(一)——利用BroadcastReceiver实现短信监听

MainActivity如下: package cc.testsmsbroadcastreceiver; import cc.testsmsbroadcastreceiver.SMSBroadcastReceiver.MessageListener; import android.os.Bundle; import android.widget.TextView; import android.app.Activity; /** * Demo描述: * 利用BroadcastReceiver实现

android应用程序监听SMS Intent广播

当设备接收到一条新的SMS消息时,就会广播一个包含了android.provider.Telephony.SMS_RECEIVED动作的Intent. 对于应用程序监听SMS Intent广播,首先需要添加RECEIVE_SMS权限.通过在应用程序manifest中添加一个uses-permission,如下面的片段所示: <uses-permission android:name="android.permission.RECEIVE_SMS"/> AndroidMani

Android的Button监听

1.android简单按钮监听----单个监听 start = (Button)findViewById(R.id.btnStart); start.setOnClickListener(new OnClickListener(){            @Override            public void onClick(View v) {                //---do something            }            }); 2.View.OnC

Android使用ContentObserver监听数据库变化(转自:http://www.blogjava.net/zhaojianhua/archive/2011/10/27/362204.html)

android 使用contentobserver监听数据库内容变化 android 使用contentobserver监听数据库内容变化 在 android中经常会用到改变数据库内容后再去使用数据库更新的内容,很多人会重新去query一遍,但是这样的问题就是程序会特别占内存,而且有可能 会搂关cursor而导致程序内存未释放等等.其实android内部提供了一种ContentObserver的东西来监听数据库内容的变化.ContentObserver 的构造函数需要一个参数Hanlder,因为

【Android 进阶】Android Home 键监听

Android Home键监听 Android 普通键值可以直接在dispatchKeyEvent()中处理,但Home键,比较特殊,需要单独监听其广播,且必须为动态广播,其静态广播无效: 需求:Home键,设置 Kill 自己,但设置中有多个Activity,在每个Activiy 中年监听Home键广播不现实,必须把监听广播抽取出来在同一个类中实现,考虑到BaseActivity: public class BaseActivity extends Activity { private Hom

android的电话监听

android的电话监听 新建一个项目,结构图如下: PhoneService: package com.demo.tingdianhua; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.telecom.TelecomManager; import android.telephony.PhoneStateListener; import an