android 4 systemui,深入理解Android(4)__深入理解SystemUI -- > SystemUIService的启动 - 好库文摘...

最近看了SystemUI的相关内容,百度了N个帖子,看了N个帖子,要么是大神的大神之作,要么是盗版的帖子,自己更是看的云里雾里。所以,励志自己啃懂,然后自己写!写一个是人就看得懂的白话文!事实上,可能大家依旧觉得有看不懂的地方,但是我会尽量的写全,把过程写到位,如果有不懂的,给我留言,贴主半夜起来给你解答!谢谢大家支持!共勉!

开始我们的正题吧,开始啃SystemUI这块硬骨头!.....Come on!

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1、SystemUIService启动时机

SystemUIService在何时由谁启动?作为一个系统级别的UI组件,自然要在系统的启动过程中寻找答案。

在负责启动各种系统服务的ServerThread中,当核心系统服务(init --> ServiceManager -- > zygote -- > SystemServer)启动完成后ServiceThread会通过调用ActivityManagerService.SystemReady()方法通知AMS系统已经就绪。

通过下面的代码,我们很清楚的发现,run()中找到了SystemUI的身影,通过调用startSystemUi方法,进行SystemUIService的启动。

源代码路径:/frameworks/base/services/java/com/android/server/SystemServer.java

[SystemServer.java -->ServerThread]

ActivityManagerService.self().systemReady(newRunnable() {public voidrun() {//调用startSystemUi()

Slog.i(TAG, "Making services ready");if (!headless) startSystemUi(contextF);

......

}

}

[SystemServer.java --> ServerThread.startSystemUi()]static final voidstartSystemUi(Context context) {

Intent intent= newIntent();

//设置SystemUIService作为启动目标

intent.setComponent(new ComponentName("com.android.systemui","com.android.systemui.SystemUIService"));//Slog.d(TAG, "Starting service: " + intent);     //启动SystemUIService

context.startServiceAsUser(intent, UserHandle.OWNER);

}

2、SystemUIService的创建

源代码路径:/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

查看源码,观察onCreate()方法:

public classSystemUIService extends Service {static final String TAG = "SystemUIService";/*SERVICES数组定义了运行于SystemUIService之中的子服务列表,当SystemUIService服务启动后会依次启动列表中所存储的子服务*/final Object[] SERVICES= newObject[] {0, //0号元素存储的是一个字符串符号,这个字符串符号存储实现状态栏/导航栏的类名.

com.android.systemui.power.PowerUI.class,

com.android.systemui.media.RingtonePlayer.class,

};

......

PublicvoidonCreate() {

......

IWindowManager wm=WindowManagerGlobal.getWindowManagerService();try{/* 根据IwindowManager.hasSystemNavBar()的返回值选择一个合适的状态栏与导航栏的实现 */

SERVICES[0] =wm.hasSystemNavBar()? R.string.config_systemBarComponent

: R.string.config_statusBarComponent;

}catch(RemoteException e) {......}

finalint N =SERVICES.length;

mServices= newSystemUI[N];for (int i=0; i

Class cl=chooseClass(SERVICES[i]);

Slog.d(TAG,"loading:" +cl);try{  //实例化子服务并将其存储在mServices数组中

mServices[i]=(SystemUI)cl.newInstance();

}catch(IllegalAccessException ex) {throw newRuntimeException(ex);

}catch(InstantiationException ex) {throw newRuntimeException(ex);

}

//设置Context,并通过调用其start()方法运行它

mServices[i].mContext= this;

Slog.d(TAG,"running:" +mServices[i]);

mServices[i].start();

}

}

......

}

我们可以发现,除了onCreate()方法之外,SystemUIService没有其他有意义的代码。

我们完全可以这么说,SystemUIService就是一个容器,在其启动时,将会逐个实例化定义在SERVICIES列表中的继承自SystemUI抽象类的子服务。

在调用了子服务的.start()方法后,SystemUIService便不做其他的事,任由各个子服务自行运行,状态导航栏也是这些子服务中的一个。

我们来看一下以下代码:

IWindowManager wm =WindowManagerGlobal.getWindowManagerService();try { /*根据IwindowManager.hasSystemNavBar()的返回值选择一个合适的状态栏与导航栏的实现*/SERVICES[0] =wm.hasSystemNavBar()? R.string.config_systemBarComponent

: R.string.config_statusBarComponent;

}catch (RemoteException e) {......}

我们跳转一下hasSystemNavBar,看一下代码:

源代码:/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

publicboolean hasSystemNavBar() {returnmHasSystemNavBar;

}public void setInitialDisplaySize(Display display, int width, int height, intdensity) {//SystemUI (status bar) layout policy // 计算屏幕短边的DP宽度

int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /density;

// 屏幕宽度在720dp以内时,使用分离的布局方案if (shortSizeDp < 600) {//0-599dp: "phone" UI with a separate status & navigation bar

mHasSystemNavBar = false;

mNavigationBarCanMove= true;

}else if (shortSizeDp < 720) {//600+dp: "phone" UI with modifications for larger screens

mHasSystemNavBar = false;

mNavigationBarCanMove= false;

}

}

hasSystemNavBar()的返回值取决于PhoneWindowManager.mhasSystemNavBar成员的取值。从以上的程序,我们可以发现根据短边的DP宽度,判定布局方案。

所谓的布局方案,在SystemUI中有两种:

(1)分离布局方案:PhoneStatusBar  --->  手机

(2)集成布局方案:TabletStatusBar --->  TV

关于dp宽度的计算问题,如果有读者不懂的,回答以下问题,就可看到超级详细的dp讲解哦,问题是:楼主帅不帅? 选项:A、真的帅,B、不要脸!

好了,下一次帖子,我会跟大家一起继续深入学习SystemUI,关注PhoneStatusBar和它的爸爸BaseStatusBar,敬请期待!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值