修改状态栏的时间

本文详细介绍了Android4.2中SystemUI的启动流程,特别是如何修改状态栏时间的展示。通过分析SystemUI的代码结构和服务启动,揭示了如何根据不同设备类型加载相应SystemUI组件。在StatusBarManagerService中,通过Clock组件的updateClock方法和getSmallTime方法,可以对状态栏时间进行定制,从而实现显示方式的修改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ps:Android4.2
首先介绍什么是SystemUI:
	对于Phone来说SystemUI指的是:StatusBar、NavigationBar.而对于平板或是TV来说SystemUI指的是CombineBar.
	SystemUI也就是我们Phone的信号、蓝牙、WIFI标志等等这些状态,当我们的设备开机后首先呈现给用户的就是各种界面(包括SystemUI)。

下面介绍SystemUI的启动流程:
	首先来看看SystemUI的代码结构,如下图:
    	
       在android4.2中,谷歌整合了phone和平板(TV)的SystemUI,也就是说可以根据设备的类型可以自动匹配相关的SystemUI。
	分析应用程序我们一般从AndroidManifest.xml开始,SystemUI也是如此,我们打开AndroidManifest,有如下相关代码:
	 
	
我们发现SystemUIService,他是在一开机就启动的服务。而SystemUIService是在SystemServer.java中真正启动的,如下代码:
	
	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.startServiceAsUser(intent, UserHandle.OWNER);
        }

	而这里的startSystemUi是在android系统启动过程中的ServerThread的run方法中调用的。在SystemServer中,初始化了Android系统中的Java层服务,如PowerManagerService、WindowManagerService等等,当然也包括了SystemUIService,它们通过ServiceManager的addService()方法,添加到ServiceManager的管理中。而我们要关注的就是StatusBarManagerService 代码如下:
	...
        StatusBarManagerService statusBar = null;
	...
	try {
                Slog.i(TAG, "Status Bar");
                statusBar = new StatusBarManagerService(context, wm);
                ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
            } catch (Throwable e) {
                reportWtf("starting StatusBarManagerService", e);
            }
	...
	try {
                Slog.i(TAG, "Notification Manager");
                notification = new NotificationManagerService(context, statusBar, lights);
                ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
                networkPolicy.bindNotificationManager(notification);
            } catch (Throwable e) {
                reportWtf("starting Notification Manager", e);
            }
	...
	既然到这里SystemUIService已经启动,那么我们就继续跟踪该Service吧。在SystemUIService的onCreate中:
  @Override
    public void onCreate() {
        // Tell the accessibility layer that this process will
        // run as the current user, i.e. run across users.
        AccessibilityManager.createAsSharedAcrossUsers(this);

        // Pick status bar or system bar.
        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
        try {
            SERVICES[0] = wm.hasSystemNavBar()
                    ? R.string.config_systemBarComponent
                    : R.string.config_statusBarComponent;
        } 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();
        }
    }
	在这段代码中,通过AIDL的方式获取了WindowManager的对象wm,并调用其方法hasSystemNavBar()来判断当前设备的类型,也就是说如果我们使用的Phone那么后续就会加载StatusBar和NivagationBar;而如果我们设备类型是Tablet(TV)之类的(可以在配置文档里面配置),就会加载CombiedBar。而
	对于平板 R.string.config_systemBarComponent  在config.xml中的值为:com.android.systemui.statusbar.tablet.TabletStatusBar ,我们继续跟踪,在TabletStatusBar中根据函数名我们可以判断在makeStatusBarView() 中对statusbar进行绘制。见代码:
    ........
    final TabletStatusBarView sb = (TabletStatusBarView)View.inflate( context, R.layout.system_bar, null);
	 mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
	.........
   	mNotificationArea = sb.findViewById(R.id.notificationArea);
	mBackButton = (ImageView)sb.findViewById(R.id.back);
        mNavigationArea = (ViewGroup) sb.findViewById(R.id.navigationArea);
        mHomeButton = mNavigationArea.findViewById(R.id.home);
        mMenuButton = mNavigationArea.findViewById(R.id.menu);
	mVolumeDownButton = mNavigationArea.findViewById(R.id.volume_down);
	mVolumeUpButton = mNavigationArea.findViewById(R.id.volume_up);
        mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
	......
由此可以看出状态栏所有相关的东东在这里都体现出来了。
	下面我们进入布局system_bar中看看:
<!-- notification icons & panel access -->
            <include layout="@layout/system_bar_notification_area" 
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:layout_marginTop="1dp"
                />
而在system_bar_notification_area中有:
 <LinearLayout
        android:id="@+id/notificationTrigger"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        >
        <com.android.systemui.statusbar.policy.Clock
            android:id="@+id/clock"
            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:singleLine="true"
            android:paddingLeft="6dip"
            android:layout_marginRight="8dip"
            android:gravity="center_vertical|left"
            />
	对此我们进入到com.android.systemui.statusbar.policy.Clock中进一步查看:
	
	final void updateClock() {
       		mCalendar.setTimeInMillis(System.currentTimeMillis());
	        setText(getSmallTime());
    	}
	private final CharSequence getSmallTime() {
        	Context context = getContext();
        	boolean b24 = DateFormat.is24HourFormat(context);
        	int res;
		 if (b24) {
        	    res = R.string.twenty_four_hour_time_format;
	        } else {
        	    res = R.string.twelve_hour_time_format;
        	}
		...
		String result = sdf.format(mCalendar.getTime());
		if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
	            int magic1 = result.indexOf(MAGIC1);
        	    int magic2 = result.indexOf(MAGIC2);
	            if (magic1 >= 0 && magic2 > magic1) {
        	        SpannableStringBuilder formatted = new SpannableStringBuilder(result);
                	if (AM_PM_STYLE == AM_PM_STYLE_GONE) {
	                    formatted.delete(magic1, magic2+1);
                } else {
                    if (AM_PM_STYLE == AM_PM_STYLE_SMALL) {
                        CharacterStyle style = new RelativeSizeSpan(0.7f);
                        formatted.setSpan(style, magic1, magic2,
                                          Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
                   	 }
                   	formatted.delete(magic2, magic2 + 1);
	                formatted.delete(magic1, magic1 + 1);
        	   }
 
                return formatted;
            }
        }
		return result;
	}
所以我们只要在getSmallTime中返回之前对其返回指进行处理即可达到我们的目地:比如修改显示方式等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值