Android11 Settings启动流程,Android 11 Settings启动流程解析

马肤

温馨提示:这篇文章已超过414天没有更新,请注意相关的内容是否还可用!

摘要:Android 11的Settings启动流程包括用户启动Settings应用、系统调用相关组件、加载配置和界面、执行用户操作等步骤。该流程涉及系统底层组件的初始化、用户界面的渲染以及用户操作的响应。整体流程优化可提高启动速度,提升用户体验。

一、系统设置首页(一级菜单):

1、Settings

之所以要在此定义空的Activity,是为了外部应用能直接跳转到XX_SettingsActivity界面,因为如果只是fragment的话,外部是没法跳转到fragment界面的,跳转到XX_SettingsActivity时,会执行其父类SettingsActivity.java中的方法,并根据XX_SettingsActivity在清单文件中的注册信息, 它的meta-data的值,找到XX_SettingsActivity对应的fragment(XX_Settings),显示出fragment界面,实现借壳。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第1张

2、AndroidManifest.xml

Settings主界面Activity使用的是Settings.java,子界面Activity使用的是SubSettings.java,Settings与SubSetting中的内部类都是空Activity(没有重写七大生命周期方法),都继承于SettingsActivity.

从AndroidManifest.xml文件中得知主页面是.homepage.SettingsHomepageActivity。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第2张

以WifiSettings为例

Android11 Settings启动流程,Android 11 Settings启动流程解析 第3张

3、SettingsHomepageActivity

①onCreate

Android11 Settings启动流程,Android 11 Settings启动流程解析 第4张

②showFragment

封装方法中进行了加载fragment的实现

Android11 Settings启动流程,Android 11 Settings启动流程解析 第5张

4、TopLevelSettings

TopLevelSettings继承自抽象类DashboardFragment, 实现抽象方法getPreferenceScreenResId()并返回preference的配置文件即可完成静态配置。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第6张

TopLevelSettings类中还有一个比较重要的就是在onAttach()方法中调用了父类DashboardFragment的onAttach()方法,这个方法主要是加载preference controllers。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第7张

5、top_level_settings.xml

主标签是一个标签,里有多个标签。每个标签对应设置首页的每一个设置项。

key

配置项的主键

title

配置项的标题

summary

要标题下面的文字

icon

前面的图标

order

用来做排序的,值越小则排行越靠前

fragment

点击该item要跳转的界面

controller

该item的控制器,控制它的内容展示,是否可用,也可以控制它的点击事件等。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第8张

5、DashboardFragment

①onCreatePreferences

Android11 Settings启动流程,Android 11 Settings启动流程解析 第9张

②refreshAllPreferences

Android11 Settings启动流程,Android 11 Settings启动流程解析 第10张

③displayResourceTiles

addPreferencesFromResource方法是将preferenceScreen下所有Preference添加到ArrayList中,然后再根据此集合构建生成PreferenceGroupAdapter,最后将此adapter设置到listview中,完成数据绑定,从而完成界面加载。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第11张

④refreshDashboardTiles

Android11 Settings启动流程,Android 11 Settings启动流程解析 第12张

⑤onAttach

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mSuppressInjectedTileKeys = Arrays.asList(context.getResources().getStringArray(
                R.array.config_suppress_injected_tile_keys));
        mDashboardFeatureProvider = FeatureFactory.getFactory(context).
                getDashboardFeatureProvider(context);
        // Load preference controllers from code
        //从代码加载首选项控制器
        final List controllersFromCode =
                createPreferenceControllers(context);
        // Load preference controllers from xml definition
        //从 xml 定义加载首选项控制器
        final List controllersFromXml = PreferenceControllerListHelper
                .getPreferenceControllersFromXml(context, getPreferenceScreenResId());
        // Filter xml-based controllers in case a similar controller is created from code already.
        //过滤基于 xml 的控制器,以防已经从代码创建了类似的控制器。
        final List uniqueControllerFromXml =
                PreferenceControllerListHelper.filterControllers(
                        controllersFromXml, controllersFromCode);
        // Add unique controllers to list.
        //将唯一的控制器添加到列表中
        if (controllersFromCode != null) {
            mControllers.addAll(controllersFromCode);
        }
        mControllers.addAll(uniqueControllerFromXml);
        // And wire up with lifecycle.
        //并与生命周期联系起来。
        final Lifecycle lifecycle = getSettingsLifecycle();
        uniqueControllerFromXml.forEach(controller -> {
            if (controller instanceof LifecycleObserver) {
                lifecycle.addObserver((LifecycleObserver) controller);
            }
        });
        // Set metrics category for BasePreferenceController.
        //为 BasePreferenceController 设置指标类别。
        final int metricCategory = getMetricsCategory();
        mControllers.forEach(controller -> {
            if (controller instanceof BasePreferenceController) {
                ((BasePreferenceController) controller).setMetricsCategory(metricCategory);
            }
        });
        mPlaceholderPreferenceController =
                new DashboardTilePlaceholderPreferenceController(context);
        mControllers.add(mPlaceholderPreferenceController);
        for (AbstractPreferenceController controller : mControllers) {
            addPreferenceController(controller);
        }
    }

二、系统设置二级菜单实现

1、SubSettings

系统设置的二级菜单界面Activity是SubSettings类,SubSettings类虽然是一个Activity但是它是一个空的Activity,它不继承Activity7大生命周期。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第13张

2、SettingsActivity

①onCreate

Android11 Settings启动流程,Android 11 Settings启动流程解析 第14张

布局文件:settings_main_prefs

Android11 Settings启动流程,Android 11 Settings启动流程解析 第15张

启动Fragment

Android11 Settings启动流程,Android 11 Settings启动流程解析 第16张

②getMetaData

Android11 Settings启动流程,Android 11 Settings启动流程解析 第17张

以WifiSettingsActivity为例

Android11 Settings启动流程,Android 11 Settings启动流程解析 第18张

③getIntent

Android11 Settings启动流程,Android 11 Settings启动流程解析 第19张

④getStartingFragmentClass

Android11 Settings启动流程,Android 11 Settings启动流程解析 第20张

⑤launchSettingFragment

Android11 Settings启动流程,Android 11 Settings启动流程解析 第21张

⑥switchToFragment

Android11 Settings启动流程,Android 11 Settings启动流程解析 第22张

3、settings_main_prefs.xml

布局文件由和和标签组成,标签默认是隐藏的。根据标签的id可以判断这个标签就是二级菜单栏的主界面内容。

Android11 Settings启动流程,Android 11 Settings启动流程解析 第23张

 三、加载默认亮度

1、top_level_settings.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第24张

2、AndroidManifest.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第25张

3、DisplaySettings

①getPreferenceScreenResId

Android11 Settings启动流程,Android 11 Settings启动流程解析 第26张

②buildPreferenceControllers

Android11 Settings启动流程,Android 11 Settings启动流程解析 第27张

4、display_settings.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第28张

5、AutoBrightnessPreferenceController

Android11 Settings启动流程,Android 11 Settings启动流程解析 第29张

6、BrightnessLevelPreferenceController

①getCurrentBrightness

Android11 Settings启动流程,Android 11 Settings启动流程解析 第30张

②convertLinearToGammaFloat

Android11 Settings启动流程,Android 11 Settings启动流程解析 第31张

7、 vendor\XXX\trunk\etc\settings-config.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第32张

8、/data/system/users/0/settings_system.xml

 

四、字体调节

1、display_settings

Android11 Settings启动流程,Android 11 Settings启动流程解析 第33张

2、FontSizePreferenceController

Android11 Settings启动流程,Android 11 Settings启动流程解析 第34张

3、ToggleFontSizePreferenceFragment

Android11 Settings启动流程,Android 11 Settings启动流程解析 第35张

4、values-zh-rCN/arrays.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第36张

5、arrays.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第37张

6、\vendor\XXX\trunk\etc\settings-config.xml

 

五、屏幕超时

1、TimeoutPreferenceController

Android11 Settings启动流程,Android 11 Settings启动流程解析 第38张

2、arrays.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第39张

3、\vendor\XXX\trunk\etc\settings-config.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第40张

六,显示实时电量

1、top_level_settings.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第41张

2、AndroidManifest.xml

Android11 Settings启动流程,Android 11 Settings启动流程解析 第42张

3、TopLevelBatteryPreferenceController

配置项中配置了TopLevelBatteryPreferenceController控制器,它继承自AbstractPreferenceController,这个抽象类用于对所有菜单项进行统一管理(例如展示或隐藏,监听点击事件等)。

public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
        LifecycleObserver, OnStart, OnStop {
    // 电量改变广播
    private final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
    // 当前配置项
    private Preference mPreference;
    // 电量信息
    private BatteryInfo mBatteryInfo;
    //初始化电量改变广播
    public TopLevelBatteryPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
        mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
            BatteryInfo.getBatteryInfo(mContext, info -> {
                mBatteryInfo = info;
                updateState(mPreference);
            }, true /* shortString */);
        });
    }
    // 控制该项是否可用
    @Override
    public int getAvailabilityStatus() {
        return mContext.getResources().getBoolean(R.bool.config_show_top_level_battery)
                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
    }
    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        // 获取当前的配置项
        mPreference = screen.findPreference(getPreferenceKey());
    }
    @Override
    public void onStart() {
        // 注册广播
        mBatteryBroadcastReceiver.register();
    }
    @Override
    public void onStop() {
        // 取消注册广播
        mBatteryBroadcastReceiver.unRegister();
    }
    @Override
    public CharSequence getSummary() {
        // 返回电量概览
        return getDashboardLabel(mContext, mBatteryInfo);
    }
    // 获取电量信息
    static CharSequence getDashboardLabel(Context context, BatteryInfo info) {
        if (info == null || context == null) {
            return null;
        }
        CharSequence label;
        if (!info.discharging && info.chargeLabel != null) {
            label = info.chargeLabel;
        } else if (info.remainingLabel == null) {
            label = info.batteryPercentString;
        } else {
            label = context.getString(R.string.power_remaining_settings_home_page,
                    info.batteryPercentString,
                    info.remainingLabel);
        }
        return label;
    }
}

4、总结

  1. 在构造方法中初始化电量改变广播
  2. 在onStart()和onStop()中注册和取消注册广播
  3. 一旦收到电量改变广播,则把电量信息保存在mBatteryInfo中
  4. 然后执行updateState(),该方法会调用getSummary()把信息设置给当前配置项
  5. getSummary()中将mBatteryInfo保存的电量信息解析出来

七、系统提供者

Android的系统设置数据存放在/data/data/com.android.providers.settings/databases/settings.db 中

是否有默认值

在寻找一个开关的默认值时,首先要明白一点,该开关是否存在默认值,以及该开关状态是否有状态保存(一般状态存储在settings的db中)。 判断条件: 在reboot(重启)之后开关状态仍旧保存或者是在reset(恢复出厂设置)之后开关状态恢复到默认的,才能找到默认值

在reboot之后开关状态仍旧保存的,表示状态存储在了db中。 在reset之后开关状态恢复默认的,表示状态有一个默认值。

比如像wiif开关,蓝牙开关,gps开关等,都有默认值,并且状态值都在db中保存。

至于像WiFi热点开关这种在reboot之后,状态没有保存,那么你就别白费力气来找他的默认值或者状态存储值了

修改默认值

大部分的开关状态都存储在了SettingProvider的db中,与状态值相关的有三个文件

  1. /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java:该文件中对状态值进行存储
  2. /frameworks/base/packages/SettingsProvider/res/values/defaults.xml:定义了开关状态的默认值
  3. /frameworks/base/core/java/android/provider/Settings.java:定义了各开关状态默认值存储时对应的key
  4. vendor\XXX\trunk\etc\settings-config.xml 亮度、字体大小、锁屏等设置的默认值在这里设置

以屏幕超时为例

1、TimeoutPreferenceController

    @Override
    public void updateState(Preference preference) {
        final TimeoutListPreference timeoutListPreference = (TimeoutListPreference) preference;
        //系统没有提供SCREEN_OFF_TIMEOUT才使用FALLBACK_SCREEN_TIMEOUT_VALUE
        final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(),
                SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE);
    }

2、DatabaseHelper

并不是所有的默认值都是通过读取defaults.xml的,也有的是在DatabaseHelper.java中直接设置

如loadSetting(stmt, Settings.Secure.ADB_ENABLED, 1); 这个ADB Debugging开关就是直接在数据库文件中写入的。

关于USB Debugging 开关也可以在systemui的systemui/usb/StorageNotification.java文件中去设置,可以判断是否有IMEI号

分析代码时如果发现在defaults.xml找不到这一项就直接在DatabaseHelper.java文件中查找。

private void loadSystemSettings(SQLiteDatabase db) {
    //数据库名
    private static final String DATABASE_NAME = "settings.db";
    
    SQLiteStatement stmt = null;
    try {
        stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
                + " VALUES(?,?);");
        //SCREEN_OFF_TIMEOUT设置def_screen_off_timeout
        //def_screen_off_timeout在defaults.xml中
        loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                R.integer.def_screen_off_timeout);
        .....
            
private void loadIntegerSetting(SQLiteStatement stmt, String key, int resid) {
            //
            loadSetting(stmt, key,
            Integer.toString(mContext.getResources().getInteger(resid)));
        }
}
    
private void loadSetting(SQLiteStatement stmt, String key, Object value) {
    //
    stmt.bindString(1, key);
    stmt.bindString(2, value.toString());
    stmt.execute();
}
    
.....
    
static final String PARTNER_SETTINGS_PATH ="etc/settings-config.xml";
private void updateSystemSecureSettings(SQLiteDatabase db) {  
    FileReader settingsReader;
    final File settingsFile = new File(Environment.getRootDirectory(), PARTNER_SETTINGS_PATH);
    try {
        settingsReader = new FileReader(settingsFile);
    } catch (FileNotFoundException e) {
        Log.w(TAG, "Can't open " + Environment.getRootDirectory() + "/" + PARTNER_SETTINGS_PATH);
        return;
    }

3、defaults.xml

    true
    //对应SCREEN_OFF_TIMEOUT
    15000
    -1
    false
    ......

4、Settings.java

        /**
         * The amount of time in milliseconds before the device goes to sleep or begins
         * to dream after a period of inactivity.  This value is also known as the
         * user activity timeout period since the screen isn't necessarily turned off
         * when it expires.
         *
         * 

* This value is bounded by maximum timeout set by * {@link android.app.admin.DevicePolicyManager#setMaximumTimeToLock(ComponentName, long)}. */ //使用adb命令获取得到,区分大小写:screen_off_timeout public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";

5、settings-config.xml


	
	
	
	
	
    //屏幕锁定时间
	
	
        
        
        
	
    
	
    //字体大小
    
	
	
	
	
    //屏幕亮度
	
	
	
	
	
  
	
    
    

6、默认值

value

含义

key

def_dim_screen

0=no 1=yes:是否让屏幕亮度渐渐变暗

Settings.System.DIM_SCREEN

def_screen_off_timeout

无操作多少秒后灭屏

Settings.System.SCREEN_OFF_TIMEOUT

def_sleep_timeout

无操作多少秒后休眠(该值要比灭屏时间长,因为在休眠之前会先灭屏)

Settings.Secure.SLEEP_TIMEOUT

def_airplane_mode_on

飞行模式是否默认开启

Settings.Global.AIRPLANE_MODE_ON

def_theater_mode_on

剧场模式是否默认开启

Settings.Global.THEATER_MODE_ON

def_airplane_mode_radios

开启飞行模式时会关掉的开关列表(通常会包括蓝牙,wifi,nfc等)

Settings.Global.AIRPLANE_MODE_RADIOS

airplane_mode_toggleable_radios

飞行模式下用户可以手动开启的开关列表

Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS

def_auto_time

1=yes, 0=no是否从网络自动同步日期、时间、时区

Settings.Global.AUTO_TIME

def_auto_time_zone

1=yes, 0=no是否从网络自动同步时区

Settings.Global.AUTO_TIME_ZONE

def_accelerometer_rotation

1=yes, 0=no是否开启自动旋转(即是否根据加速度传感器旋转屏幕方向)

Settings.System.ACCELEROMETER_ROTATION

def_screen_brightness

屏幕默认亮度(取值区间为0–255)

Settings.System.SCREEN_BRIGHTNESS

def_screen_brightness_automatic_mode

是否开启屏幕亮度的自动调节

Settings.System.SCREEN_BRIGHTNESS_MODE

def_window_animation_scale

1=yes, 0=no窗口动画缩放

Settings.System.WINDOW_ANIMATION_SCALE

def_window_transition_scale

1=yes, 0=no窗口透明度

Settings.System.TRANSITION_ANIMATION_SCALE

def_haptic_feedback

是否开启触摸反馈,不清楚什么含义

Settings.System.HAPTIC_FEEDBACK_ENABLED

def_bluetooth_on

0=disabled. 1=enabled.默认是否开启蓝牙

Settings.Global.BLUETOOTH_ON

def_wifi_display_on

0=disabled. 1=enabled.是否开启wifi显示

Settings.Global.WIFI_DISPLAY_ON

def_install_non_market_apps

是否允许安装不是在应用市场下载的app:1 = 允许通过安装包安装,0 = 不允许通过安装包安装

Settings.Secure.INSTALL_NON_MARKET_APPS

def_package_verifier_enable

在安装app之前进行证书检查,1审查,0不审查

Settings.Global.PACKAGE_VERIFIER_ENABLE

def_location_providers_allowed

是否开启gps,若字符串为null则默认不开启gps,还需借助LOCATION_MODE进行判断

Settings.Secure.LOCATION_PROVIDERS_ALLOWED

assisted_gps_enabled

是否开启辅助的gps应用

Settings.Global.ASSISTED_GPS_ENABLED

def_netstats_enabled

是否开启流量统计

Settings.Global.NETSTATS_ENABLED

def_usb_mass_storage_enabled

是否开启usb海量存储

Settings.Global.USB_MASS_STORAGE_ENABLED

def_wifi_on

wifi默认是否开启

Settings.Global.WIFI_ON

def_wifi_sleep_policy

wifi是否休眠(会和移动网络来回切换)取值为0-never, 1-only when plugged in, 2-always

Settings.Global.WIFI_SLEEP_POLICY

def_networks_available_notification_on

是否通知用户打开网络

Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON

def_backup_enabled

0-disabled, 1-enabled是否开启设置备份

Settings.Secure.BACKUP_ENABLED

def_backup_transport

用于备份或者恢复的传输文件

Settings.Secure.BACKUP_TRANSPORT

def_notification_pulse

当有通知来时,led灯是否要重复闪烁

Settings.System.NOTIFICATION_LIGHT_PULSE

def_mount_play_notification_snd

当有事件来临时是否播放通知铃声

Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND

def_mount_ums_autostart

是否自动启动主机检测系统

Settings.Secure.MOUNT_UMS_AUTOSTART

def_mount_ums_prompt

是否在主机检测时显示通知

Settings.Secure.MOUNT_UMS_PROMPT

def_mount_ums_notify_enabled

Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED

当开启ums时是否显示通知

def_power_sounds_enabled

电量过低时是否铃声通知

Settings.Global.POWER_SOUNDS_ENABLED

def_low_battery_sound

低电量时播放的铃声文件来源

Settings.Global.LOW_BATTERY_SOUND

def_dock_sounds_enabled

当插拔电源时是否播放声音

Settings.Global.DOCK_SOUNDS_ENABLED

def_desk_dock_sound

插上电源时播放的音频文件

Settings.Global.DESK_DOCK_SOUND

def_desk_undock_sound

拔下电源时播放的音频文件

Settings.Global.DESK_UNDOCK_SOUND

def_car_dock_sound

使用车载电源充电时播放的音频文件

Settings.Global.CAR_DOCK_SOUND

def_car_undock_sound

当从车载电源拔下时播放的音频文件

Settings.Global.CAR_UNDOCK_SOUND

def_lockscreen_sounds_enabled

当解锁或是锁屏时是否播放声音

Settings.System.LOCKSCREEN_SOUNDS_ENABLED

def_lock_sound

锁屏时播放的音频文件

Settings.Global.LOCK_SOUND

def_unlock_sound

解锁时播放的音频文件

Settings.Global.UNLOCK_SOUND

def_trusted_sound

在未解锁的情况下设备进入到可信任状态时播放的音频文件

Settings.Global.TRUSTED_SOUND

def_wireless_charging_started_sound

开启无线充电时播放声音

Settings.Global.WIRELESS_CHARGING_STARTED_SOUND

def_lockscreen_disabled

第一次开机时默认不锁屏(若要彻底去掉锁屏页面还需要在别的方法中设置)

Settings.System.LOCKSCREEN_DISABLED

def_device_provisioned

设备是否已经被配置(该参数考虑的时多用户不同时刻使用同一个设备的情况)

Settings.Global.DEVICE_PROVISIONED

def_dock_audio_media_enabled

使用dock音频输出媒体

Settings.Global.DOCK_AUDIO_MEDIA_ENABLED

def_vibrate_in_silent

静音模式下是否允许震动

Settings.System.VIBRATE_IN_SILENT

def_accessibility_script_injection

是否增强js的屏幕阅读性

Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION

def_accessibility_speak_password

访问模式下是否语音播报密码

Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD

def_low_battery_sound_timeout

当经过一定时间后,如果低电量提醒为播放声音,则灭屏

Settings.Global.LOW_BATTERY_SOUND_TIMEOUT

def_lock_screen_show_notifications

是否在锁屏界面显示通知

Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS

def_lock_screen_allow_private_notifications

允许在锁屏界面上显示私有通知,就像是解锁状态下一样

Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS

def_wifi_scan_always_available

设置-wlan-高级-随时扫描开关

Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE

7、adb命令获取/修改/设置值

C:\Users\jiabao.guan>adb shell settings get system screen_off_timeout
60000
C:\Users\jiabao.guan>adb shell settings put system guan 66
C:\Users\jiabao.guan>adb shell settings get system guan
66
C:\Users\jiabao.guan>adb shell settings put system screen_off_timeout 120000
C:\Users\jiabao.guan>adb shell settings get system screen_off_timeout
120000

八、添加辅助菜单

测试目标:

为系统设置最底部增加一项菜单项(title:辅助功能),进入辅助功能菜单项,设置一个项(高对比度字体),和两个项(颜色调整和多彩屏幕)。

1、top_level_settings.xml

在res/xml/top_level_settings.xml配置文件中增加一个标签,并为标签设置相关属性(fragment属性和controller属性需要配置该类的全限定类名)。

    

2、assistant

配置好后创建com.android.settings.assistant包,在该包下创建这两个类。(AssistantFunctionDashboardFragment类和AssistantFunctionPreferenceController类)

3、AssistantFunctionDashboardFragment

package com.android.settings.assistant;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.wiosfeature.firebase.ServiceUtils;
import android.content.Context;
import android.os.Bundle;
import androidx.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import android.provider.SearchIndexableResource;
import java.util.ArrayList;
import java.util.List;
import android.util.Log;
/**
 * @Author : 柒
 * @Time : 2022/8/24 14:17
 */
public class AssistantFunctionDashboardFragment extends SettingsPreferenceFragment {
    private static final Object TAG = "AssistantFunctionDashboardFragment";
    private Context mContext;
    @Override
    public int getMetricsCategory() {
        return MetricsProto.MetricsEvent.SETTINGS_SYSTEM_CATEGORY;
    }
    //创建二级菜单
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        super.onCreatePreferences(savedInstanceState, rootKey);
        addPreferencesFromResource(R.xml.assistant_function);
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }
    // 为每个二级菜单项设置点击事件
    @Override
    public boolean onPreferenceTreeClick(Preference preference) {
        String key = preference.getKey();
        android.util.Log.i("AssistantFunctionDashboardFragment", "guan+onPreferenceTreeClick: " + key);
        switch (key){
            case "color_adjustment":
                android.util.Log.i("AssistantFunctionDashboardFragment", "guan+color_adjustment: " + key);
                break;
            case "colorful_screen":
                android.util.Log.i("AssistantFunctionDashboardFragment", "guan+colorful_screen: " + key);
                break;
        }
        return true;
    }
    /**
     * For Search.
     */
    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider(R.xml.assistant_function) {
                @Override
                protected boolean isPageSearchEnabled(Context context) {
                    return super.isPageSearchEnabled(context);
                }
                @Override
                public List getXmlResourcesToIndex(Context context, boolean enabled) {
                    return super.getXmlResourcesToIndex(context, enabled);
                }
            };
}

4、AssistantFunctionPreferenceController

package com.android.settings.assistant;
import com.android.settings.core.BasePreferenceController;
import android.content.Context;
/**
 * @Author : 柒
 * @Time : 2022/8/24 14:17
 */
public class AssistantFunctionPreferenceController extends BasePreferenceController {
    //调用父类的构造方法
    public AssistantFunctionPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
    }
    //实现该菜单项的显示
    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    }
}

5、AssistantFunctionDashboardActivity

在Settings目录下创建

package com.android.settings;
/**
 * @Author : 柒
 * @Time : 2022/8/24 15:11
 */
public class AssistantFunctionDashboardActivity extends SettingsActivity{
}

6、assistant_function.xml


    
    
    

7、AndroidManifest.xml

        
        
            
                
                
            
            
        

8、Settings

public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ }

9、SettingsGateway

在SettingsGateway类的ENTRY_FRAGMENTS数组中加入AssistantFunctionDashboardFragment类名,在SETTINGS_FOR_RESTRICTED数组中加入AssistantFunctionPreferenceController类名

    public static final String[] SETTINGS_FOR_RESTRICTED = {
            // Home page
            AssistantFunctionPreferenceController.class.getName(),
        .....
                }
    public static final String[] ENTRY_FRAGMENTS = {
            AssistantFunctionDashboardFragment.class.getName(),
        ....
    }

10、strings

    assistant & function
    assistant & summary
    high_contrast & contrast_font
    high_contrast_font & summary
    color & adjustment
    color_adjustment & summary
    colorful & screen
    colorful_screen & summary
    "辅助功能"
    "高对比度字体、颜色调整、多彩屏幕"
    "高对比度字体"
    "高对比度字体"
    "颜色调整"
    "颜色调整"
    "多彩屏幕"
    "多彩屏幕"


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码