Android16在状态栏顶部新增图标(SystemUI)

一、新增图标资源

复制代码
我这边是新增一个显示mic被禁用的图标:
路径:
bash 复制代码
framework/base/core/res/res/drawable-nodpi/ic_mic_off.xml

首先在上面路径下新增下面我们的图标文件

xml 复制代码
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="?attr/colorControlNormal">
  <path
      android:fillColor="@android:color/white"
      android:pathData="M11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v5.17l1.82,1.82c0.11,-0.31 0.18,-0.64 0.18,-0.99V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v1.17l2,2V5zM2.81,2.81L1.39,4.22l11.65,11.65c-0.33,0.08 -0.68,0.13 -1.04,0.13 -2.76,0 -5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c0.57,-0.08 1.12,-0.24 1.64,-0.46l5.14,5.14 1.41,-1.41L2.81,2.81zM19,11h-2c0,0.91 -0.26,1.75 -0.69,2.48l1.46,1.46C18.54,13.82 19,12.47 19,11z"/>
</vector>

然后在下面的路径添加我们的占位符,即我们图标的相应键值:

bash 复制代码
framework/base/core/res/res/values/config.xml

string-array name="config_statusBarIcons">下添加我们的占位符status_bar_no_mic

xml 复制代码
<string-array name="config_statusBarIcons">
        <item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_call_strength</xliff:g></item>
        <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>
        <item><xliff:g id="id">@string/status_bar_nfc</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_tty</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_speakerphone</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_cdma_eri</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_data_connection</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_secure</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_connected_display</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_vpn</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_location</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_mute</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_volume</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_zen</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_screen_record</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_ethernet</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_oem_satellite</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_wifi</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_no_mic</xliff:g></item>          ----------这里是我们的
        <item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_stacked_mobile</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
        <item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
    </string-array>

相应的需要添加上string资源:

xml 复制代码
<string translatable="false" name="status_bar_no_mic">NoMic</string>   ----这里是我们的
    <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>
    <string translatable="false" name="status_bar_cast">cast</string>
    <string translatable="false" name="status_bar_connected_display">connected_display</string>
    <string translatable="false" name="status_bar_hotspot">hotspot</string>
    <string translatable="false" name="status_bar_location">location</string>
    <string translatable="false" name="status_bar_bluetooth">bluetooth</string>
    <string translatable="false" name="status_bar_nfc">nfc</string>
    <string translatable="false" name="status_bar_tty">tty</string>
    <string translatable="false" name="status_bar_speakerphone">speakerphone</string>
    <string translatable="false" name="status_bar_zen">zen</string>
    <string translatable="false" name="status_bar_mute">mute</string>
    <string translatable="false" name="status_bar_volume">volume</string>
    <string translatable="false" name="status_bar_wifi">wifi</string>
    <string translatable="false" name="status_bar_cdma_eri">cdma_eri</string>
    <string translatable="false" name="status_bar_data_connection">data_connection</string>
    <string translatable="false" name="status_bar_phone_evdo_signal">phone_evdo_signal</string>
    <string translatable="false" name="status_bar_phone_signal">phone_signal</string>
    <string translatable="false" name="status_bar_battery">battery</string>
    <string translatable="false" name="status_bar_alarm_clock">alarm_clock</string>
    <string translatable="false" name="status_bar_secure">secure</string>
    <string translatable="false" name="status_bar_clock">clock</string>
    <string translatable="false" name="status_bar_mobile">mobile</string>
    <string translatable="false" name="status_bar_stacked_mobile">stacked_mobile</string>
    <string translatable="false" name="status_bar_vpn">vpn</string>
    <string translatable="false" name="status_bar_ethernet">ethernet</string>
    <string translatable="false" name="status_bar_microphone">microphone</string>
    <string translatable="false" name="status_bar_camera">camera</string>
    <string translatable="false" name="status_bar_airplane">airplane</string>
    <string translatable="false" name="status_bar_no_calling">no_calling</string>
    <string translatable="false" name="status_bar_call_strength">call_strength</string>

然后在framework/base/core/res/res/values/symbols.xml里面添加我们定义的图标和占位资源:

xml 复制代码
<java-symbol type="drawable" name="ic_mic" />
<java-symbol type="string" name="status_bar_no_mic" />

二、修改framework

下面我们需要修改的文件路径为:

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java

状态栏上许多系统图标(如静音、闹钟、蓝牙等)的策略控制,都集中在 PhoneStatusBarPolicy.java 中。

java 复制代码
private final String mNoMic;  //定义占位值---接收我们前面定义的status_bar_no_mic
private boolean mNoMicVisible;

在构造函数中赋值:

java 复制代码
@Inject
    public PhoneStatusBarPolicy(StatusBarIconController iconController,
            CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
            @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
            @Main Resources resources,
            HotspotController hotspotController, BluetoothController bluetoothController,
            NextAlarmController nextAlarmController, UserInfoController userInfoController,
            RotationLockController rotationLockController, DataSaverController dataSaverController,
            ZenModeController zenModeController,
            DeviceProvisionedController deviceProvisionedController,
            KeyguardStateController keyguardStateController,
            LocationController locationController,
            SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
            UserManager userManager, UserTracker userTracker,
            DevicePolicyManager devicePolicyManager,
            @Nullable TelecomManager telecomManager, @DisplayId int displayId,
            @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
            RingerModeTracker ringerModeTracker,
            PrivacyItemController privacyItemController,
            PrivacyLogger privacyLogger,
            ConnectedDisplayInteractor connectedDisplayInteractor,
            ZenModeInteractor zenModeInteractor,
            JavaAdapter javaAdapter
    ) {
        //.......其他代码
        mNoMic = resources.getString(com.android.internal.R.string.status_bar_no_mic); //赋值我们的占位
        mNoMicVisible = false; //初始化状态控制变量---
    }

在init中实现我们的逻辑:禁用麦克风的时候状态栏显示出禁用麦克风的图标,麦克风可用的时候不显示图标

java 复制代码
/** Initialize the object after construction. */
    public void init() {
        // listen for broadcasts
        IntentFilter filter = new IntentFilter();
        //........其他代码
	mIconController.setIcon(mNoMic,com.android.internal.R.drawable.ic_mic_off,null);//把我们的图标和定义的占位联系起来
        IntentFilter micfilter = new IntentFilter();
        micfilter.addAction(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED);//接受mic可用状态变化广播
        BroadcastReceiver mMicMuteReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                updateTestIconVisibility();//更新显示状态
            }
        };
        mBroadcastDispatcher.registerReceiverWithHandler(mMicMuteReceiver, micfilter, mHandler);//注册广播
        updateTestIconVisibility();
    }

    private void updateTestIconVisibility(){
        boolean isMuted = AudioSystem.isMicrophoneMuted();//获取当前mic是否禁用,返回ture代表被禁用,false代表可用
        mNoMicVisible = isMuted;
        mIconController.setIconVisibility(mNoMic,mNoMicVisible);//设置图标是否显示
        //----这里其实我们的占位符其实就是我们的图标以及其他属性的一个唯一键值。
    }

完成效果

SystemUI相关的修改需要在实战中积累经验💪

相关推荐
古法安卓1 小时前
Android-Fork 机制详解
android·java·android studio
Android打工仔2 小时前
不要在 Data 层随意把 Cold Flow 转换成 Hot Flow
android·架构·kotlin
峥嵘life2 小时前
2026免费的 opencode 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言
杉氧3 小时前
拒绝重复造轮子:我写了一个生产级的 Kotlin 协程与 Flow 工具库(CoroutineKit)
android·kotlin·workflow
恋猫de小郭3 小时前
Flutter GSoC 2026 提案进度解读,补上 DevTools、FFI 和原生平台的关键缺口
android·前端·flutter
2501_915909063 小时前
怎么用 FlutterFlow 把应用发布到 App Store?
android·ios·小程序·https·uni-app·iphone·webview
峥嵘life3 小时前
2026华为AI码道 CodeArts 使用分享:Windows端 + 服务器CLI 实战总结
android·大数据·开发语言·python
yxlalm4 小时前
对话记忆持久化-Redis热与MySQL冷
android·redis·mysql
1570925113413 小时前
Android进阶之光:HTTP协议原理深度解析
android·网络协议·http