电池图标显示

电池图标是SystemUI显示中不可缺少的一部分,它显示在SystemUI的电池和信号组合区域。

从布局来看,电池的显示属于status_bar.xml,包含了system_icons.xml布局

<includelayout="@layout/system_icons"/>

从这里可以看出,电池图标和信号图标属于同一个区域,所以这一块一般是两个布局,单卡和双卡,我们可以根据对应的机型选择msim_system_icons.xml或者system_icons.xml

电池图标的部分:

<com.android.systemui.BatteryMeterViewandroid:id="@+id/battery"

android:layout_height="14.5dp"

android:layout_width="9.5dp"

android:layout_marginBottom="@dimen/battery_margin_bottom"

android:visibility="gone"/>

电池电量百分比的部分:

<com.android.systemui.BatteryLevelTextViewandroid:id="@+id/battery_level_text"

android:layout_height="match_parent"

android:layout_width="wrap_content"

android:gravity="center"

android:layout_gravity="center_vertical"

android:textColor="#ffffff"

android:textSize="@dimen/battery_level_text_size"

android:layout_marginStart="7dp"/>

电池图标具体的实现显示和更新分别在两个自定义View中实现:BatteryMeterView和BatteryLevelTextView

在原生的实现中: BatteryMeterView这个类来监听电池状态的变化的,是一个被BatteryController类所管理的ImageView。 BatteryController通过监听android.intent.action.BATTERY_CHANGED广播以从 BetteryService中获取电量信息,并根据电量信息画一个电池图标在画布上。原生的方法不需要去替换图片。

但有时候我们有需求去用图片来显示更新电池图标,最常见的比如有一套五格信号图标和充电图标,替换android原生的画出来的电池图标,我们可以将BatteryMeterView设置未GONE,写一个自定义的ImageView如下:

<com.android.systemui.BatteryIconViewandroid:id="@+id/battery_icons"

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:layout_marginBottom="@dimen/battery_margin_bottom"

android:scaleType="fitCenter"/>

自定义View,我们需要一个广播接收者来监听Intent.ACTION_BATTERY_CHANGED,用来获取电池的状态

private classBatteryStatuteBroadcastReceiver extendsBroadcastReceiver {

public static final int UNKNOWN_LEVEL = -1;

int level = UNKNOWN_LEVEL;

int plugType;

booleanplugged;

int health;

int status;

String technology;

int voltage;

int temperature;

@Override

public void onReceive(Context context, Intentintent) {

final String action = intent.getAction();

if (action.equals(Intent.ACTION_BATTERY_CHANGED)){

level = (int)(100f

* intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0)

/ intent.getIntExtra(BatteryManager.EXTRA_SCALE,100));

plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,0);

plugged = plugType != 0;

health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,

BatteryManager.BATTERY_HEALTH_UNKNOWN);

status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,

BatteryManager.BATTERY_STATUS_UNKNOWN);

technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);

voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE,0);

temperature =intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);

updateIcons();

postInvalidate();

}

}

}

这个Receiver只能动态进行注册,在窗口加载时注册,在窗口销毁时解注册

@Override

public voidonAttachedToWindow() {

super.onAttachedToWindow();

IntentFilterfilter = newIntentFilter();

filter.addAction(Intent.ACTION_BATTERY_CHANGED);

finalIntent sticky =getContext().registerReceiver(mReceiver,filter);

if (sticky !=null) {

mReceiver.onReceive(getContext(),sticky);

}

mBatteryController.addStateChangedCallback(this);

}

@Override

public voidonDetachedFromWindow() {

super.onDetachedFromWindow();

getContext().unregisterReceiver(mReceiver);

mBatteryController.removeStateChangedCallback(this);

}

我们在接收到电池变化的广播时,进行updateIcon,选择需要的图标组,这里我们可以用if else语句,也可以用level-list进行选择,使用if else语句繁琐且效率底下,比如五格电池显示,在不同的电量区间显示不同的电池图标。一个比较好的方式是使用level-list

步骤

1.        自定义一个ImageView,在ondraw中实现图片资源的替换

2.        在构造函数中对ImageView进行设置资源

setImageResource(R.drawable.battery_level_list);

3.        battery_level_list是一个level-list,定义如下

<?xmlversion="1.0"encoding="utf-8"?>

<level-listxmlns:android="http://schemas.android.com/apk/res/android">

<itemandroid:maxLevel="15"android:drawable="@drawable/stat_sys_battery_1"/>

<itemandroid:maxLevel="49"android:drawable="@drawable/stat_sys_battery_2"/>

<itemandroid:maxLevel="75"android:drawable="@drawable/stat_sys_battery_3"/>

<itemandroid:maxLevel="95"android:drawable="@drawable/stat_sys_battery_4"/>

<itemandroid:maxLevel="100"android:drawable="@drawable/stat_sys_battery_5"/>

</level-list>

4.        其中maxLevel表示最大值,也就是说0-15用的是第一个资源,一个level是50的话,就会从第一个开始匹配,匹配到第三个的时候满足条件,所以就显示三格信号,还有minLevel表示最小值,二者结合可以确定一个level范围

5.        以电池图标显示为例,收到电池状态改变的广播后,获取电池电量百分比,设置相应的level

6.        在ondraw中,获取图片资源,在画布中显示即可

Drawable drawable = getDrawable();

BatteryStatuteBroadcastReceiverreceiver = mReceiver;

final int level = receiver.level;

drawable.setLevel(level);

Bitmapb = ((BitmapDrawable) drawable).getBitmap();

Bitmapbitmap = b.copy(Bitmap.Config.ARGB_8888,true);

canvas.drawBitmap(bitmap, 0, 0, null);

}

public voidupdateIcons() {

if (mTracker.status ==BatteryManager.BATTERY_STATUS_CHARGING&&mTracker.level != 100) {

setImageResource(R.drawable.battery_chargeing_level_list);

} else {

setImageResource(R.drawable.battery_level_list);

}

}

电池信息管理

我们的操作只是浮于表面,根据收到的广播,根据广播中携带的几个状态进行简单的判断显示,底层电池的状态如何改变,有什么测试方法,如何发送的Framework状态,Framework层又是如何打包发送电池状态改变的广播,需要我们再进行探索

Android电池管理的在上层功能其实很简单:无非是1.监测电池电量的变化并更新显示界面,2.监听进入充电状态和退出充电状态消息并更新界面

android系统电池部分的驱动程序,继承了传统linux系统下的Power Supply驱动程序架构,Battery驱动程序通过Power Supply驱动程序生成相应的sys文件系统,从而向用户空间提供电池各种属性的接口,然后遍历整个文件夹,查找各个能源供应设备的各种属性

Android的Linux 内核中的电池驱动会提供如下sysfs接口给framework:

/sys/class/power_supply/ac/onlineAC 电源连接状态

/sys/class/power_supply/usb/onlineUSB电源连接状态

/sys/class/power_supply/battery/status充电状态

/sys/class/power_supply/battery/health电池状态

/sys/class/power_supply/battery/present使用状态

/sys/class/power_supply/battery/capacity电池 level

/sys/class/power_supply/battery/batt_vol电池电压

/sys/class/power_supply/battery/batt_temp电池温度

/sys/class/power_supply/battery/technology电池技术

当供电设备的状态发生变化时,driver会更新这些文件,然后通过jni中的本地方法android_server_BatteryService_update向java层发送信息。当监听到power_supply变化的消息后, nativeUpdate函数就会重新读取以上sysfs文件获得当前状态。

而在用户层则是在BatteryService.java中通过广播的方式将如下一些电池相关的属性上报给上层app使用。

frameworks/base/services/java/com/android/server/BatteryService.java

BatteryService 在SystemServer.java 中创建,BatteryService是在系统启动的时候就跑起来的,为电池及充电相关的服务,主要作了如下几件事情: 监听 UEvent、读取sysfs 中的状态 、发出广播Intent.ACTION_BATTERY_CHANGED通知上层

底层上报电池变化的方式一:UEventObserver

在BatteryService定义了UEventObserver, uevent是Linux内核用来向用户空间主动上报事件的机制

private final UEventObservermInvalidChargerObserver =newUEventObserver() {

@Override

public voidonUEvent(UEventObserver.UEvent event) {

final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;

synchronized (mLock) {

if (mInvalidCharger != invalidCharger) {

mInvalidCharger =invalidCharger;

}

}

}

};

}

监听invalid_charger这个属性,当有状态变化时就去用onUEvent去处理

if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {

mInvalidChargerObserver.startObserving(

"DEVPATH=/devices/virtual/switch/invalid_charger");

}

UEvent的实现分为三层,API+JNI+HAL暂且不细表

我们可以看到上面的实现方式只监听了一种状态,其他的从JNI_OnLoad()得来

底层上报电池变化的方式二:通过AIDL,battery配置改变的时候,调用update

private final class BatteryListener extends IBatteryPropertiesListener.Stub {

@Override

public voidbatteryPropertiesChanged(BatteryProperties props) {

final long identity= Binder.clearCallingIdentity();

try {

BatteryService.this.update(props);

} finally {

Binder.restoreCallingIdentity(identity);

}

}

}

调用到processValuesLocked(),然后发送广播给关关系它的应用sendIntentLocked(),通过广播Intent.ACTION_BATTERY_CHANGED,将电池状态、电池电量、电池工艺等属性打包,发送给其它的使用者,也就是说,只要 在app程序里监听了Intent.ACTION_BATTERY_CHANGED这个广播,就能获取到电池的各种状态属性

应用如果想要接收到BatteryService发送出来的电池信息,则需要注册一个Intent为

Intent.ACTION_BATTERY_CHANGED的BroadcastReceiver,电池相关的属性就可以直接读到

附:电池相关的测试知识

◆驱动路径

/sys/class/power_supply/battery/status

◆读取电池的状态

cat /sys/class/power_supply/battery/uevent

◆模拟环境,取出电池配置文件

adb pull /system/etc/thermal-engine-8909.conf

[BATT_ID_MONITOR]
   algo_type monitor
   sensor batt_id
   sampling 1000
   thresholds 14000
   thresholds_clr 12000
   actions battery
   action_info 3

adb remount
adb push thermal-engine-8909.conf /system/etc/.
adb reboot

◆得到当前电池的温度,得到有背光和没有背光的温度区间

adb shell cat /sys/bus/spmi/devices/qpnp-vadc-*/batt_id

Android系统应用---SystemUI之三:状态栏电池图标的显示和Android电池管理的探讨相关推荐

  1. Android 系统(58)---Android 系统 UI - SystemUI之功能介绍和UI布局实现

    Android 系统 UI - SystemUI之功能介绍和UI布局实现 前言 Android ROM开发过程中,难免会涉及到对SystemUI的修改,之前做过一些这方面的工作,现在整理下,准备按照如 ...

  2. android 状态栏显示流程,基于Android系统的跨屏状态栏实现方法与流程

    本发明属于车机应用技术领域,具体涉及一种基于Android系统的跨屏状态栏实现方法. 背景技术: 目前,燃油车.新能源车等各类型车辆迅速发展.同时,与手持移动终端的发展趋势相似--从以黑莓品牌为代表的 ...

  3. Android11 状态栏icon图标的显示流程

    隐藏状态栏icon闹钟的显示 设置闹钟后在状态栏ICON区域会显示一个闹钟小图标,我们实现设置闹钟后让它不显示. 参考博客:https://blog.csdn.net/weixin_33881140/ ...

  4. Android实训课程之三 这次课老师先是提到了Android有四大组件:Activity、Service、Broadcast Receiver、Content Provider。然后重点提到Acti

    Android实训课程之三 这次课老师先是提到了Android有四大组件:Activity.Service.BroadcastReceiver.ContentProvider.然后重点提到Activi ...

  5. 笔记本电脑右下角的电池图标不显示如何找出

    首先在任务管理器的详细信息中找到 explorer.exe 文件,结束进程,之后在文件中运行新任务,输入explorer,即可重新打开,电池图标就显示啦. 另一种常用方法适合Win10 打开" ...

  6. Android 系统 UI - SystemUI之功能介绍和UI布局实现

    前言 Android ROM开发过程中,难免会涉及到对SystemUI的修改,之前做过一些这方面的工作,现在整理下,准备按照如下章节介绍SystemUI.借此对SystemUI做下整体性回顾.  -S ...

  7. Android系统 小米/三星/索尼 应用启动图标未读消息数(BadgeNumber)动态提醒

    在Android手机上,如QQ.微信当有未读消息的时候.我们可以看到在应用的启动图标的右上角会有一个红色圈圈.且圈圈里会动态显示未读消息的数目,如下图显示: 那么该功能是怎么实现的呢? 在万能的互联网 ...

  8. 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速【转】

    本文转载自:http://blog.csdn.net/mr_raptor/article/details/8006721 Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速 ...

  9. 对于ANDROID 5.0及其以上版本WIFI图标上显示感叹号的原因分析及解决方法

    这里我指的是WIFI可正常连接网络使用的前提下,手机状态栏WIF图标上仍出现感叹号的情况. 原因: 从 Android 5.0 开始,当安卓系统连接网络时,系统会向Google的某个特定的网址(htt ...

  10. Android6.0电池图标外显示电量百分比

    众所周知Android6.0进入界面后电池电量百分比被隐藏进了调谐者模式里面,即使打开调谐者模式显示电量数字也在电池图标里,对于某些习惯于5.1电量显示的人来说这是一个很难受的事情,那么这里我来提供一 ...

最新文章

  1. Git提交代码时报 Please tell me who you are
  2. matlab疲劳驾驶_第一本无人驾驶技术书
  3. 清华大学计算机专业学生埃朗读村,《朗读者~矣晓沅(清华大学计算机研究生  彝族)》...
  4. 机器学习复制粘贴笔记要点
  5. 白板推导系列Pytorch-支持向量机(SVM)
  6. 小木棍 [数据加强版]*
  7. elementui二维表动态渲染
  8. Coverage [minx,miny,maxx,maxy] is [12, 4, 13, 6, 3], index [x,y,z] is [2, 5, 3]错误原因及其解决方式
  9. 一文带小白玩转NFC、门禁卡
  10. python批量合并excel文件,后缀名为xls
  11. iphone远没有android好用,IPhone真的比Android流畅?不要被视觉欺骗了
  12. 如何用sql计算回购率、复购率指标
  13. 【硬盘】2021-西部数据叠瓦盘(SMR)、垂直盘(CMR/PMR)型号、容量大全
  14. 培养自己的核心竞争力
  15. [Swift]LeetCode16. 最接近的三数之和 | 3Sum Closest
  16. android switch设置背景文字,switchView
  17. 配置华为防火墙双机热备
  18. 中国教育和科技计算机网网络中心,中国教育和科研计算机网网络中心通告
  19. python 公司年会抽奖_python实现年会抽奖程序
  20. 如何把粉丝从一个公众号转移到另一个新的公众号上?或者把公众号的主体由A公司变为B公司?

热门文章

  1. Android Camera2对焦框和对焦
  2. 源支付5.18源码/三网免挂/带云端/附源码搭建教程
  3. 微信小程序 + 腾讯位置服务SDK 实现路线规划
  4. 计算日期间隔,以XX年XX月XX日格式显示
  5. 新年新气象,90行代码菜鸟用Python制作小姐姐新年日历天气卡,送人太有面子啦!...
  6. Lagrange’s Mean Value Theorem - 拉格朗日中值定理
  7. MacBook Pro打开前置摄像头
  8. 从此甩掉光驱 U盘安装系统最详攻略
  9. 浏览器-解决火狐浏览器总是提示Adobe Flash更新的问题
  10. 黑盒测试具体有哪些操作步骤?