现在的位置: 首页 > 综合 > 正文

Android4.0 状态栏启动(1)

2013年08月13日 ⁄ 综合 ⁄ 共 4860字 ⁄ 字号 评论关闭

android4.0系统可以运行于平板电脑和手机上面,这样对于状态栏来说,也是有不同风格的,从SystemUi的代码分类我就可以看出来,google考虑了不同情况下状态栏的显示等,

在源代码里面有这么两个文件夹需要注意:

com.android.systemui.statusbar.phone  这个是针对手机而需要的status bar

com.android.systemui.statusbar.tablet   这个是针对平板电脑而需要的staus bar(system bar)

 

首先状态栏是如何启动起来的呢?

我们都知道系统刚启动,在SystemServer会加载系统的各种服务,状态栏也不例外,就是在这个时候创建的,代码如下:

SystemServer.java

 ActivityManagerService.self().systemReady(new Runnable() {
            public void run() {
                Slog.i(TAG, "Making services ready");

                startSystemUi(contextF);
                try {
                    if (batteryF != null) batteryF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Battery Service ready", e);
                }

 

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.startService(intent);
    }

 

通过上面的代码我就看到系统启动了com.android.systemui.SystemUIService 这个服务,在这个服务里面就会启动状态栏,

但是这里就会有个选择,是启动status bar呢 还是启动 system bar呢,android是这么决定的:

public void onCreate() {
        // Pick status bar or system bar.
        IWindowManager wm = IWindowManager.Stub.asInterface(
                ServiceManager.getService(Context.WINDOW_SERVICE));
        try {
            SERVICES[0] = wm.canStatusBarHide()  (1)
                    ? R.string.config_statusBarComponent(2)
                    : R.string.config_systemBarComponent;(3)
        } catch (RemoteException e) {
            Slog.w(TAG, "Failing checking whether status bar can hide", e);
        }

        final int N = SERVICES.length;
        mServices = new SystemUI[N];
        for (int i=0; i<N; i++) {
            Class cl = chooseClass(SERVICES[i]);
            Slog.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;
            Slog.d(TAG, "running: " + mServices[i]);
            mServices[i].start();
        }
    }

 

上面的(1) 出,会调用到phoneWIndowManager里面对应的那个函数,在那里面会根据配置文件,手机宽高等信息来判断使用哪一种bar,代码如下

public boolean canStatusBarHide() {
        return mStatusBarCanHide;
    }

 if (width > height) {
            shortSize = height;
          .........

        } else {
            shortSize = width;
          .......

        }

        // Determine whether the status bar can hide based on the size
        // of the screen.  We assume sizes > 600dp are tablets where we
        // will use the system bar.
        int shortSizeDp = shortSize
                * DisplayMetrics.DENSITY_DEFAULT
                / DisplayMetrics.DENSITY_DEVICE;
        mStatusBarCanHide = shortSizeDp < 600;
        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                mStatusBarCanHide
                ? com.android.internal.R.dimen.status_bar_height
                : com.android.internal.R.dimen.system_bar_height);

 

这里假如手机宽(高) 小于600dp,就认为是手机了,这样mStatusBarHide = true;

我们回到这里

SERVICES[0] = wm.canStatusBarHide()  

                    ? R.string.config_statusBarComponent;

                    : R.string.config_systemBarComponent;

这样SERVICES[0]  = R.string.config_statusBarComponent (这个字符串就是 com.anroid.systemui.statusbar.phone)

实际上SERVERCES这个数组里面就两个元素,一个是我们上面的那个com.anroid.systemui.statusbar.phone ,另外一个是PowerUI,这个暂且不管,这个主要是根据电量等信息弹出一些提示框,比如电量低,或者充电器有问题等框。

接下来会调用com.anroid.systemui.statusbar.phone的start方法,注意com.anroid.systemui.statusbar.phone这个类不是一个服务,就是一个普通的类,start方法也是它的一个普通的方法而已。

在start方法里面就会创建状态栏那些界面对应的各种view,包括下拉状态栏后的view等,把这些view都创建好以后,就把这个view加载windowmanager里面就可以了,这样状态栏就可以显示出来了,代码如下:

 

final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                PixelFormat.OPAQUE);
       
        // the status bar should be in an overlay if possible
        final Display defaultDisplay
            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        if (ActivityManager.isHighEndGfx(defaultDisplay)) {
            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        }

        lp.gravity = getStatusBarGravity();
        lp.setTitle("StatusBar");
        lp.packageName = mContext.getPackageName();
        lp.windowAnimations = R.style.Animation_StatusBar;
        WindowManagerImpl.getDefault().addView(sb, lp);  //这里的sb就是状态栏view

 

这里需要注意的是 平时看到的状态栏和下拉后的状态栏是两个东西,不要混到一起,而且这里也会创建两个view,一个是普通的状态栏view,另外一个下拉后的view,这两个view都要加载WindosManager里面,添加的代码基本一样,但是最重要的是那个参数里面的type是不一样的,一个是WindowManager.LayoutParams.TYPE_STATUS_BAR,而下拉的那个type是WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;

 

 

 

 

抱歉!评论已关闭.