Android4.4 SystemUI分析之PowerUI
来源:互联网 发布:linux 修改语言环境 编辑:程序博客网 时间:2024/04/29 17:59
以下分析是基于MTK Android4.4原生的SystemUI与Google 的SystemUI有微小的区别,但两者的整体框架是差不多的。
这一篇是分析SystemUI的第一篇,先从最简单的PowerUI着手,源码路径:/frameworks/base/packages/SystemUI 程序目录结构如下:
我导入Eclipse编辑,报错的原因是因为找不到Framework上的一些包和资源,这个没有关系;修改完后在使用mmm模块编译,再push到手机(eng版本)上进行调试,push后需要重启才能生效。
在AndroidManifest.xml上没有Activity注册
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>所以整个程序启动是从外部启动SystemUIService的。那么是如何启动SystemUIService的呢?看下这个文件:/frameworks/base/services/java/com/android/server/SystemServer.java在这个文件中可以找到
static final void startSystemUi(Context context) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.OWNER); }所以SystemUI在SystemService启动时就被调用了。
SystemUIService的关键代码如下:
package com.android.systemui;import android.app.Service;import android.content.Intent;import android.content.res.Configuration;import android.os.IBinder;import android.util.Log;import java.io.FileDescriptor;import java.io.PrintWriter;import java.util.HashMap;public class SystemUIService extends Service { private static final String TAG = "SystemUIService"; /** * The classes of the stuff to start. */ private final Class<?>[] SERVICES = new Class[] { com.android.systemui.recent.Recents.class, com.android.systemui.statusbar.SystemBars.class, com.android.systemui.usb.StorageNotification.class, com.android.systemui.power.PowerUI.class, com.android.systemui.media.RingtonePlayer.class, com.android.systemui.settings.SettingsUI.class, }; /** * Hold a reference on the stuff we start. */ private final SystemUI[] mServices = new SystemUI[SERVICES.length]; @Override public void onCreate() { HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>(); final int N = SERVICES.length; for (int i=0; i<N; i++) { Class<?> cl = SERVICES[i]; Log.d(TAG, "loading: " + cl); Log.d("dzt", "loading: " + cl); try { mServices[i] = (SystemUI)cl.newInstance(); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = components; Log.d(TAG, "running: " + mServices[i]); Log.d("dzt", "running: " + mServices[i]); mServices[i].start(); } }}这些类
com.android.systemui.recent.Recents.class, com.android.systemui.statusbar.SystemBars.class, com.android.systemui.usb.StorageNotification.class, com.android.systemui.power.PowerUI.class, com.android.systemui.media.RingtonePlayer.class, com.android.systemui.settings.SettingsUI.class,
都是继承于:SystemUI,在SystemUIService的OnCreate()函数中会创建实例,并调用mServices[i].start();方法。
下面就分析最简单的com.android.systemui.power.PowerUI.class
在PowerUI的start()方法中,注册一些监听器
public void start() { mLowBatteryAlertCloseLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryCloseWarningLevel); mLowBatteryReminderLevels[0] = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); mLowBatteryReminderLevels[1] = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); // Register for Intent broadcasts for... IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); /// M: Support show battery level when configuration changed. @{ filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); /// M: Support show battery level when configuration changed. @} /// M: Hide low battery dialog when PowerOffAlarm ring. @{ filter.addAction("android.intent.action.normal.boot"); filter.addAction("android.intent.action.ACTION_SHUTDOWN_IPO"); /// M: Hide low battery dialog when PowerOffAlarm ring. @} mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); }例如监听ACTION_BATTERY_CHANGED判断电量的大小,如果低电给一个提示给用户,其它的ACTION也都是根据广播来处理一些特定的事情,如果跟电源相关功能需要定制或添加新的监听器都可以在这个类中修改。
关于电源监听的详细信息可以查看:http://blog.csdn.net/deng0zhaotai/article/details/39521461
SystemUI上的电池是如何画上去的呢?看下图
在status_bar.xml这个布局文件中可以找到
<com.android.systemui.BatteryMeterView android:id="@+id/battery" android:layout_height="16dp" android:layout_width="10.5dp" android:layout_marginBottom="0.33dp" android:layout_marginStart="4dip" />这个就是显示电池图标的View,类定义在/frameworks/base/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
我在这里把BatteryMeterView.java拿出来写了一个Demo就是上图在Activity上显示的电池小图标
在BatteryMeterView类中有两个重要的函数来注册广播和注销广播
@Overridepublic void onAttachedToWindow() {super.onAttachedToWindow();IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_CHANGED);filter.addAction(ACTION_LEVEL_TEST);final Intent sticky = getContext().registerReceiver(mTracker, filter);if (sticky != null) {// preload the battery levelmTracker.onReceive(getContext(), sticky);}}@Overridepublic void onDetachedFromWindow() {super.onDetachedFromWindow();getContext().unregisterReceiver(mTracker);}在广播上监听电池的改变调用postInvalidate() 去绘制小图标
private class BatteryTracker extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {if (testmode && !intent.getBooleanExtra("testmode", false))return;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);Log.i(TAG, "onReceive ----- level = " + level + " plugType = "+ plugType + " health = " + health + " status = "+ status + " technology = " + technology+ " voltage = " + voltage + " temperature = "+ temperature);setContentDescription(context.getString(R.string.accessibility_battery_level, level));postInvalidate();} }}BatteryTracker mTracker = new BatteryTracker();调用postInvalidate()会回调View的public void draw(Canvas c)去重绘图标。
整个小图标的绘制都是在public void draw(Canvas c)中完成的,没有用到图片,详细的细节就需要好好分析源码
log的TAG
private static final String TAG = TestSystemUI.class.getSimpleName();
得到的TAG就是TestSystemUI
- Android4.4 SystemUI分析之PowerUI
- Android4.4 SystemUI分析之DessertCase
- Android4.4 SystemUI分析之Clock时钟显示
- Android4.4 Systemui状态栏之信号逻辑流程分析
- android 6.0 SystemUI源码分析(5)-PowerUI介绍
- Android4.1Systemui分析
- android4 SystemUI 流程分析
- systemui开发---PowerUI && StorageNotification
- android4.4 systemUI设置
- Android4.4 Systemui状态栏状态图标更新流程分析
- Android4.4 systemui 启动流程
- Android学习——systemUIService 之PowerUI分析
- android4.4 SystemUI的分析及滑动navigation的显示和隐藏
- Android4.4 SystemUI添加Dialog弹窗
- 某android4.4手机的SystemUI
- android4.4修改SystemUI编译出错
- Android4.0 SystemUI
- SystemUI之Airplane mode之分析
- ActiveMQ 文件传输
- 华人首富李嘉诚说:不想穷,就好好记住这篇文章!
- Solr入门之SolrServer实例化方式
- 求最大公共子串
- Android Listener侦听的几种写法
- Android4.4 SystemUI分析之PowerUI
- 一种可行的系列动画播放方式
- poj_3273
- 连接数优化
- JSON字符串转javabean,MorphDynaBean cannot be cast to...问题解决
- .NET动态编译
- u-boot代码分析
- leetcode || 63、Unique Paths II
- 读《wireshark网络分析就这么简单》