当前位置: 首页 > news >正文

RKAndroid11-系统设置新增开关选项

场景:在Room 开发中

  • 我们在日常开发的应用里面有一些信息、开关 需要在系统设置里面显示
  • 部分业务逻辑开关需要在系统设置里面可以直接控制

文章目录

  • 需求
  • 一、参考资料
  • 二、实现方案
  • 三、实现思路
  • 四、基本UI常识介绍
    • 基本概念
      • Preference 系统基于以下几个核心类:
    • Preference 类型
      • CheckBoxPreference
      • EditTextPreference
      • SwitchPreference
      • PreferenceFragment
  • 五、源码分析
    • 找到需要添加UI元素的Fragment 及在哪个界面添加需求的界面 -SystemDashboardFragment
    • 布局中新增UI元素- system_dashboard_fragment
      • 核心字段 理解:
    • 自定义控制器 - CloudBootParentPreferenceController
    • 自定义跳转的Fragment - CloudBootSettings
    • 跳转的Fragment 的布局 - cloud_boot_settings
    • 控制子界面控制器-CloudBootPreferenceController
    • 相关string字段-strings.xml
    • 路由 -SettingsGateway
  • 总结


需求

系统设置新增开关选项控制页面,比如 在系统设置里面添加一个 应用自启动开关。

在这里插入图片描述
在这里插入图片描述

一、参考资料

MTKAndroid12-13-开机应用自启功能实现
MTK-删除设置首页菜单项
Android 11 Settings源码入门
Android Preference简单介绍
RK-Android11-系统增加一个属性值

核心知识点:

  • 理解Android 基本架构:代码逻辑、业务、UI层面 架构基本理解
  • Settings App 用到的 Preference 这一套:Preference 、PreferenceScreen 、PreferenceFragment 或 PreferenceActivity 等基本的UI元素理解和其子UI元素及属性了解。

二、实现方案

新增文件:

/packages/apps/Settings/src/com/android/settings/cloud/CloudBootParentPreferenceController.java
/packages/apps/Settings/src/com/android/settings/cloud/CloudBootPreferenceController.java
/packages/apps/Settings/src/com/android/settings/cloud/CloudBootSettings.java
/packages/apps/Settings/res/drawable-hdpi/icon_yun_diannao.png
/packages/apps/Settings/res/xml/cloud_boot_settings.xml

修改文件:

/packages/apps/Settings/AndroidManifest.xml
/packages/apps/Settings/res/values-zh-rCN/strings.xml
/packages/apps/Settings/res/xml/system_dashboard_fragment.xml
/packages/apps/Settings/src/com/android/settings/core/gateway/SettingsGateway.java

三、实现思路

这里还是把思路简要说一下


- 系统界面的布局中添加这个item  这里添加:system_dashboard_fragment.xml 
- 基于Settings 的UI架构,在布局中添加UI元素,总要有Controller->CloudBootParentPreferenceController 和 对应的界面 CloudBootSettings 吧,当然这里有一些配置属性 key 、title、order、icon、keywords  等 
- 配置,可以外部访问,其实就是一个校验、网关的作用,源码架构决定。 SettingsGateway
- 

四、基本UI常识介绍

基本概念

Preference 系统基于以下几个核心类:

  • Preference - 所有设置项的基类
  • PreferenceScreen - 设置界面的容器,相当于一个设置页面
  • PreferenceFragment 或 PreferenceActivity - 用于承载 Preference 界面的组件

Preference 类型

CheckBoxPreference

  • 复选框类型的设置项

  • 保存 boolean 值

<CheckBoxPreferenceandroid:key="wifi_enabled"android:title="启用WiFi"android:summary="打开或关闭WiFi连接"android:defaultValue="true" />

EditTextPreference

  • 可编辑文本的设置项
  • 保存字符串值
<EditTextPreferenceandroid:key="user_name"android:title="用户名"android:summary="请输入您的用户名"android:dialogTitle="输入用户名"android:defaultValue="默认用户" />

SwitchPreference

  • 开关类型的设置项(Android 4.0+)
  • 保存 boolean 值
<SwitchPreferenceandroid:key="notifications_enabled"android:title="通知"android:summary="启用或禁用应用通知"android:defaultValue="true" />

PreferenceFragment

现代 Android 应用通常使用 PreferenceFragment 来显示设置界面

public class SettingsFragment extends PreferenceFragmentCompat {@Overridepublic void onCreatePreferences(Bundle savedInstanceState, String rootKey) {setPreferencesFromResource(R.xml.preferences, rootKey);// 可以在这里添加Preference变更监听器Preference preference = findPreference("key");preference.setOnPreferenceChangeListener((pref, newValue) -> {// 处理变更return true; // 返回true保存变更});}
}

暂且只 简单介绍这些,方便理解, Settings 里面的 UI 子元素蛮多的,用到的时候就自然理解了。

五、源码分析

找到需要添加UI元素的Fragment 及在哪个界面添加需求的界面 -SystemDashboardFragment

上面有所介绍,这里先找到对应的页面,当我们进入系统页面,会有这些提示:
在这里插入图片描述
找到这个Fragment最终的目的是找到它的 xml 布局,如下:

    protected int getPreferenceScreenResId() {return R.xml.system_dashboard_fragment;}

布局中新增UI元素- system_dashboard_fragment

 <Preferenceandroid:key="reset_dashboard"android:title="@string/reset_dashboard_title"android:summary="@string/reset_dashboard_summary"android:icon="@drawable/ic_restore"android:order="-50"android:fragment="com.android.settings.system.ResetDashboardFragment"settings:controller="com.android.settings.system.ResetPreferenceController"/><!-- add start --><Preferenceandroid:key="cloud_boot_summary"android:title="@string/cloud_boot_title"android:fragment="com.android.settings.cloud.CloudBootSettings"android:order="-110"android:icon="@drawable/ic_restore"settings:controller="com.android.settings.cloud.CloudBootParentPreferenceController"settings:keywords="@string/keywords_cloud_boot"/>
<!-- add end --><Preferenceandroid:key="pointer_speed_summary"android:title="@string/pointer_speed"android:fragment="com.android.settings.cloud.PointerSpeedSettings"android:order="-110"settings:controller="com.android.settings.cloud.PointerSpeedParentPreferenceController"settings:keywords="@string/keywords_cloud_boot"/>

核心字段 理解:

字段类型必需说明 示例特点
keyString唯一标识符 “wifi_enabled”用于在 SharedPreferences 中存储和检索值;必须唯一;通过 findPreference(key) 方法可以查找特定 Preference
titleString推荐显示的主标题 “Wi-Fi”显示在 Preference 的主要位置;通常简短明了,直接说明设置项功能;可以是字符串资源或直接文本
orderint可选显示顺序 100数值越小,显示位置越靠上 ;如果不指定,将按照 XML 中的声明顺序显示 ;可用于动态调整 Preference 顺序
iconDrawable可选左侧图标 @drawable/ic_wifi
controlleClass系统级 动态控制逻辑"com.android.settings.wifi.WifiPrefere用于系统设置中的高级控制逻辑;必须是 com.android.settingslib.core.AbstractPreferenceController 的子类;通常用于动态控制 Preference 的可用性/可见性
keywordsString可选搜索关键词 “wireless,network”用于系统设置的搜索功能;多个关键词用逗号分隔;应包含相关术语和同义词
fragmentClass可选跳转的Fragment "com.android.settings.wifi.Wif用于实现设置项的深层导航;必须是全限定类名(包含包名)通常用于打开子设置页面
summaryString可选描述文本“Manage wireless networks”
intent Intent可选替代fragment的跳转方式定义Intent动作

自定义控制器 - CloudBootParentPreferenceController

说白了就是当前 在 系统面板里面显示的内容,这里根据属性 显示不同的 字符串、文本内容呀。

package com.android.settings.cloud;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import android.os.SystemProperties;
/*** Parent menu summary of media controls settings*/
public class CloudBootParentPreferenceController extends BasePreferenceController {private String clouddesk;public CloudBootParentPreferenceController(Context context, String key) {super(context, key);clouddesk = SystemProperties.get("persist.sys.fise.packagename","com.ctg.itrdc.clouddesk");}@Overridepublic int getAvailabilityStatus() {return AVAILABLE;}@Overridepublic CharSequence getSummary() {int summary;if (clouddesk.equals(SystemProperties.get("persist.sys.launcher.packagename", ""))) {summary = R.string.cloud_boot_start;} else {summary = R.string.cloud_boot_stop;}return mContext.getText(summary);}
}

自定义跳转的Fragment - CloudBootSettings


package com.android.settings.cloud;
import android.app.settings.SettingsEnums;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;/*** Media control settings located in the sound menu*/
@SearchIndexable
public class CloudBootSettings extends DashboardFragment {private static final String TAG = "CloudBootSettings";@Overrideprotected int getPreferenceScreenResId() {return R.xml.cloud_boot_settings;}@Overrideprotected String getLogTag() {return TAG;}@Overridepublic int getMetricsCategory() {return 6;}public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =new BaseSearchIndexProvider(R.xml.cloud_boot_settings);
}

这里核心内容还是 xml 相关布局内容 cloud_boot_settings

   @Overrideprotected int getPreferenceScreenResId() {return R.xml.cloud_boot_settings;}

跳转的Fragment 的布局 - cloud_boot_settings

<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:title="@string/cloud_boot_title"><SwitchPreferenceandroid:key="cloud_boot_resume_switch"android:title="@string/cloud_boot_summary"android:summary="@string/cloud_boot_resume_description"app:keywords="@string/keywords_cloud_boot"app:controller="com.android.settings.cloud.CloudBootPreferenceController"app:allowDividerAbove="true" /></PreferenceScreen>

这里面的 UI子字段属性暂不协助理解,自己可以查询下,见名知意的了,看多了其实很熟悉了的。

控制子界面控制器-CloudBootPreferenceController

 package com.android.settings.cloud;import static android.provider.Settings.Secure.MEDIA_CONTROLS_RESUME;import android.content.Context;
import android.provider.Settings;import com.android.settings.core.TogglePreferenceController;
import android.os.SystemProperties;
/*** Toggle for media controls settings*/
public class CloudBootPreferenceController extends TogglePreferenceController {private String clouddesk;public CloudBootPreferenceController(Context context, String key) {super(context, key);clouddesk = SystemProperties.get("persist.sys.fise.packagename","com.ctg.itrdc.clouddesk");}@Overridepublic boolean isChecked() {return clouddesk.equals(SystemProperties.get("persist.sys.launcher.packagename", ""));}@Overridepublic boolean setChecked(boolean isChecked) {if (isChecked)SystemProperties.set("persist.sys.launcher.packagename", clouddesk);elseSystemProperties.set("persist.sys.launcher.packagename", "");return true;}@Overridepublic int getAvailabilityStatus() {return AVAILABLE;}
}

其实就是一个设置属性 、 默认 判断 CheckBox 状态的 控制器。

相关string字段-strings.xml

 <string name="cloud_boot_title">云电脑自启动</string><string name="cloud_boot_summary">云电脑自启动开关</string><string name="cloud_boot_resume_description">选择云电脑是否开机自启动</string><string name="cloud_boot_stop">开机不自启动</string><string name="cloud_boot_start">开机自启动</string><string name="keywords_cloud_boot">云电脑</string>

路由 -SettingsGateway

/*** A list of fragment that can be hosted by SettingsActivity. SettingsActivity will throw a* security exception if the fragment it needs to display is not in this list.*/public static final String[] ENTRY_FRAGMENTS = {AdvancedConnectedDeviceDashboardFragment.class.getName(),CreateShortcut.class.getName(),WifiSettings.class.getName(),// add start CloudBootSettings.class.getName()//add end };

如同 方法注释,一个校验功能,如果不在路由里面配置,这个控制界面Fragment是无法展示出来的,非法。
在这里插入图片描述
在这里插入图片描述

总结

  • 这里就是在Settings App 里面添加一个开关功能 。 这个扩展性很大,比如:自启应用、自启服务 等所有跟开关相关的业务都可以借助这个来实现。
  • 了解一下开关在设置里面如何添加,进而了解一下Settigns 架构、逻辑、业务
  • 结合属性来存储开关基本值的一个业务逻辑
  • 这个开关逻辑的业务实现了,你会发现 列表、展示 相关的业务,在Settigns 里面的需求也就一样了,没多少难度。 Settings 本身没那么复杂,接触多了发现不难。
http://www.dtcms.com/a/269141.html

相关文章:

  • 1. http 有哪些版本,你是用的哪个版本,怎么查看
  • 构建分布式高防架构实现业务零中断
  • 2025最新如何解决VSCode远程连接开发机失败/解决方案大全
  • 提示工程(Prompt Engineering)研究进展
  • Spring Data JPA基本方法调用规律
  • web渗透之指纹识别1
  • Shader面试题100道之(1-20)
  • PX4无人机上的返航操作和参数解读
  • 华为OD机试 2025B卷 - 最长的指定瑕疵度的元音子串 (C++PythonJAVAJSC语言)
  • DCN2:大规模推荐系统中的碰撞权重与显式交叉层协同优化
  • C++ tcp客户端处理重连问题
  • 3S技术+ArcGIS/ENVI全流程实战:水文、气象、灾害、生态、环境及卫生等领域应用
  • 前端工程化速通——①ES6
  • OSPF路由过滤实验案例
  • severb
  • 大模型通用架构图
  • es性能优化
  • 国产ARM+FPGA工业开发平台——GM-3568JHF
  • LeetCode 151. 反转字符串中的单词
  • 软考(软件设计师)存储管理—存储空间管理,文件共享保护
  • 虚幻引擎Gameplay框架
  • STM32固件升级设计——串口IAP升级(基于YMODEM协议)
  • CosyVoice2.0整合包:免费一键启动,释放语音克隆的创意潜能
  • day048-系统负载高排查流程与前后端分离项目
  • 上传Vue3+vite+Ts组件到npm官方库保姆级教程
  • python高级变量XIV
  • 【数据结构之哈夫曼树与编码实现】
  • 【Linux操作系统】简学深悟启示录:Linux基本指令
  • OpenStack扩展
  • 05. study_JSBridge机制