AOSP 设置-提示音和振动 添加一个带有开关(Switch)的设置项

要求

如题,在设置-提示音和振动中添加一个带有开关(Switch)的设置项。

复制代码
要实现的效果:
1、能正常显示带有开关(Switch)的设置项
2、给这个开关设置默认属性
3、开关能正常使用(具体逻辑需要自己加)

步骤

1、UI显示

可以根据上方的"振动模式下一律显示振动图标"来定位要在哪里添加。

xml 复制代码
packages/apps/Settings/res/xml/sound_settings.xml

<SwitchPreferenceCompat
        android:key="top_paddle_control_volume"
        android:title="@string/top_paddle_control_volume_title"
        android:order="-25"
        settings:controller="com.android.settings.notification.TopPaddleVolumePreferenceController"/>

只要加上上面这段xml代码就能在设置中显示了,一开始可以不加settings:controller这个配置,也会正常显示的,只是没有功能,纯UI。后续TopPaddleVolumePreferenceController是需要自己加的。

2、定义对应的controller

要给这个switch开关定义一个controller来控制开关

java 复制代码
packages/apps/Settings/src/com/android/settings/notification/TopPaddleVolumePreferenceController.java

package com.android.settings.notification;

import static com.android.settings.notification.SettingPref.TYPE_SECURE;

import android.content.Context;
import android.provider.Settings.Secure;

import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;

import android.provider.Settings;
import android.util.Log;

// public class TopPaddleVolumePreferenceController  extends SettingPrefController {
public class TopPaddleVolumePreferenceController  extends TogglePreferenceController {
    private static final String TAG = "TopPaddleVolumePreferenceController";
    private static final String TOP_PADDLE_CONTROL_VOLUME = "top_paddle_control_volume";

    public TopPaddleVolumePreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
    }

    @Override
    public boolean isChecked() {
        Log.d(TAG, "ENTER isChecked()");
        // Read database status, default 0 (off)
        return Settings.System.getInt(mContext.getContentResolver(),
            TOP_PADDLE_CONTROL_VOLUME, 0) != 0;
        // 经过测试,这里的TOP_PADDLE_CONTROL_VOLUME也可以替换成Settings.System.TOP_PADDLE_CONTROL_VOLUME
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        Log.d(TAG, "isChecked = "+isChecked);
        // Write database status
        return Settings.System.putInt(mContext.getContentResolver(),
            TOP_PADDLE_CONTROL_VOLUME, isChecked ? 1 : 0);
        // 经过测试,这里的TOP_PADDLE_CONTROL_VOLUME也可以替换成Settings.System.TOP_PADDLE_CONTROL_VOLUME
    }

    @Override
    public int getAvailabilityStatus() {
        return AVAILABLE;
    }

    /**
     * 修复错误:覆盖 TogglePreferenceController 中的抽象方法
     * 该方法用于在搜索结果中高亮显示菜单路径
     */
    @Override
    public int getSliceHighlightMenuRes() {
        // 因为你在 sound_settings.xml 中添加,所以指向声音菜单
        return R.string.menu_key_sound; 
    }
}

3、数据初始化

需要给这个设置项定义一个变量A,对吧,点击开关时实际就是修改这个变量A的值。而且还需要给这个变量A初始化一个值,0或者1,规定这个开关是默认开还是默认关

3.1 定义switch开关的初始值

java 复制代码
frameworks\base\core\java\android\provider\Settings.java

public static final class System extends NameValueTable {
    /**
     * Whether keyboard vibration feedback is enabled. The value is boolean (1 or 0).
     *
     * @hide
     */
    @hide
    public static final String KEYBOARD_VIBRATION_ENABLED = "keyboard_vibration_enabled";
    
这样就是定义了一个变量了,相当于数据库的key,后面切换开关时修改的就是这个key。
其中@hide和@hide我看其它的变量也有,我也对应着加上了,反正如果你没有@hide编译会报错。

注意:你定义的这个KEYBOARD_VIBRATION_ENABLED是放在class System还是class Secure中很重要的。我一开始是没注意,定义在了class Secure,但是绑定初始值时用的Settings.System.TOP_PADDLE_CONTROL_VOLUME,结果就报错了,这里注意。

3.2 定义switch开关的默认值

这个默认值其实不用定义,在初始值赋值的时候可以直接给个0或者1,但是这里为了代码的规范化,咱们还是定义一下。

xml 复制代码
frameworks\base\packages\SettingsProvider\res\values\defaults.xml

<!--cmy add, Top paddle control volume, default: false -->
    <bool name="def_top_paddle_control_volume">true</bool>

3.3 绑定初始值

java 复制代码
frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java

private void loadSystemSettings(SQLiteDatabase db) {
    // cmy add
    loadBooleanSetting(stmt, Settings.System.TOP_PADDLE_CONTROL_VOLUME,
        R.bool.def_top_paddle_control_volume);

这样修改完,然后编译刷机,就能看到switch开关被打开了,因为绑定的默认值def_top_paddle_control_volume是true。

查看变量值的adb命令

shell 复制代码
adb shell settings get system top_paddle_control_volume

这里是get system,这个system可能跟你定义变量的位置有关,前面说的,看你的变量是定义在class System还是class Secure
相关推荐
DogDaoDao4 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
JohnnyDeng945 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
Android小码家8 小时前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士8 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love9 小时前
MySQL的执行流程
android·数据库·mysql
云起SAAS14 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒15 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌15 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_9151063215 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴19 小时前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io