精华内容
下载资源
问答
  • systemui

    千次阅读 2019-04-26 10:21:45
    ›一、SystemUI 概述 ›二、模块基本布局 ›三、模块内部框架 ›四、模块流程 五、重要文件的介绍 一、SystemUI 概述 1.Statusbar 的功能作用 1.1 状态栏的通知功能(包括时间,通知,系统状态等) 1.2...

     

    一、SystemUI 概述

    二、模块基本布局

    三、模块内部框架

    四、模块流程

    五、重要文件的介绍

     

     

    一、SystemUI 概述

    1.Statusbar 的功能作用

        1.1 状态栏的通知功能(包括时间,通知,系统状态等)

       1.2 状态栏的日期显示

    2.Statusbar 的使用方法

        2.1 notification 的使用

        2.2 系统图标的增加删除

     

    * notification 的使用

     

     

    Notification n = new Notification();  //实例化Notification       

    n.icon = R.drawable.icon; //设置状态栏显示图标

    n.tickerText = "Test Notifaction";  //设置显示提示信息

    n.when = System.currentTimeMillis(); //显示时间

    n.flags = Notification.FLAG_NO_CLEAR;  

    n.flags = Notification.FLAG_ONGOING_EVENT;   

    static final int ID = 1;

    NotificationManager nm =(NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);  

     

    Intent intent = new Intent(Main.this, Main.class);  

    PendingIntent pi = PendingIntent.getActivity(Main.this,0, intent, 0);  

    n.setLatestEventInfo(Main.this, "My Title","My Content", pi);  

    nm.notify(ID, n); //发出通知  

    nm.cancel(ID);   //取消通知

     

     

     

    如何区分“正在进行的”和“通知”,谁决定一个事件是“正在进行的”还是持续的“通知”?

    通过设置Notification的flag属性可以设定notification是正在进行的还是持续的notification。FLAG_INSISTENT和FLAG_ONGOING_EVENT标志位可以让Notification成为持续的或正在进行的Notification。

    正在进行的事件的通知:

    notification.flags =notification.flags | Notification.FLAG_ONGOING_EVENT;

    持续的Notification一直重复,直到用户取消:

    notification.flags =notification.flags | Notification.FLAG_INSISTENT;

     

    * 系统图标的增加删除

     

    状态栏添加显示的系统图标的步骤

    1.frameworks\base\core\res\res\drawalbe中添加系统图标的图片资源

    2.frameworks\base\core\res\res\values\config.xml 中添加图片引用,这些 icon 在这个stringarray的位置就决定了其在status bar 上显示的位置了。

    3.在 StatusbarPolicy.java 中初始化所增加的系统图标

    4.在构造函数中 SetIcon

    5.StatusBarPolicy 调用registerReceiver注册了感兴趣的 intent,当感兴趣的 intent 发生时,对图标进行更新

    6..添加图标更新函数

    删除时删除相关代码图片即可

     

    二、模块基本布局

     

    1.StatusBar的布局文件:frameworks/base/packages/SystemUI/res/layout/status_bar.xml

    2.LinearLayoutandroid:id="@+id/icons"我们看到的状态栏,系统默认是左边放通知图标 notificationIcons,右边放状态图标 statusIcons :

      --通知图标区域:IconMerger android:id="@+id/notificationIcons"

      --状态图标区域:LinearLayout android:id="@+id/statusIcons"

      --时间图标区域:com.android.systemui.statusbar.Clock

    3.LinearLayoutandroid:id="@+id/ticker"显示。在正常情况下ticker 是不显示的,只有在 StatusBarService收到通知时它才显示

    4.最后一个是DateView ,它是在点击statusbar时才显示的,默认是隐藏的

    5.StatusBar的下拉布局文件:frameworks/base/packages/SystemUI/res/layout/

    status_bar_expanded.xml

     

    三、模块内部框架

     

     

     

    Statusbar内部各种交互以及模块与其他应用的交互都是建立在StatusbarService之上的,其中包括Statusbar 视图的创建(包括 Statusbar 、 TrackingView和 StatusbarExpandedView),视图动画,系统图标(闹钟、 wifi 、SIM卡等)的加载和管理,其他应用通知信息的加载显示、更新、删除等,其他应用的远程接口控制(如当打电话时statusbar处于禁用状态的)对Android系统其他应用的通知信息(包括图标、 tracker 、notification的布局等)的处理。SIM 卡信息的控制等。

    总之StatusbarService是 Statusbar 的灵魂所在,是 Statusbar的核心,所有关于Statusbar 的操作处理都是建立在 StatusbarService 这个基础之上的。

    StatusbarService所在目录:\frameworks\base\packages\SystemUI\src\com\android\systemui\

    statusbar\StatusBarService.java

     

    四、 模块流程

     

     

    1.启动流程

       1.1 StatusbarService的启动流程

       1.2 系统图标初始化流程

    2.通知处理

    3.图标更新

       2.1 通过广播接收器的方式

       2.2 通过远程代理方式

    4.拖动刷新

    5.远程接口

     

    1.启动流程

     

    1.1 StatusbarService的启动流程

     

    1.当系统进程system_press启动之后,调用系统SystemServer.java,在SystemServer 中运行 ServerThread.run()方法时会注册 StatusBarManagerService:

    statusBar = newStatusBarManagerService(context);   

    ServiceManager.addService(Context.STATUS_BAR_SERVICE,statusBar);

    2.让后调用StatusBarManagerService的systemReady2() 方法,会在systemReady2() 方法中启动StatusbarService:

    ComponentName cn =ComponentName.unflattenFromString(mContext.getString(com.android.internal.R.string.config_statusBarComponent));  

    Intent intent = new Intent(); 

    intent.setComponent(cn);

    mContext.startService(intent); 

    3.在SystemUI模块的SystemUiApp.java的onCreate方法中也会startService,这是当Statusbar意外退出而导致StatusbarService停止服务时会重新启动StatusbarService

     

    1.2 系统图标初始化流程

     

    在启动StatusBarService后,StatusbarService会调用一个makeStatusBarView的方法,在里面将创建StatusBarView,

    在创建StatusbarView的过程中会加载系统图标。

    在启动StatusbarService的过程中会创建StatusBarPolicy的对象,StatusBarPolicy.java主要负责状态栏显示策略的管理(如状态栏的图标什么时候显示,在什么位置显示等)。StatusBarPolicy的构造函数中初始化了很多系统图标(如电池信息图标,闹钟图标,声音图标,信号栏图标等)。默认时有很多图标是不显示的,需要显示时再进行更新。

    以电池电量显示为例,大概关键步骤如下:

    1.通过BroadcastReceiver机制,StatusBarPolicy中注册的             mIntentReceiver收到BatteryService广播的   ACTION_BATTERY_CHANGED事件触发;

    2.调用updateBattery(intent)开始更新电池状态栏;

    3.从intent中解析需要的字段,调用StatusBarManager的setIcon();     (StatusBarManager是客户端使用的状态栏管理类)

    4.通过IBinder机制跨进程调用StatusBarManagerService的setIcon();     (StatusBarManagerService派生于IStatusBarService.Stub,是状态栏管理的服务端,是具体实现,StatusBarManagerService有一个mIcons成员,这个list成员在StatusBarManagerService创建时加载。StatusBarManagerService的setIcon()过程中,会又"battery"字段获得在mIcons中的索引,再由包名、图片id和等级创建StatusBarIcon实例,并将这个实例更新StatusBarIconList中所获得索引对应项)

    5.调用CommandQueue的setIcon();

    (CommandQueue派生于IStatusBar.Stub,有一个内部接口Callbacks,这个接口的实现就是StatusBarService。CommandQueue、StatusBarService和StatusBarManager属于同一个进程,而StatusBarManagerService是一个系统级服务,它们之间必然需要通过IBinder进程间通信。CommandQueue用于处理状态栏、通知相关的请求,内部维护了一个事件队列,setIcon()会创建一个OP_SET_ICON的massege,发送给Handler处理(CommandQueue内部也有一个StatusBarIconList实例,这个实例是由StatusBarService创建。在处理OP_SET_ICON的massege前,会先通过getViewIndex获得图标View的位置索引viewIndex,(因为有些图标有可能为空)再更新StatusBarIconList,最后调用Callbacks,也就是StatusBarService的addIcon()或者updateIcon());

    6.以addIcon()为例,StatusBarService的addIcon()会创建一个新的StatusBarIconView,将第步中所创建的StatusBarIcon实例设置进去,然后把这个view添加到LinearLayout的viewIndex位置。

    这样一个电池相关图标就在状态栏上添加或者更新了。

     

    2.通知处理

     

     

    在应用Activity中实现通知栏图标变化的程序中,是用NotificationManager对象mNotificationManager来发送通知。

    1.通知为Notification mNotification  对象,填充mNotification  的图标和消息内容以及一个when;

    2.然后构造了一个Intent对象intent,包含了本Activity对象的引用,以及本Activity的类名,一个PendingIntentpi对象,包含上述Intent对象以及本Activity对象的引用,是用于消息列表中显示本Activity项。

    3.点击时重新激活Activity,然后调用nm.setLatestEventInfo设置状态栏下拉列表项内容;

    4.最后调用nm.notify(1,n)方法来发送通知。

    接着改变状态栏的工作就由NotificationManager和StatusBarManagerService交互了。

     

     

     

    3.图标更新

       2.1 通过广播接收器的方式

     

    StatusBarPolicy调用registerReceiver注册了感兴趣的 intent, 当感兴趣的intent 发生时,对图标进行更新。例如,设置一个闹钟后,闹钟模块会发出一个叫做Intent.ACTION_ALARM_CHANGED 的广播,然后 StatusBarPolicy接收到此广播,继而更新状态栏上的闹钟图标。

    代码示例:

    // Alarm clockStatusBarPolicy构造方法中初始化闹钟图标

    mService.setIcon("alarm_clock",R.drawable.stat_notify_alarm,0);

    mService.setIconVisibility("alarm_clock",false);

    // StatusBarPolicy构造方法中注册闹钟改变广播

    filter.addAction(Intent.ACTION_ALARM_CHANGED);

    //改变闹钟图标

    private final void updateAlarm(Intentintent) {

    boolean alarmSet =intent.getBooleanExtra(“alarmSet”, false);

    mService.setIconVisibility(“alarm_clock”,alarmSet);

    }

     

       2.2 通过远程代理方式

     

     

    StatusBarManager有一个更新图标的方法: publicvoid updateIcon(IBinder key, String slot, int iconId, int iconLevel),不过StatusBarManager 并未把方法公开在 sdk 中,但是应该有方法可以访问的。

          public voidupdateIcon(IBinder key, String slot, int iconId, int iconLevel) {

                try {

                    mService.updateIcon(key, slot,mContext.getPackageName(), iconId,                                                                                 iconLevel);

                } catch (RemoteException ex) {

                           throw newRuntimeException(ex);

                }

          }

    mService 是StatusBarManager的一个成员变量,StatusBarManager 被构建的时候被赋值,他是 IStatusBar 的一个代理对象

         StatusBarManager(Contextcontext) {

               mContext = context;

               mService =IStatusBar.Stub.asInterface(

                     ServiceManager.getService(Context.STATUS_BAR_SERVICE));

         }

     

    4.拖动刷新

     

     

    从点击StatusBar会出现新的View,它的流程如下:

    StatusBarView 就是StatusBar 所代表的View,那么查看它的代码,看它处理点击的方法。

    它属性变量保存了StatusBarService的引用mService,它的点击处理函数onTouchEvent()和onInterceptTouchEvent()都会调用到StatusBarService类中的interceptTouchEvent()方法。

    当我们点击StatusBar 时,会先走到onInterceptTouchEvent()这个函数,而且这个函数只会在第一次走到,然后会走到onTouchEvent() 方法,这个方法每收到一个TouchEvent() 就会走到,因此会走到多次。

    函数onInterceptTouchEvent() 的处理:

    1 、调用到StatusBarService中的interceptTouchEvent() ,在这里又会走到event.getAction() == MotionEvent.ACTION_DOWN分支,在分支中,由于mExpanded == false 且y < hitSize会继续调用prepareTracking(y) 。

    2 、函数prepareTracking()处理:这里由于mExpanded == false所以会向H 中发送MSG_ANIMATE_REVEAL 消息,进入StatusBarService自己的消息循环。执行doRevealAnimation() 函数。

    3 、函数doRevealAnimation()处理:这个实现的功能很简单,就是在TrackingView( 就是点击时StatusBar 下出现的View)还没有完全显示出来的时候,通过动画的方式,一点一点的将TrackingView 显示出来。

    当我们手指离开时调用顺序如下:

    1 、StatusBarView :onTouchEvent(),此时Action != MotionEvent.ACTION_DOWN 走到 StatusBarService :interceptTouchEvent();

    2 、interceptTouchEvent() 中会走到分支elseif (mTracking) ;

    3 、由于ACTION_UP所以会调用performFling(),在这里会向Handler 发送 MSG_ANIMATE消息,然后进入函数doAnimation() 。

    4 、在doAnimation() 由于mAnimY <mStatusBarView.getHeight() 分支成立,会继续调用updateExpandedViewPos(0)和performCollapse();

    5 、在performCollapse()中,通过mTrackingView.setVisibility(View.GONE)实现了让mTrackingView的隐藏,其实这个函数还实现了其他的View 的隐藏,比如我们点击后进行拖动所出现的其他View 。

     

    5.远程接口

     

    StatusBarManagerService通过使用 IStatusBar 的 aidl调用CommandQueue 在 CommandQueue 中定义Callbacks

    StatusBarService实现了 CommandQueue 中 Callbacks的回调

    public interface Callbacks {

    public void addIcon(String slot, int index, intviewIndex, StatusBarIcon icon);

    public void updateIcon(String slot, int index, intviewIndex,

                                         StatusBarIcon old, StatusBarIcon icon);

    public void removeIcon(String slot, int index, intviewIndex);

    public void addNotification(IBinder key,StatusBarNotification notification);

    public void updateNotification(IBinder key,StatusBarNotification notification);

    public void removeNotification(IBinder key);

    public void disable(int state);

    public void animateExpand();

    public void animateExpandToggles(booleanneedForceStatusBar);

    public void animateCollapse();

    public void showSIMIndicator(String businessType);

    public void hideSIMIndicator();

    }

     

    五、重要文件的介绍

     

     

    1.StatusBarManagerService是服务端StatusBarService的管理者 

    2.StatusBarservice是Statusbar 的核心

    3.StatusBarPolicy负责状态栏显示的策略管理

    4.CommandQueue是StatusBarservice 和

       StatusBarManagerService 交互的枢纽

    StatusBarManagerService是服务端StatusBarService的管理者  

                     

     frameworks\base\services\java\com\android\server\

            StatusBarManagerService.java

    StatusBarManagerService是StatusBarService的管理者,是StatusBarService与外界通信的桥梁,在 StatusBarManagerService.java中,有 addNotification, removeNotification,updateNotification等方法用于管理传递给他的通知对象。这个类是一些管理方法,实际执行相关动作的是在IStatusBar.java里面,这个是framework/base/core/java/com /android/internal/statusbar/IStatusBar.aidl自动生成的用于IPC 的类。

    StatusBarservice是Statusbar 的核心

    \frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\StatusBarService.java

    StatusBarService这个服务是Statusbar模块的中心点,所有关于图标的加载、更新、删除等处理,与应用的交互,对通知信息的处理,动画的完成等都是建立在StatusBarService这个基础之上的。

    StatusBarPolicy负责状态栏显示的策略管理

    \frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\StatusBarPolicy.java

    Android中状态栏上有很多图标,这些图标什么时候显示什么时候不显示,这些都是StatusBarPolicy来管理的。StatusBarPolicy的构造函数里初始化了好几个图标,如闹钟icon,信号栏icon等。默认时有很多图标是不显示的,需要显示时再进行更新。StatusBarPolicy调用registerReceiver注册了感兴趣的intent,当感兴趣的intent发生时,对图标进行更新。StatusBarPolicy只是一个策略管理,实际的功能是StatusBarService来实现的。StatusBarService初始化时初始化了一个用于显示statusbar的StatusBarView。StatusBarView里面定义了icon名字,的显示顺序,对应的png图等,在StatusBarService调用makeStatusBarView方法时实现statusbar的初始化。

    CommandQueue是StatusBarservice 和

    StatusBarManagerService交互的枢纽

    \frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\

    CommandQueue.java

    IStatusBar.java里面对应的方法是用CommandQueue 的接口callback 的形式调用的,callback的实现在对应的服务提供类也就是StatusBarService.java中提供的。最终执行状态栏更新通知等事件都是在实现的CommandQueue.Callbacks里面执行。

     

     

     

    展开全文
  • SystemUI

    2018-01-24 13:40:31
    tag (android:excludeFromRecents="true"该属性用于控制activity不在最近列表...位于frameworks/base/packages/SystemUI,在SystemServer中通过startService来开启SystemUIService,在SystemUIService的onCreate方法中开
    tag (android:excludeFromRecents="true"该属性用于控制activity不在最近列表中显示。默认false。)


    SystemUI
    位于frameworks/base/packages/SystemUI,在SystemServer中通过startService来开启SystemUIService,在SystemUIService的onCreate方法中开启相关服务:
    @Override
        public void onCreate() {
            super.onCreate();
            ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        }
    具体都有哪些服务呢?查看SystemUIApplication的相关方法:
    /**
         * Makes sure that all the SystemUI services are running. If they are already running, this is a
         * no-op. This is needed to conditinally start all the services, as we only need to have it in
         * the main process.
         *
         * <p>This method must only be called from the main thread.</p>
         */
        public void startServicesIfNeeded() {
            if (mServicesStarted) {
                return;
            }


            if (!mBootCompleted) {
                // check to see if maybe it was already completed long before we began
                // see ActivityManagerService.finishBooting()
                if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
                    mBootCompleted = true;
                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
                }
            }


            Log.v(TAG, "Starting SystemUI services.");
            final int N = SERVICES.length;
            for (int i=0; i<N; i++) {
                Class<?> cl = SERVICES[i];
                if (DEBUG) 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 = mComponents;
                if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
                mServices[i].start();


                if (mBootCompleted) {
                    mServices[i].onBootCompleted();
                }
            }
            mServicesStarted = true;
        }




    在for循环中实例化相关服务,这些服务都已经定义在了SERVICES这个数组中:
    /**
         * The classes of the stuff to start.
         */
        private final Class<?>[] SERVICES = new Class[] {
                com.android.systemui.keyguard.KeyguardViewMediator.class,
                com.android.systemui.recent.Recents.class,
                com.android.systemui.volume.VolumeUI.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
        };
    可以看到包含但不限于:锁屏  最近打开列表   音量调节界面  系统状态栏  通知  电量  铃声等







    展开全文
  • 要求:修改SystemUI锁屏界面时间格式 Android P 上Sysyemui锁屏界面上的日期显示不在DateView处理了,使用KeyguardSliceProvider来处理,继承Contentprovide 之前Android O修改日期直接是在 SystemUI/src/...

    要求:修改SystemUI锁屏界面时间格式

    Android P 上Sysyemui锁屏界面上的日期显示不在DateView处理了,使用KeyguardSliceProvider来处理,继承Contentprovide

    之前Android O修改日期直接是在
    SystemUI/src/com/android/systemui/statusbar/policy/DateView.java

        public DateView(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs,
                    R.styleable.DateView,
                    0, 0);
    
            try {
                mDatePattern = a.getString(R.styleable.DateView_datePattern);
            } finally {
                a.recycle();
            }
            if (mDatePattern == null) {
                mDatePattern = getContext().getString(R.string.system_ui_date_pattern);
            }
    +
    +        String date_format = android.provider.Settings.System.getString(
    +                getContext().getContentResolver(),
    +                android.provider.Settings.System.DATE_FORMAT);
    +        
    +        if(!TextUtils.isEmpty(date_format)){
    +            mDatePattern = date_format;
    +        }
    +
        }
    

    Android P修改在SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java

         public boolean onCreateSliceProvider() {
             mAlarmManager = getContext().getSystemService(AlarmManager.class);
             mContentResolver = getContext().getContentResolver();
             mNextAlarmController = new NextAlarmControllerImpl(getContext());
             mNextAlarmController.addCallback(this);
             mZenModeController = new ZenModeControllerImpl(getContext(), mHandler);
             mZenModeController.addCallback(this);
             mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
    +
    +        String date_format = android.provider.Settings.System.getString(
    +                getContext().getContentResolver(),
    +                android.provider.Settings.System.DATE_FORMAT);
    +        
    +        if(!TextUtils.isEmpty(date_format)){
    +            mDatePattern = date_format;
    +        }
    +
             registerClockUpdate();
             updateClock();
             return true;
         }
    

    分析Anndroid P上处理方式

    接受到时间变化,或这个上面初始的时候,调用updateClock方法
        /**
         * Receiver responsible for time ticking and updating the date format.
         */
        @VisibleForTesting
        final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (Intent.ACTION_TIME_TICK.equals(action)
                        || Intent.ACTION_DATE_CHANGED.equals(action)
                        || Intent.ACTION_TIME_CHANGED.equals(action)
                        || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
                        || Intent.ACTION_LOCALE_CHANGED.equals(action)) {
                    if (Intent.ACTION_LOCALE_CHANGED.equals(action)
                            || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
                        // need to get a fresh date format
                        mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
                    }
                    mHandler.post(KeyguardSliceProvider.this::updateClock);
                }
            }
        };
        
    
    获取最新的时间显示,然后通知contentprovide更新显示。mLastText的值与Slice关联,现实的时候就跟新了。
        protected void updateClock() {
            final String text = getFormattedDate();
            if (!text.equals(mLastText)) {
                mLastText = text;
                mContentResolver.notifyChange(mSliceUri, null /* observer */);
            }
        }
    
        protected String getFormattedDate() {
            if (mDateFormat == null) {
                final Locale l = Locale.getDefault();
                DateFormat format;
                String country = getContext().getResources().getConfiguration().locale.getCountry();
                if (country.equals("XA")) {
                    format = DateFormat.getInstanceForSkeleton("eeeMMMd", l);
                }else{
                    format = DateFormat.getInstanceForSkeleton(mDatePattern, l);
                }
                format.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
                mDateFormat = format;
            }
            mCurrentTime.setTime(System.currentTimeMillis());
            return mDateFormat.format(mCurrentTime);
        }
    
        @Override
        public Slice onBindSlice(Uri sliceUri) {
            ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
            builder.addRow(new RowBuilder(builder, mDateUri).setTitle(mLastText));
            addNextAlarm(builder);
            addZenMode(builder);
            addPrimaryAction(builder);
            return builder.build();
        }
    
        protected void addPrimaryAction(ListBuilder builder) {
            // Add simple action because API requires it; Keyguard handles presenting
            // its own slices so this action + icon are actually never used.
            PendingIntent pi = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
            Icon icon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
            SliceAction action = new SliceAction(pi, icon, mLastText);
    
            RowBuilder primaryActionRow = new RowBuilder(builder, Uri.parse(KEYGUARD_ACTION_URI))
                .setPrimaryAction(action);
            builder.addRow(primaryActionRow);
        }
        
    
    展开全文
  • SystemUI 7.0学习总结一-SystemUI的启动

    千次阅读 2017-05-24 17:03:11
    最近在学习并接触SystemUI模块的工作,Keyguard做为引入库也纳入了SystemUI的大家庭,所以整体感觉SystemUI模块还是挺大的,为了日后的查阅还是要写一下笔记。笔记记录过程中参考了许多网友的文章,在本文最后的文章...

    最近在学习并接触SystemUI模块的工作,Keyguard做为引入库也纳入了SystemUI的大家庭,所以整体感觉SystemUI模块还是挺大的,为了日后的查阅还是要写一下笔记。笔记记录过程中参考了许多网友的文章,在本文最后的文章参考会一一罗列,在此非常感谢他们的分享。

    SystemUI概览

    SystemUI属于系统级的apk,位置在frameworks\base\packages\SystemUI,主要功能有:

    • 状态栏信息显示,比如电池,wifi信号,3G/4G等icon显示
    • 通知面板,比如系统消息,第三方应用消息
    • 近期任务栏显示面板,比如长按近期任务快捷键,显示近期使用的应用
    • 截图服务
    • 壁纸服务
    • ……

    SystemUI的启动流程

    SystemServer启动后,会在Main Thread启动ActivityManagerService,当ActivityManagerService systemReady后,会去启动SystemUIService。
    SystemServer路径:/base/services/java/com/android/server/SystemServer.java

        mActivityManagerService.systemReady(new Runnable() {
                @Override
                public void run() {
                    Slog.i(TAG, "Making services ready");
                    ......
                    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartSystemUI");
                    try {
                        startSystemUi(context);
                    } catch (Throwable e) {
                        reportWtf("starting System UI", e);
                    }
                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                    ......
                }            
             });

    在这个方法里启动一个SystemUIService服务,

    static final void startSystemUi(Context context) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.android.systemui",
                        "com.android.systemui.SystemUIService"));
            intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
            //Slog.d(TAG, "Starting service: " + intent);
            context.startServiceAsUser(intent, UserHandle.SYSTEM);
        }

    通过startServiceAsUser,SystemUIService就启动了,即SystemUI进程开机启动。

    public class SystemUIService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
            ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        }
        ......

    在SystemUIService的onCreate方法中会调用SystemUIApplication的startServicesIfNeeded方法,这个方法会调用 startServicesIfNeeded(SERVICES)方法启动一系列服务(并不是真正的service,都继承自SystemUI)。

    public class SystemUIApplication extends Application {
        ......
    
        /**
         * The classes of the stuff to start.
         */
        private final Class<?>[] SERVICES = new Class[] {
                com.android.systemui.tuner.TunerService.class,
                com.android.systemui.keyguard.KeyguardViewMediator.class,
                com.android.systemui.recents.Recents.class,
                com.android.systemui.volume.VolumeUI.class,
                Divider.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.keyboard.KeyboardUI.class,
                com.android.systemui.tv.pip.PipUI.class,
                com.android.systemui.shortcut.ShortcutKeyDispatcher.class,
                com.android.systemui.VendorServices.class
        };
    
        ......
    
        public void startServicesIfNeeded() {
            startServicesIfNeeded(SERVICES);
        }
    }

    startServicesIfNeeded方法会遍历SERVICES 这个数组,依次调用service的start方法启动服务。

    private void startServicesIfNeeded(Class<?>[] services) {
            if (mServicesStarted) {
                return;
            }
    
            if (!mBootCompleted) {
                // check to see if maybe it was already completed long before we began
                // see ActivityManagerService.finishBooting()
                if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
                    mBootCompleted = true;
                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
                }
            }
    
            Log.v(TAG, "Starting SystemUI services for user " +
                    Process.myUserHandle().getIdentifier() + ".");
            final int N = services.length;
            for (int i=0; i<N; i++) {
                Class<?> cl = services[i];
                if (DEBUG) Log.d(TAG, "loading: " + cl);
                try {
                    Object newService = SystemUIFactory.getInstance().createInstance(cl);
                    mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                } catch (InstantiationException ex) {
                    throw new RuntimeException(ex);
                }
    
                mServices[i].mContext = this;
                mServices[i].mComponents = mComponents;
                if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
                mServices[i].start();
    
                if (mBootCompleted) {
                    mServices[i].onBootCompleted();
                }
            }
            mServicesStarted = true;
        }

    看到这里,这么多文字可能不够直观,那就看看图吧,非常感谢参考文章中的分享。
    这里以SERVICES 中com.android.systemui.keyguard.KeyguardViewMediator.class为例,
    图一

    SystemUI Services启动后,根据各Services的功能,SystemUI的各个模块就开始正常工作起来了。

    参考文章

    1. http://blog.csdn.net/qq_31530015/article/details/53507968
    2. http://blog.csdn.net/zhudaozhuan/article/details/50817180
    3. http://blog.csdn.net/yj934672573/article/details/54571704
    4. http://blog.csdn.net/Picasso_L/article/details/69388919
    5. … …
    展开全文
  • [深入SystemUI]-了解SystemUI的大致架构

    千次阅读 2019-05-12 14:43:27
    这篇文章还是在于一位前辈的交流过程中汲取到的,之前也有看网上的关于SystemUI的内容,但是都没有从架构角度去琢磨SystemUI,我一位SystemUI小白就先在这里班门弄斧了,希望各位看官们抱着批评的...
  • Android 4.0 ICS SystemUI浅析——SystemUI启动流程

    万次阅读 多人点赞 2012-06-07 09:22:03
    本文只是对SystemUI分析的一个开始——启动流程的分析,网上有很多关于2.3的SystemUI的分析,可4.0与2.3的差别还是很大的,为了给自己留下笔记同时也方便大家学习和探讨,遂写此文,后续将有更多关于SystemUI的分析...
  • SystemUI模块总结

    千次阅读 2019-03-05 14:13:18
    SystemUI模块总结 1,SystemUI路径: SystemUI被放在 framework/base/packages/apps/SystemUI 在该目录的二级目录src/com/android下可看到SystemUI和Keyguard两个目录 SystemUI Keyguard 由此可见如今将锁屏界面...
  • android 6.0 SystemUI源码分析(1)-SystemUI介绍 转载 http://blog.csdn.net/zhudaozhuan/article/details/50816086 1. SystemUI介绍 SystemUI是一个系统应用,主要功能有: 1)状态栏信息显示,比如...
  • SystemUI架构分析

    万次阅读 多人点赞 2017-02-10 17:49:21
    SystemUI架构分析SystemUI架构分析 前言 1SystemUI介绍 1SystemUI摘要 2什么是SystemUI 2SystemUI的启动过程 3SystemUI的SERVICES 1音量控制 11音量控制简介 12音量控制SERVICE的初始化 13控制音量过程 2...
  • SystemUI 剖析

    千次阅读 2017-10-08 10:10:58
    序言17年上半年主要做车机项目SystemUI的工作,一般的来说可以选择在源码的基础上定制,也可以重新编写。具体选择哪种方案,也要根据自身项目的需求和工作量来考虑,但是不管选择哪种,都需要对SystemUI源码有一定的...
  • 1.SystemUI启动 SystemUI是核心系统应用,需要开机启动,启动SystemUI进程,是通过启动SystemUIService来实现的。 frameworks\base\services\java\com\android\server\SystemServer.java SystemServer启动后...
  • System UI 学习之一:system ui启动流程

    千次阅读 2013-07-16 11:46:15
    本文只是对SystemUI分析的一个开始——启动流程的分析,网上有很多关于2.3的SystemUI的分析,可4.0与2.3的差别还是很大的,为了给自己留下笔记同时也方便大家学习和探讨,遂写此文,后续将有更多关于SystemUI的分析...
  • Android SystemUI 架构详解

    千次阅读 2019-12-25 19:36:47
    Android SystemUI 架构详解 本文描述Android系统中一个核心应用SystemUI,详细赘述SystemUI中几大模块功能的实现过程。由于作者水平有限,如发现本文中错误的地方,欢迎指正。 1、SystemUI介绍 1.1、SystemUI...
  • SystemUI锁屏流程

    千次阅读 2019-07-09 11:44:16
    SystemUI启动的时候启动各个SERVICE,这些Service不是四大组件的service,这个SERVICE继承SystemUI,实现了start()和onBootComplete方法.其中StatusBar加载了SystemUI几乎全部的界面,其中包括锁屏界面, 其中Bouncer是...
  • SystemUI 布局

    千次阅读 2017-04-10 19:45:09
    frameworks\base\packages\SystemUI 代码构成: 一、布局详细介绍布局特点: 1、FrameLayout,自定义控件 的大量使用 2、布局层级分布,高度细化 3、状态繁多statusBar 状态栏界面 布局文件 status_bar.xml ...
  • 前言SystemUI功能介绍SystemUI主要视图 PhoneStatusBarViewPanelHolderkeyguard_bouncer 总结 前言 Android ROM开发过程中,难免会涉及到对SystemUI的修改,之前做过一些这方面的工作,现在整理下,准备按照...
  • System UI 调试方法

    千次阅读 2014-12-04 10:29:15
    工作需要想了解下SystemUi的启动流程,所以需要调试下SystemUI,这样比较高效: 1、SyStemUI是随系统启动的,所以我们先要在系统启动的时候把SystemUI的启动关掉,这个在SystemServer里面,可以...
  • SystemUI之功能介绍和UI布局实现

    万次阅读 2018-03-16 15:09:47
    SystemUI功能介绍 SystemUI主要视图 PhoneStatusBarView PanelHolder keyguard_bouncer 总结 前言 Android ROM开发过程中,难免会涉及到对SystemUI的修改,之前做过一些这方面的工作,现在整理下,准备...
  • SystemUI作为系统应用,在开机的时候就会开始加载启动,今天来学习一下它的启动流程。 SystemServer.java (frameworks\base\services\java\com\android\server) 1.最开始会调用SystemServer里面的...
  • android SystemUI浅析之SystemUI启动流程

    千次阅读 2013-08-12 15:54:41
    前言:最近在研究4.2的status bar 和navigation bar,想做一下总结,后来碰到一篇文章分享一下,至于4.2上的变化以及4.2上的...我们知道Android 4.0以后SystemUI同时适用于Phone和Tablet(TV),因此,对于Phone来说Syst
  • 前言SystemUI功能介绍SystemUI主要视图 PhoneStatusBarViewPanelHolderkeyguard_bouncer 总结 前言 Android ROM开发过程中,难免会涉及到对SystemUI的修改,之前做过一些这方面的工作,现在整理下...
  • SystemUI概述 自android2.2开始,原本存在与framework-res.apk中的状态栏和下拉通知栏界面控制被分割出一个单独的apk文件,命名为SystemUI.apk,保存在System/priv-app/SystemUI/文件夹中。在SystemUI.apk中,存在着状态...
  • SystemUI是android系统中的部分系统组件,以一个apk的形式存在,功能主要包括锁屏、任务管理、下拉通知栏、状态栏等。SystemUI虽然是一个apk,但是编译依赖源码环境,系列文章是将SystemUI拆分出来,最终可以在...
  • AndroidQ SystemUI之启动

    2020-02-20 16:34:31
    从本篇开始准备写一下关于SystemUI相关的东西,SystemUI包含的东西挺多的,顶部的StatusBar,中间的Lockscreen,底部的NavigationBar等等,可以说SystemUI就是一台手机的门面,是用户对手机系统的第一印象,非常重要...
  • android systemui

    千次阅读 2012-11-07 17:14:26
    本文只是对SystemUI分析的一个开始——启动流程的分析,网上有很多关于2.3的SystemUI的分析,可4.0与2.3的差别还是很大的,为了给自己留下笔记同时也方便大家学习和探讨,遂写此文,后续将有更多关于SystemUI的分析...
  • 5.0SystemUI布局

    2016-04-27 15:23:15
    Android5.0SystemUI作了很大的改动。手机中的下拉状态栏,锁屏,通知以及最近打开任务列表等功能都是SystemUI实现的。 1,Notification 和 Quick Settings 被合并在一个界面中 2,KeyGuard和SystemUI联系更紧密了...
  • SystemUI常见问题修改方法

    千次阅读 2019-05-09 18:03:24
    AndroidO,AndroidP SystemUI问题修改笔记 修改NavigationBar ‘back’ 触控范围 SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java @VisibleForTesting NearestTouchFrame...
  • Android systemUI移植

    千次阅读 2016-12-19 15:50:54
    SystemUI 在Android4.3或以前版本,SystemUI是分为Tablet和Phone两种不同代码文件的,在Android4.4已经整合了phone和tablet,统一为phone,只区分phone和tv。对于Phone来说SystemUI指的是:StatusBar(状态栏)、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 43,434
精华内容 17,373
关键字:

systemui