Android学习小记----监听电量的变化(不能静态注册的广播)

  最近在做一个Demo,监听电量变化,持续记录电量的变化。

  一开始我是在Activity中注册广播,可以正常监听电量状态,但随着Activity生命周期变化,不能持续监听电量。就想到用service来持续监听,尝试了多次静态注册,发现竟然接收不到电量变化的广播。!!!!????

  后来上网搜索,发现有五个不能静态注册的广播,这里记录一下,免得下次再后知后觉的发现并惊讶于自己的笨拙。

 不能静态注册的广播:

  android.intent.action.SCREEN_ON

  android.intent.action.SCREEN_OFF

  android.intent.action.BATTERY_CHANGED

  android.intent.action.CONFIGURATION_CHANGED

  android.intent.action.TIME_TICK

原因(有以下几种说法,提供给大家参考):

  1.提高系统效率:这两个事件是android的基本事件,如果大多数程序监听,会大大的拖慢整个系统,所以android不鼓励我们在后台监听这两个事件。

  2.因为有序广播的优先级问题。以上这些广播中,静态注册时,系统的优先级大于应用,并且系统阻止了广播的向下传播。又因在Android 的广播机制中,动态注册的优先级是要高于静态注册优先级的。故用动态注册代替静态注册。

  3.系统安全问题。

解决方式(以android.intent.action.BATTERY_CHANGED为例):

  动态注册不能放到activity中,因为动态注册必须要在activity消亡的时候调用unregisterReceiver,会随着activity的解锁消失而不能再接收广播。一般的办法是在activity起来后马上start一个service,这个service里动态注册一个broadcastreceiver,service必须常驻在系统内,所以要接收开机消息android.intent.action.BOOT_COMPLETED。

 

持续监听电量变化实例:

1,在Broadcast中启动service代码,开机自动启动:

 private String boot_action ="android.intent.action.BOOT_COMPLETED";  
@Override
public void onReceive(Context context, Intent intent) { 
      if(boot_action.equals(action)){
         Log.i(TAG, "android.intent.action.BOOT_COMPLETED");
         Intent in0 = new Intent(context, BatteryService.class);
         context.startService(in0);
             
     }  
}

不要忘记在Manifest.xml中注册开机启动广播:

1 <receiver android:name="BootBroadcastReceiver" >
2             <intent-filter>
3                 <action android:name="android.intent.action.BOOT_COMPLETED" />
4             </intent-filter>
5 </receiver>

 

2,在service中动态注册广播,处理电量,service停止后自动启动

  1 import java.text.SimpleDateFormat;
  2 
  3 import android.app.Service;
  4 import android.content.BroadcastReceiver;
  5 import android.content.Context;
  6 import android.content.Intent;
  7 import android.content.IntentFilter;
  8 import android.os.BatteryManager;
  9 import android.os.IBinder;
 10 import android.util.Log;
 11 
 12 public class BatteryService extends Service {
 13 
 14     private static final String TAG = "BatteryReceiver"; 
 15     @Override
 16     public IBinder onBind(Intent intent) {
 17         return null;
 18     }
 19     
 20     @Override  
 21     public void onCreate() {  
 22         super.onCreate(); 
 23         Log.i(TAG, "onCreate--------------");
 24         IntentFilter batteryfilter = new IntentFilter();
 25         batteryfilter.addAction(Intent.ACTION_BATTERY_CHANGED);
 26         registerReceiver(batteryReceiver, batteryfilter);
 27     }
 28     
 29     @Override  
 30     public void onStart(Intent intent, int startId) { 
 31         super.onStart(intent, startId);  
 32     }
 33     
 34     @Override  
 35     public int onStartCommand(Intent intent, int flags, int startId) {
 36         Log.i(TAG, "onStartCommand--------------");
 37         return Service.START_STICKY; //
 38     }
 39     
 40     @Override  
 41     public void onDestroy() {  
 42         Log.i(TAG, "onDestroy--------------");
 43         super.onDestroy(); 
 44         this.unregisterReceiver(batteryReceiver); 
 45         
 46     }
 47     // 接收电池信息更新的广播  
 48      private BroadcastReceiver batteryReceiver = new BroadcastReceiver(){
 49         @Override
 50         public void onReceive(Context context, Intent intent) {
 51             Log.i(TAG, "BatteryReceiver--------------");
 52             String action = intent.getAction();
 53             Log.i(TAG, " 0 action:"+ action);
 54             Log.i(TAG, "ACTION_BATTERY_CHANGED");
 55             int status = intent.getIntExtra("status", 0);
 56             int health = intent.getIntExtra("health", 0);
 57             boolean present = intent.getBooleanExtra("present", false);
 58             int level = intent.getIntExtra("level", 0);
 59             int scale = intent.getIntExtra("scale", 0);
 60             int icon_small = intent.getIntExtra("icon-small", 0);
 61             int plugged = intent.getIntExtra("plugged", 0);
 62             int voltage = intent.getIntExtra("voltage", 0);
 63             int temperature = intent.getIntExtra("temperature", 0);
 64             String technology = intent.getStringExtra("technology");
 65 
 66             String statusString = "";
 67             switch (status) {
 68             case BatteryManager.BATTERY_STATUS_UNKNOWN:
 69                 statusString = "unknown";
 70                 break;
 71             case BatteryManager.BATTERY_STATUS_CHARGING:
 72                 statusString = "charging";
 73                 break;
 74             case BatteryManager.BATTERY_STATUS_DISCHARGING:
 75                 statusString = "discharging";
 76                 break;
 77             case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
 78                 statusString = "not charging";
 79                 break;
 80             case BatteryManager.BATTERY_STATUS_FULL:
 81                 statusString = "full";
 82                 break;
 83             }
 84             String acString = "";
 85 
 86             switch (plugged) {
 87             case BatteryManager.BATTERY_PLUGGED_AC:
 88                 acString = "plugged ac";
 89                 break;
 90             case BatteryManager.BATTERY_PLUGGED_USB:
 91                 acString = "plugged usb";
 92                 break;
 93             }
 94              
 95             SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS ");
 96               String date = sDateFormat.format(new java.util.Date()); 
 97              
 98             Log.i(TAG, "battery: date=" + date + ",status " + statusString 
 99                      + ",level=" + level +",scale=" + scale 
100                      + ",voltage=" + voltage +",acString=" + acString );
101             
102              MyLog.i("Battery.txt", "Battery",":date=" + date + ",status=" + statusString 
103                     + ",level=" + level +",scale=" + scale 
104                     + ",voltage=" + voltage );
105 
106         }
107      };
108 }

 

那么怎样才能保证service不被杀死?

Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,这里在onStartCommand方法的返回值做文章就可以了,这里用到的是Service.START_STICKY这个返回值:

网络上找到的解释:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

3,将电量数据保存到文件中(这里只提取了关键的方法)

 

 1 /**
 2      * 打开日志文件并写入日志
 3      * 
 4      * @return
 5      * **/
 6     private static void writeLogtoFile(String logTypename, String mylogtype,
 7             String tag, String text) {// 新建或打开日志文件
 8         Log.i("zjq", "mylog----------");
 9         File path = Environment.getExternalStorageDirectory();
10         Date nowtime = new Date();
11         String needWriteFiel = logfile.format(nowtime);
12         String needWriteMessage = text;
13         File file = new File(path, needWriteFiel + logTypename);
14         try {
15             FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖
16             BufferedWriter bufWriter = new BufferedWriter(filerWriter);
17             bufWriter.write(needWriteMessage);
18             bufWriter.newLine();
19             bufWriter.close();
20             filerWriter.close();
21         } catch (IOException e) {
22             e.printStackTrace();
23         }
24     }

 

posted @ 2016-05-13 11:33  JoanneZhang  阅读(13070)  评论(0编辑  收藏  举报