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     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM