編輯:關於android開發
MSM8909+Android5.1.1之BSP開發---電池管理2---BatteryInfo.java
先來借用MTK對電池管理的框架圖
圖1
通過電話測試指令:*#*#4636#*#*可以彈出Testing界面
圖2
選擇Battery information,進入:
圖3
我們接入USB或是DC充電的時候,Power plug都顯示的時Unknown
說明底層就判斷為Unknown類型,此問題要查清楚
BatteryInfo對應的代碼為packages\apps\Settings\src\com\android\settings\BatteryInfo.java
1. \packages\apps\Settings\AndroidManifest.xml
(1) android:label
android:label="@string/battery_info_label",label表示標簽,@表示引用,表示從string這個文件中引用battery_info_label這個鍵值的值,
\packages\apps\Settings\res\values\ strings.xml中對應的值如下:
Battery info
(2) android:taskAffinity
android:taskAffinity="com.android.settings"表示BatteryInfo Activity希望進入com.android.settings這個task。
Activity的歸屬,也就是Activity應該在哪個Task中,Activity與Task的吸附關系。我們知道,一般情況下在同一個應用中,啟動的Activity都在同一個Task中,它們在該Task中度過自己的生命周期,這些Activity是從一而終的好榜樣。
那麼為什麼我們創建的Activity會進入這個Task中?它們會轉到其它的Task中嗎?如果轉到其它的Task中,它們會到什麼樣的Task中去?
解決這些問題的關鍵,在於每個Activity的taskAffinity屬性。
每個Activity都有taskAffinity屬性,這個屬性指出了它希望進入的Task。如果一個Activity沒有顯式的指明該Activity的taskAffinity,那麼它的這個屬性就等於Application指明的taskAffinity,如果Application也沒有指明,那麼該taskAffinity的值就等於包名。而Task也有自己的affinity屬性,它的值等於它的根Activity的taskAffinity的值。
2. BatteryInfo.java代碼分析
2.1 onCreate()
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.battery_info); // create the IntentFilter that will be used to listen // to battery status broadcasts mIntentFilter = new IntentFilter(); mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); }
(1) R.layout.battery_info
其值在packages\apps\Settings\res\layout\battery_info.xml定義
(2) 創建一個IntentFilter類的對象mIntentFilter
用於監聽電池狀態廣播。
(3) mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
為此IntentFilter增加一個ACTION_BATTERY_CHANGED的action,也就是說當其他Activity、或是Service等發送包含有ACTION_BATTERY_CHANGED的intent時,BatteryInfo就執行更新電池狀態的動作
2.2 onResume()
public void onResume() { super.onResume(); mStatus = (TextView)findViewById(R.id.status); mPower = (TextView)findViewById(R.id.power); mLevel = (TextView)findViewById(R.id.level); mScale = (TextView)findViewById(R.id.scale); mHealth = (TextView)findViewById(R.id.health); mTechnology = (TextView)findViewById(R.id.technology); mVoltage = (TextView)findViewById(R.id.voltage); mTemperature = (TextView)findViewById(R.id.temperature); mUptime = (TextView) findViewById(R.id.uptime); // Get awake time plugged in and on battery mBatteryStats =IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME)); mScreenStats = IPowerManager.Stub.asInterface(ServiceManager.getService(POWER_SERVICE)); mHandler.sendEmptyMessageDelayed(EVENT_TICK, 3000); registerReceiver(mIntentReceiver, mIntentFilter); }
在onResume()方法中通過registerReceiver(mIntentReceiver,mIntentFilter);注冊一個Receiver,最終在onReceive()方法中收到值為ACTION_BATTERY_CHANGED的action時,BatteryInfo這個Activity要更新電池狀態信息。
(1) 創建一個Handler
mHandler.sendEmptyMessageDelayed(EVENT_TICK,3000);使用到Handler,其創建如下:
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_TICK: updateBatteryStats(); sendEmptyMessageDelayed(EVENT_TICK, 1000); break; } } };
重寫handleMessage()用於處理消息EVENT_TICK,在收到此消息後,調用updateBatteryStats()更新電池狀態,並1000ms後發送EVENT_TICK消息。
(2) 注冊一個監聽器
/** *Listens for intent broadcasts */ private IntentFilter mIntentFilter; private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { int plugType =intent.getIntExtra("plugged", 0); mLevel.setText("" +intent.getIntExtra("level", 0)); mScale.setText("" +intent.getIntExtra("scale", 0)); mVoltage.setText("" +intent.getIntExtra("voltage", 0) + " " +getString(R.string.battery_info_voltage_units)); mTemperature.setText("" +tenthsToFixedString(intent.getIntExtra("temperature", 0)) +getString(R.string.battery_info_temperature_units)); mTechnology.setText("" +intent.getStringExtra("technology")); mStatus.setText(Utils.getBatteryStatus(getResources(), intent)); switch (plugType) { case 0: mPower.setText(getString(R.string.battery_info_power_unplugged)); break; case BatteryManager.BATTERY_PLUGGED_AC: mPower.setText(getString(R.string.battery_info_power_ac)); break; case BatteryManager.BATTERY_PLUGGED_USB: mPower.setText(getString(R.string.battery_info_power_usb)); break; caseBatteryManager.BATTERY_PLUGGED_WIRELESS: mPower.setText(getString(R.string.battery_info_power_wireless)); break; case(BatteryManager.BATTERY_PLUGGED_AC|BatteryManager.BATTERY_PLUGGED_USB): mPower.setText(getString(R.string.battery_info_power_ac_usb)); break; default: mPower.setText(getString(R.string.battery_info_power_unknown)); break; } int health =intent.getIntExtra("health", BatteryManager.BATTERY_HEALTH_UNKNOWN); String healthString; if (health ==BatteryManager.BATTERY_HEALTH_GOOD) { healthString =getString(R.string.battery_info_health_good); } else if (health ==BatteryManager.BATTERY_HEALTH_OVERHEAT) { healthString =getString(R.string.battery_info_health_overheat); } else if (health ==BatteryManager.BATTERY_HEALTH_DEAD) { healthString =getString(R.string.battery_info_health_dead); } else if (health ==BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE) { healthString =getString(R.string.battery_info_health_over_voltage); } else if (health ==BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE) { healthString =getString(R.string.battery_info_health_unspecified_failure); } else if (health ==BatteryManager.BATTERY_HEALTH_COLD) { healthString =getString(R.string.battery_info_health_cold); } else { healthString =getString(R.string.battery_info_health_unknown); } mHealth.setText(healthString); } } };
1) Battery status信息的更新
其中Battery status有些特別:
mStatus.setText(Utils.getBatteryStatus(getResources(),intent));
看packages\apps\Settings\src\com\android\settings\Utils.java\getBatteryStatus()的實現:
public static StringgetBatteryStatus(Resources res, Intent batteryChangedIntent) { final Intent intent = batteryChangedIntent; int plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN); String statusString; if (status == BatteryManager.BATTERY_STATUS_CHARGING) { int resId; if (plugType == BatteryManager.BATTERY_PLUGGED_AC) { resId =R.string.battery_info_status_charging_ac; } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) { resId =R.string.battery_info_status_charging_usb; } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) { resId =R.string.battery_info_status_charging_wireless; } else { resId =R.string.battery_info_status_charging; } statusString = res.getString(resId); } else if (status ==BatteryManager.BATTERY_STATUS_DISCHARGING) { statusString = res.getString(R.string.battery_info_status_discharging); } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { statusString = res.getString(R.string.battery_info_status_not_charging); } else if (status == BatteryManager.BATTERY_STATUS_FULL) { statusString = res.getString(R.string.battery_info_status_full); } else { statusString = res.getString(R.string.battery_info_status_unknown); } return statusString; }
從上面可知,plugType是unknown,所以從\packages\apps\Settings\res\values\strings.xml的battery_info_status_charging獲取到充電狀態是Charing,如下:
Charging
2) 如何獲取電池的信息
public void onReceive(Context context,Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { int plugType =intent.getIntExtra("plugged", 0);
這是上面其中一段代碼,收到廣播,且其中intent的action的值為 ACTION_BATTERY_CHANGED時就從intent中讀取plugged的值,這個intent是由BatteryService廣播出來的。
2.3 onPause()
@Override public void onPause() { super.onPause(); mHandler.removeMessages(EVENT_TICK); Slog.e(TAG, "BatteryInfo--->onPause()"); // we are no longer on the screen stop the observers unregisterReceiver(mIntentReceiver); }
比較簡單,就是刪除EVENT_TICK消息和注銷監聽器mIntentReceiver
Java 單例模式,Java模式前言:昨天公司計劃把項目中的部分功能做出SDK的形式,供其他公司的產品使用,所以不得不重新研究一下單例模式。 為什麼單例 1
Android熱補丁技術—dexposed原理簡析(手機淘寶采用方案) 本文由嵌入式企鵝圈原創團隊成員、阿裡資深工程師Hao分享。 上篇文章《Android無線開發的幾種
Kotlin中的“忍者”函數 —— 理解泛型的能力(KAD 12),kotlinkad作者:Antonio Leiva 時間:Feb 8, 2017 原文鏈接:https
Android java層音頻相關的分析與理解(三)調用相關 Android中會有多個應用需要支持音頻的播放。當同一時間內有多個應用需要輸出音頻的時候,到底是全部輸出