先来借用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
<activityandroid:name="BatteryInfo" android:label="@string/battery_info_label" android:taskAffinity="com.android.settings" android:parentActivityName="Settings"> <intent-filter> <actionandroid:name="android.intent.action.MAIN" /> <categoryandroid:name="android.intent.category.DEVELOPMENT_PREFERENCE" /> <categoryandroid:name="android.intent.category.VOICE_LAUNCH" /> </intent-filter> </activity>
(1) android:label
android:label="@string/battery_info_label",label表示标签,@表示引用,表示从string这个文件中引用battery_info_label这个键值的值,
\packages\apps\Settings\res\values\ strings.xml中对应的值如下:
<!-- The title of the activity to seebattery info. -->
<stringname="battery_info_label">Battery info</string>
(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,如下:
<stringname="battery_info_status_charging">Charging</string>
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