android(cm11)状态栏源码分析(一)
来源:互联网 发布:动态壁纸软件情侣 编辑:程序博客网 时间:2024/05/31 05:28
(一):写在前面
最近由于工作需要,需要了解CM11中的有关于StatusBar相关的内容。总的来说,刚开始阅读其源码的时候,是有点困难,不过通过构建相关代码的脑图和流程图,几天下来,我已经对其源码有了一个大体的了解,不过其内部细节还有很多不是很明白,但是这对于我的工作来说就已经足够了。
在android系统中,有关于系统状态栏有关的代码位于/framework/base/packages/SystemUI/中,很明显,该SystemUI是一个app源码,当系统进行编译的时候,就会生成SystemUI.apk。所以我们对待它就像是对待普通app程序一样。
好了,现在开始我们的代码分析。
(二):StatusBar流程分析
对于android系统来说,SystemUI的启动是有位于packages下面的android系统launcher启动器启动的,启动方式其实是通过java的反射机制实现的。其启动SystemUI的SystemUIService,该SystemUIService是Service的一个子类,同时,在该类中通过反射机制同时启动6个和系统UI相关的类,这个我们后面再分析。
这6个和系统UI相关的类都继承自SystemUI类,在SystemUIService中实例化这6个类的时候同时启动该类对应的start()方法来启动服务。而他们的start()函数中主要是启动相关ServiceMonitor的start方法,在该ServiceMonitor中主要是启动相关的包的服务,即调用startService()函数。在启动服务的时候,就会实例化StatusBar,并且调用其onStart()函数。这个就是StatusBar的启动流程,这样说的话可能理解起来比较繁琐,下面的这张图就是系统状态栏的启动过程的流程图:
(三):SystemUIService源码分析
下面我们来分析一下SystemUIService的源码。
该SystemUIService类继承自Service类,说明该类是一个服务类,在该类中都是干了什么工作呢?我们先找到Service类中的onCreate()方法:
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(); } }
从这里可以看出,通过一个for循环将数组SERVICES中保存的类实例化,即调用newInstance()函数,实例化完成之后,对其对象中的属性进行赋值,最后再调用相应的start()函数。
下面我们来看一下SERVICES数组中的保存的6个类:
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, };
当然,在这个类里面也存有其他相关的函数,包括配置发生改变的函数,销毁函数等,下面我们来看一下该类的脑图:
由于在这里启动了6个相关的类,但是我们在这篇文章中,我们先分析SystemBars.class类。
(四):SystemBars源码分析
在上面的流程图中,我们知道,启动的6个类都是继承自SystemUI类,我们先来看一下SystemUI类:
SystemUI类是一个抽象类,在该类中定义了一些方法,其中包括启动方法,配置发生改变的函数,销毁函数等。下面我们先来看一下该类的代码:
public Context mContext; public Map<Class<?>, Object> mComponents; public abstract void start(); protected void onConfigurationChanged(Configuration newConfig) { } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } @SuppressWarnings("unchecked") public <T> T getComponent(Class<T> interfaceType) { return (T) (mComponents != null ? mComponents.get(interfaceType) : null); } public <T, C extends T> void putComponent(Class<T> interfaceType, C component) { if (mComponents != null) { mComponents.put(interfaceType, component); } }
在这个类中,比较有意思的就是Map对象,该对象就是保存相关类的组件。下面我们来看一下脑图:
下面我们来看SystemBars的源码,在这里我们主要查看的是其start()函数:
mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found
在这里,主要是初始化ServiceMonitor对象,并且调用其start()函数。
但是对于ServiceMonitor类的对象来说,其start()函数,最终都要调用位于SystemBars类中的createStatusBarFromConfig()函数,在该函数中,主要是调用BaseStatusBar对象的start()函数。
private void createStatusBarFromConfig() { if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); final String clsName = mContext.getString(R.string.config_statusBarComponent); if (clsName == null || clsName.length() == 0) { throw andLog("No status bar component configured", null); } Class<?> cls = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (BaseStatusBar) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; mStatusBar.start(); if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); }
下面我们来看一下SystemBars类的脑图:
(五):ServiceMonitor源码分析
在ServiceMonitor类中主要是使用Handler中的信息类来进行包服务管理,其中有启动服务,继续服务,暂停服务,停止服务等函数,在这里辗转反侧最终还是回归到SystemBars中的StatusBars的启动:
(六):最终流程分析
上面我们提到了,最终还是要启动StatusBar,而这里启动的StatusBar并不是其真正的StatusBar,而是他的子类,也就是位于com/android/systemui/statusbar/phone/PhoneStatusBar.java,下面我们来看一下他的start()函数:
@Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); updateDisplaySize(); ThemeConfig currentTheme = mContext.getResources().getConfiguration().themeConfig; if (currentTheme != null) { mCurrentTheme = (ThemeConfig)currentTheme.clone(); } else { mCurrentTheme = ThemeConfig.getSystemTheme(); } mLocationController = new LocationController(mContext); mBatteryController = new BatteryController(mContext); mDockBatteryController = new DockBatteryController(mContext); mBluetoothController = new BluetoothController(mContext); super.start(); // calls createAndAddWindows() addNavigationBar(); SettingsObserver observer = new SettingsObserver(mHandler); observer.observe(); // Developer options - Force Navigation bar try { boolean needsNav = mWindowManagerService.needsNavigationBar(); if (!needsNav) { mDevForceNavbarObserver = new DevForceNavbarObserver(mHandler); mDevForceNavbarObserver.observe(); } } catch (RemoteException ex) { // no window manager? good luck with that } // 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.System.getUriFor(Settings.System.HEADS_UP_NOTIFICATION), true, mHeadsUpObserver, mCurrentUserId); } }
在这个代码中,我们看到代码中,有一个类PhoneStatusBarPolicy类,该类就是向状态栏中添加图标的管理类。下面我们来看一下该类的构造方法:
public PhoneStatusBarPolicy(Context context) { mContext = context; mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); // listen for broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_ALARM_CHANGED); filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); mSimState = new IccCardConstants.State[numPhones]; for (int i=0; i < numPhones; i++) { mSimState[i] = IccCardConstants.State.READY; } // TTY status mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null); mService.setIconVisibility("tty", false); // Cdma Roaming Indicator, ERI mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null); mService.setIconVisibility("cdma_eri", false); // bluetooth status BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); int bluetoothIcon = R.drawable.stat_sys_data_bluetooth; if (adapter != null) { mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON); if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) { bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected; } } mService.setIcon("bluetooth", bluetoothIcon, 0, null); mService.setIconVisibility("bluetooth", mBluetoothEnabled); // Alarm clock mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null); mService.setIconVisibility("alarm_clock", false); // Sync state mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null); mService.setIconVisibility("sync_active", false); // "sync_failing" is obsolete: b/1297963 // volume mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null); mService.setIconVisibility("volume", false); updateVolume(); }
而这里主要是添加监听广播,并且添加其他相关图标。
还有有些图标是在布局文件中添加的,其中于StatusBar相关的布局文件是在下面几个文件中的:
- SystemUI/res/layout/status_bar.xml
- SystemUI/res/layout/super_status_bar.xml
以及其内部include的相关文件。
好了,至此,有关与android系统状态栏相关的代码已经了解的差不多了,通过这个,我们可以向状态栏中添加图标或者是删除图标,这个是比较简单了。
好了,有关与状态栏的代码我们就分析到此,后面我们再来分析QuickSettings的相关的代码。
- android(cm11)状态栏源码分析(一)
- [Android]下载CM11.0 Android 源码过程与错误解决
- 下载CM11.0 Android 源码过程与错误解决
- CM11.0源码编译
- Android源码分析--MediaServer源码分析(一)
- Android源码分析--MediaServer源码分析(一)
- Android Gallery3D源码分析(一)
- android binder驱动源码分析(一)
- phonegap源码分析(一)------ android
- android gallery3d 源码分析(一)
- phonegap源码分析(一)------ android
- Android Gallery3D源码分析(一)
- phonegap源码分析(一)------ android
- phonegap源码分析(一)------ android
- phonegap源码分析(一)------ android
- Android Launcher源码分析(一)
- android WifiDisplay 源码分析系列 (一)
- Android AsyncTask源码分析(一)
- SQL数据库对某一字段下的值进行求和,然后倒序排序
- 欢迎使用CSDN-markdown编辑器
- 位域初识
- javascript 导出div为图片PNG,div转svg,svg转canvas
- C++标准库——时间相关
- android(cm11)状态栏源码分析(一)
- javascript中window.event事件用法详解
- Strategy Pattern 策略模式
- 自定义jstl fn函数fns
- Android RecyclerView 使用完全解析 体验艺术般的控件
- julia :谈循还,row 与 col who first?
- Spring AOP 事务管理
- 返回键的处理,以及退出程序
- Unity3D-DoTween