Android SystemUI源码分析(一)
2016-05-27 10:53
543 查看
最近,在做SystemUI的项目。公司主要是做汽车后视镜产品的。 在后视镜中嵌入了android OS, 主要有导航,语音,蓝牙控制等等功能。MTK平台。对于非手机的产品来说,改动还是蛮大的。附:我司产品效果图。
PS : 改动Launcher的地方也挺大的。说正题吧。
对于手机来说SystemUI指的是:StatusBar(状态栏)、NavigationBar(导航栏)。
对于Tablet或者是TV来说SystemUI指的是:CombinedBar(包括了StatusBar和NavigationBar)。
启动后Phone界面上的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的SystemUI,因此对于整个Android系统来说,SystemUI都有举足轻重的作用。
源码的路径地址: ……. \frameworks\base\packages\SystemUI。
打开SystemUI的manifase.xml文件,可以看到有一个SystemUIService,这个Service是在SystemServer.Java中被启动的,如下所示:
启动后,在看看SystemUIService里,在onCreate()函数里,
在这段代码中,通过AIDL的方式获取了WindowManager的对象wm,并调用其方法canStatusBarHide()来判断当前设备的类型,也就是说如果我们使用的Phone那么后续就会加载StatusBar和NivagationBar;而如果我们设备类型是Tablet(TV)之类的(可以在配置文档里面配置),就会加载CombiedBar。。在com.android.systemui.statusbar包下的PhoneStatusBar才是我们的重点。
这里的重心主要是在super.start()和addNavigationBar()上。目前市面上很多手机已经刷入了ICS,但是大多数是没有NavigationBar的,也就是说自己修改了源码,屏蔽了NavigationBar。继续跟踪super.start()方法,来到/SourceCode/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java的start()方法中.在这里,完成了SystemUI的整个初始化以及设置过程
aefd
,并最终呈现到界面上。在StatusBar中的start()方法主要完成了以下几个工作:首先获取需要在StatusBar上显示的各种icons。然后初始化一些属性。最后通过WindowManager的addView方法将StatusBar显示出来。分析到这里可能有人会问了,明明说分析的是SystemUI的嘛,怎么最后变成StatusBar了呢?如果你硬要说我跑题那我也没有办法,回过头去看看addNavigationBar(),你会发现和StatusBar的加载几乎一致,因此没必要再详述了。如果细心阅读了的朋友肯定会发现这句代码:
mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
<待续。。。。。。。>
PS : 改动Launcher的地方也挺大的。说正题吧。
对于手机来说SystemUI指的是:StatusBar(状态栏)、NavigationBar(导航栏)。
对于Tablet或者是TV来说SystemUI指的是:CombinedBar(包括了StatusBar和NavigationBar)。
启动后Phone界面上的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的SystemUI,因此对于整个Android系统来说,SystemUI都有举足轻重的作用。
源码的路径地址: ……. \frameworks\base\packages\SystemUI。
导入Eclipse里后显示的是两个工程,UsbStorageActivity 和 ScreenshotStubActivity,主要的改动在USBStorageActivity里。
打开SystemUI的manifase.xml文件,可以看到有一个SystemUIService,这个Service是在SystemServer.Java中被启动的,如下所示:
启动后,在看看SystemUIService里,在onCreate()函数里,
/** * 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, }; 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); 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]); mServices[i].start(); } }
在这段代码中,通过AIDL的方式获取了WindowManager的对象wm,并调用其方法canStatusBarHide()来判断当前设备的类型,也就是说如果我们使用的Phone那么后续就会加载StatusBar和NivagationBar;而如果我们设备类型是Tablet(TV)之类的(可以在配置文档里面配置),就会加载CombiedBar。。在com.android.systemui.statusbar包下的PhoneStatusBar才是我们的重点。
@Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); updateDisplaySize(); /// M: Support Smartbook Feature. if (SIMHelper.isMediatekSmartBookSupport()) { /// M: [ALPS01097705] Query the plug-in state as soon as possible. mIsDisplayDevice = SIMHelper.isSmartBookPluggedIn(mContext); Log.v(TAG, "start, mIsDisplayDevice=" + mIsDisplayDevice); } super.start(); // calls createAndAddWindows() addNavigationBar(); // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext); mHeadsUpObserver.onChange(true); // set up if (ENABLE_HEADS_UP) { mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(SETTING_HEADS_UP), true, mHeadsUpObserver); } //RMT add mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor("navi_bar_status"), false, mNaviBarObserver); mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor("dvr_record_resume"), false, mDvrRecordResumeObserver); mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor("avin_status"), false, mAvinStatusObserver); //xxx crash start mContext.registerReceiver(mDvrSmallWindow, new IntentFilter("com.xxx.small.ACTION_WINDOW")); mContext.registerReceiver(mDvrMaxWindow, new IntentFilter("com.xxx.max.ACTION_WINDOW")); // xxx crash end }
这里的重心主要是在super.start()和addNavigationBar()上。目前市面上很多手机已经刷入了ICS,但是大多数是没有NavigationBar的,也就是说自己修改了源码,屏蔽了NavigationBar。继续跟踪super.start()方法,来到/SourceCode/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java的start()方法中.在这里,完成了SystemUI的整个初始化以及设置过程
aefd
,并最终呈现到界面上。在StatusBar中的start()方法主要完成了以下几个工作:首先获取需要在StatusBar上显示的各种icons。然后初始化一些属性。最后通过WindowManager的addView方法将StatusBar显示出来。分析到这里可能有人会问了,明明说分析的是SystemUI的嘛,怎么最后变成StatusBar了呢?如果你硬要说我跑题那我也没有办法,回过头去看看addNavigationBar(),你会发现和StatusBar的加载几乎一致,因此没必要再详述了。如果细心阅读了的朋友肯定会发现这句代码:
mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Android 4.0的SystemUI加载启动的过程大致就是这样,虽然看似简单,但这仅仅是个开始,master还是后面呢!!各家厂商根据自家的需求,需要定制SystemUI或者美化SystemUI,不同的平台(QCOM、MTK等等)也会有不同的修改,但大体框架是没有变的,无非是在原有基础上的修修改改或者增加一些自己的类等等。通过对Android源码框架性的理解,可以学习到很多设计上的知识(虽然自己还很欠缺)。通过这次分析,开始逐渐用StarUML来画时序图,这也是一个学习的过程。
<待续。。。。。。。>
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories