android SystemUI全解析

来源:互联网 发布:sql语句分页查询实例 编辑:程序博客网 时间:2024/05/22 11:39

本文由以下博客转载解释编辑而成:

 

Android Frameworks层开发之SystemUI分析


Android 4.0 ICS SystemUI浅析——StatusBar加载流程分析

Android 4.0 ICS SystemUI浅析——SystemUI启动流程


Android 4.0 ICS 用户界面概述

希望以一种更好的理解和解释帮助大家和自己了解android SystemUI

首先了解android系统栏(SystemUI)

  1.   状态栏(statusBar)

    在左侧显示等候处理的通知以及在右侧显示一些设备状态,包括时间,电量等级,信号强度。轻轻的向下滑动状态栏将显示通知的细节。

  2. 导航栏(navigationBar)

    这是Android 4.0 手机上的新功能,导航栏目前只会出现在没有传统的物理按键的设备上。它囊括了设备的导航控制,包括返回,回到主界面,最近使用,同时在Android 2.3或者更早版本编写的应用程序中扮演了Menu的角色。

  3. 复合栏

    在平板电脑上,状态栏和导航栏结合在一起显示在屏幕底部。

1.初始SystemUI

我们知道Android 同时适用于Phone和Tablet(TV),因此,对于Phone来说SystemUI指的是:

StatusBar(状态栏)、NavigationBar(导航栏)。而对于Tablet或者是TV来说SystemUI指的是:

CombinedBar(包括了StatusBar和NavigationBar)

知悉statusBar 和navigationBar 含义请查看我的

 

Android Frameworks层开发之SystemUI分析

首先来看看SystemUI的代码位置,路径:SourceCode/frameworks/base/packages/SystemUI

在Android 4.0及以上中,Google整合了Phone和Tablet(TV)的SystemUI,也就说可以根据设备

的类型自动匹配相应的SystemUI

通过我的Android Frameworks层开发之SystemUI分析,我们可以知道

SystemUIService是在SystemServer.java中被启动的

[java] view plaincopy
  1. static final void startSystemUi(Context context) {  
  2.     Intent intent = new Intent();  
  3.     intent.setComponent(new ComponentName("com.android.systemui",  
  4.                 "com.android.systemui.SystemUIService"));  
  5.     Slog.d(TAG, "Starting service: " + intent);  
  6.     context.startService(intent);  
  7. }
这里的startSystemUi()方法则在ServerThread的run()方法中被调用。这里提到SystemServer就不得不提及Android的启动流程

 Android的启动分为内核启动、Android启动、launcher启动,我们的SystemServer就处于Android启动中

既然到这里SystemUIService已经启动,

首先查看其onCreate()方法,如下:

[java] view plaincopy
  1. public void onCreate() {  
  2.     // Pick status bar or system bar.  
  3.     IWindowManager wm = IWindowManager.Stub.asInterface(  
  4.             ServiceManager.getService(Context.WINDOW_SERVICE));  
  5.     try {  
  6.         SERVICES[0] = wm.canStatusBarHide()//根据wm.canStatusBarHide()判断设备类型  
  7.                 ? R.string.config_statusBarComponent  
  8.                 : R.string.config_systemBarComponent;  
  9.     } catch (RemoteException e) {  
  10.         Slog.w(TAG, "Failing checking whether status bar can hide", e);  
  11.     }  
  12.   
  13.     final int N = SERVICES.length;  
  14.     mServices = new SystemUI[N];  
  15.     for (int i=0; i<N; i++) {  
  16.         Class cl = chooseClass(SERVICES[i]);  
  17.         Slog.d(TAG, "loading: " + cl);  
  18.         try {  
  19.             mServices[i] = (SystemUI)cl.newInstance();  
  20.         } catch (IllegalAccessException ex) {  
  21.             throw new RuntimeException(ex);  
  22.         } catch (InstantiationException ex) {  
  23.             throw new RuntimeException(ex);  
  24.         }  
  25.         mServices[i].mContext = this;  
  26.         Slog.d(TAG, "running: " + mServices[i]);  
  27.         mServices[i].start();  
  28.     }  
  29. }  

在这段代码中,通过AIDL的方式获取了WindowManager的对象wm,

并调用其方法canStatusBarHide()来判断当前设备的类型,

也就是说如果我们使用的Phone那么后续就会加载StatusBar和NivagationBar;

而如果我们设备类型是Tablet(TV)之类的

(可以在配置文档里面配置),
就会加载CombiedBar。

这里的canStatusBarHide()方法的具体实现是在:frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java。

为什么会是这里呢?我们在Eclipse中导入源码之后,找到SystemUIService.java中的

wm.canStatusBarHide()方法,通过open Implementation直接跳转到WindowsManagerService中:

[java] view plaincopy
  1. public boolean canStatusBarHide() {  
  2.     return mPolicy.canStatusBarHide();  
  3. }  

但这里我们发现canStatusBarHide()实际上是WindowManagerPolicy的对象调用的方法,

而WindowManagerPolicy只是一个接口类,根据以往分析的经验可以知道,

这里的WindowManagerPolicy对象所调用的canStatusBartHide()方法一定是其实现类中的方法。

因此,继续通过open Implementation跳转,来到了PhoneWindownManager中:

[java] view plaincopy
  1. public boolean canStatusBarHide() {  
  2.     return mStatusBarCanHide;  
  3. }  

继续查看mSatuBarCanHide的实现,如下所示:

[java] view plaincopy
  1. // Determine whether the status bar can hide based on the size  
  2. // of the screen.  We assume sizes > 600dp are tablets where we  
  3. // will use the system bar.  
  4. int shortSizeDp = shortSize  
  5.         * DisplayMetrics.DENSITY_DEFAULT  
  6.         / DisplayMetrics.DENSITY_DEVICE;  
  7. mStatusBarCanHide = shortSizeDp < 600;  
  8. mStatusBarHeight = mContext.getResources().getDimensionPixelSize(  
  9.         mStatusBarCanHide  
  10.         ? com.android.internal.R.dimen.status_bar_height  
  11.         : com.android.internal.R.dimen.system_bar_height);  
  12.   
  13. mHasNavigationBar = mContext.getResources().getBoolean(  
  14.         com.android.internal.R.bool.config_showNavigationBar);  

这里通过shortSizeDp来判断当前设备的类型,如果当前屏幕的shortSize
Dp<600dp,

则系统会认为该设备是Phone反之则认为是Tablet。根据mStatusBarCanHide的值,

设定StatusBar或者SystemBar(CombinedBar)的高度,以及是否显示NavigationBar。

        继续回到我们的SystemUIService.java的onCreate()方法中,根据前面对canStatusBarHide()

的判断,SERVICE[0]中将存放R.string.config_statusBarComponent或者

R.string.config_systemBarComponent。它们的值具体是:

[html] view plaincopy
  1. <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>  
  2. <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>  

因为我的测试设备是Phone,那么现在SERVICE[0]中存放的就是

com.android.systemui.statusbart.phone.PhoneStatusBar。查看以下代码:

[java] view plaincopy
  1. final int N = SERVICES.length;  
  2. mServices = new SystemUI[N];  
  3. for (int i=0; i<N; i++) {  
  4.     Class cl = chooseClass(SERVICES[i]);  
  5.     Slog.d(TAG, "loading: " + cl);  
  6.     try {  
  7.         mServices[i] = (SystemUI)cl.newInstance();  
  8.     } catch (IllegalAccessException ex) {  
  9.         throw new RuntimeException(ex);  
  10.     } catch (InstantiationException ex) {  
  11.         throw new RuntimeException(ex);  
  12.     }  
  13.     mServices[i].mContext = this;  
  14.     Slog.d(TAG, "running: " + mServices[i]);  
  15.     mServices[i].start();  
  16. }  

这些方法会分别启动两个方法,这两个方法可以从log中知道,分别是

PhoneStatusBar.start()和PowerUI.start()。而我们的目的是要弄清SystemUI的启动,

因此现关注PhoneStatusBar.start()方法。

知悉我的 

Android Frameworks层开发之SystemUI分析

那么我们这里的重心主要是在super.start()和addNavigationBar()

super.start()用于首先获取需要在StatusBar上显示的各种icons。

然后初始化一些属性。最后通过WindowManager的addView方法将StatusBar显示出来。

addNavigationBar()用于启用NavigationView

想要进一步的开发StatusBar,请参阅http://blog.csdn.net/yihongyuelan/article/details/7623578,

我这里只是解释加载过程


0 0
原创粉丝点击