隐藏状态栏icon闹钟的显示

设置闹钟后在状态栏ICON区域会显示一个闹钟小图标,我们实现设置闹钟后让它不显示。

参考博客:

通过SystemUi的加载流程,我们知道有这么一个方法makeStatusBarView(result)

是创建状态栏的,找到如下代码

android 显示桌面角标 安卓手机图标显示_android 显示桌面角标


这里的代码主要实现了:

  1. 使用 CollapsedStatusBarFragment 替换 status_bar_container(状态栏通知显示区域, status_bar_container在xml文件super_status_bar.xml文件中)
  2. statusBarFragment.initNotificationIconArea(mNotificationIconAreaController) 初始化通知栏区域
  3. mStatusBarView.setBar(this) 传递statusBar处理下拉事件和mStatusBarView.setPanel(mNotificationPanel) 传递 NotificationPanelView 显示下拉UI控制

看CollapsedStatusBarFragment

在视图创建后,需要创建图标,下面这里是status_icon的创建,也就是CollapsedStatusBarFragment 类

CollapsedStatusBarFragment的onCreateView方法:

android 显示桌面角标 安卓手机图标显示_android 显示桌面角标_02


下面是视图的创建,将status_bar.xml显示创建视图到CollasedStatusBarFragment中

我们先聚集在system_icon_area区域,就是显示蓝牙、wifi、VPN、网卡icon那块区域:

@Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mStatusBar = (PhoneStatusBarView) view;
        if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
            mStatusBar.restoreHierarchyState(
                    savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
        }
        .......
        mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons),
                Dependency.get(CommandQueue.class));
        mDarkIconManager.setShouldLog(true);
        Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
        mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
        mClockView = mStatusBar.findViewById(R.id.clock);
        showSystemIconArea(false);
        showClock(false);
        initEmergencyCryptkeeperText();
        initOperatorName();
    }

我们发现了这几行代码:
1、mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons),
Dependency.get(CommandQueue.class)); //R.id.statusIcons即是system_icons.xml里面的控件。

system_icons.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/system_icons"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical">

    <com.android.systemui.statusbar.phone.StatusIconContainer
        android:id="@+id/statusIcons"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:paddingEnd="@dimen/signal_cluster_battery_padding"
        android:gravity="center_vertical"
        android:orientation="horizontal"/>

    <com.android.systemui.BatteryMeterView android:id="@+id/battery"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:clipToPadding="false"
        android:clipChildren="false"
        systemui:textAppearance="@style/TextAppearance.StatusBar.Clock" />
</LinearLayout>

2、Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager); //进入其实现类StatusBarIconControllerImpl.java,在其构造函数中我们找到了实现

public StatusBarIconControllerImpl(Context context) {
        super(context.getResources().getStringArray(
                com.android.internal.R.array.config_statusBarIcons));

我们可以发现状态栏icon加载的图标来源于framework/base/core/res/res/values/config.xml文件
在这里我们就找到了index和slot的出处,原来在初始化的时候就已经定义好了所有的slots,然后从framework中加载出来,index就是string-array中的顺序。

<string-array name="config_statusBarIcons">
        <item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_rotate</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_headset</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_data_saver</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_ime</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_sync_failing</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_sync_active</xliff:g></item>
        ................
    </string-array>
    
    <string translatable="false" name="status_bar_rotate">rotate</string>
    <string translatable="false" name="status_bar_headset">headset</string>
    <string translatable="false" name="status_bar_data_saver">data_saver</string>
    <string translatable="false" name="status_bar_managed_profile">managed_profile</string>
    <string translatable="false" name="status_bar_ime">ime</string>
    <string translatable="false" name="status_bar_sync_failing">sync_failing</string>
    <string translatable="false" name="status_bar_sync_active">sync_active</string>
  .......

然后是StatusBarIconControllerImpl.java这个控制器来控制icon的加载显示和移除。
由PhoneStatusBarPolicy.java类来负责调用执行:
有2种方式实现对ICON的控制显示和隐藏
1、首先类本身实现了大量的回调接口,通过重写这些接口类的方法,会在触发的时候被回调,然后更新ICON显示和隐藏

public class PhoneStatusBarPolicy
        implements BluetoothController.Callback,
                CommandQueue.Callbacks,
                RotationLockControllerCallback,
                Listener,
                ZenModeController.Callback,
                DeviceProvisionedListener,
                KeyguardStateController.Callback,
                LocationController.LocationChangeCallback,
                RecordingController.RecordingStateChangeCallback,
                TrainController.Callback{
                ...

2、在初始化的时候又注册了大量的监听,能够监听广播进行调节改变显示

public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
        mContext = context;
        //  初始化headset的slot
        mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
 
        // listen for broadcasts
        IntentFilter filter = new IntentFilter();
        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
        filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
        //  注册headset状态变化的action
        filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
        filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);

依靠监听和回调机制,可以用来控制状态栏icon图标的显示、隐藏。在PhoneStatusBarPolicy.java中来实现,下面我们以闹钟为例,我们不希望设置闹钟之后状态栏显示闹钟icon。每个icon对应一个updatexxx(),我们找到关于闹钟的updateAlarm()

private void updateAlarm() {
        final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
        final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
        int zen = mZenController.getZen();
        final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
        mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
                : R.drawable.stat_sys_alarm, buildAlarmContentDescription());
        //mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
        //jiaxian.zhang 直接修改为false
        mIconController.setIconVisibility(mSlotAlarmClock, false);
    }

修改后push到手机发现成功实现!