1.创建一级菜单
packages\apps\Settings\res\xml\top_level_settings.xml
<com.android.settings.widget.HomepagePreference android:fragment="com.android.settings.DeviceStatusSettings" android:icon="@drawable/ic_settings_display_white" android:key="top_level_device_status" android:order="-80" android:title="@string/device_status_settings" android:summary="@string/device_status_dashboard_summary" settings:controller="com.android.settings.devicestatus.TopLevelDeviceStatusPreferenceController"/>
DeviceStatusSettings
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class DeviceStatusSettings extends DashboardFragment { private static final String TAG = "DeviceStatusSettings"; private static final String KET_SPK_MODE_SETTINGS = "spk_mode_settings"; @Override public int getMetricsCategory() { return SettingsEnums.DISPLAY; } @Override protected String getLogTag() { return TAG; } @Override protected int getPreferenceScreenResId() { return R.xml.device_status_setting; } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); } @Override protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { return buildPreferenceControllers(context, getSettingsLifecycle()); } @Override public int getHelpResource() { return R.string.help_uri_display; } private static List<AbstractPreferenceController> buildPreferenceControllers( Context context, Lifecycle lifecycle) { final List<AbstractPreferenceController> controllers = new ArrayList<>(); controllers.add(new SpkModePreferenceController(context, KET_SPK_MODE_SETTINGS)); return controllers; } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.device_status_setting) { @Override public List<AbstractPreferenceController> createPreferenceControllers( Context context) { return buildPreferenceControllers(context, null); } }; }
TopLevelDeviceStatusPreferenceController
public class TopLevelDeviceStatusPreferenceController extends BasePreferenceController { public TopLevelDeviceStatusPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } @Override public int getAvailabilityStatus() { return AVAILABLE; } }
2.创建二级菜单
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="display_settings_screen" android:title="@string/device_status_settings" settings:keywords="@string/keywords_display"> <PreferenceCategory android:title="@string/device_spk_mode"> <com.android.settingslib.RestrictedPreference android:key="device_spk_mode" android:title="@string/device_spk_mode" android:summary="@string/summary_placeholder" android:fragment="com.android.settings.devicestatus.SpkModeSettings" settings:controller="com.android.settings.devicestatus.SpkModePreferenceController"/> </PreferenceCategory> </PreferenceScreen>
SpkModeSettings
public class SpkModeSettings extends RadioButtonPickerFragment { private static final String TAG = "SpkModeSettings"; public static final int FALLBACK_VALUE = 0; private static final String SPK_MODE_BROADCAST = "android.intent.action.SPK_MODE"; private static final String SPK_MODE_PERSIST = "persist.realbom.spkmode"; @Override public void onAttach(Context context) { super.onAttach(context); } @Override protected List<? extends CandidateInfo> getCandidates() { final String[] entries = entries(); final String[] values = keys(); final List<SpkModeControlCandidateInfo> candidates = new ArrayList<>(); if (entries == null || entries.length <= 0) return null; if (values == null || values.length != entries.length) { throw new IllegalArgumentException("Entries and values must be of the same length."); } for (int i = 0; i < entries.length; i++) { candidates.add(new SpkModeControlCandidateInfo(entries[i], values[i])); } return candidates; } private String[] entries() { return getResources().getStringArray(R.array.spk_mode_entries); } private String[] keys() { return getResources().getStringArray(R.array.spk_mode_values); } @Override protected String getDefaultKey() { return getCurrentSkpModeValue(getContext()); } @Override protected boolean setDefaultKey(String key) { setCurrentSkpModeValue(getContext(), key); return true; } @Override protected int getPreferenceScreenResId() { return R.xml.spk_mode; } @Override public int getMetricsCategory() { return 1; } private String getCurrentSkpModeValue(Context context) { if (context == null) { return Long.toString(FALLBACK_VALUE); } else { return SystemProperties.get(SPK_MODE_PERSIST, "0"); } } private void setCurrentSkpModeValue(Context context, String key) { try { if (context != null) { Log.d(TAG,"set current value == "+key); int value = Integer.parseInt((String) key); SystemProperties.set(SPK_MODE_PERSIST, String.valueOf(value)); //Settings.System.putInt(context.getContentResolver(), SPK_MODE, value); setSkpModeValue(context,value); } } catch (NumberFormatException e) { Log.e(TAG, "could not persist screen timeout setting", e); } } @Override protected void onSelectionPerformed(boolean success) { super.onSelectionPerformed(success); //getActivity().finish(); } private final class SpkModeControlCandidateInfo extends CandidateInfo { private final String name; private final String key; SpkModeControlCandidateInfo(String title, String value) { super(true); name = title; key = value; } @Override public CharSequence loadLabel() { return name; } @Override public Drawable loadIcon() { return null; } @Override public String getKey() { return key; } } private void setSkpModeValue(Context context, int value){ Intent intent = new Intent(); intent.setAction(SPK_MODE_BROADCAST); //intent.putExtra("com",4); intent.putExtra("value",value); context.sendBroadcast(intent); } }
SpkModePreferenceController
public class SpkModePreferenceController extends BasePreferenceController { public static String PREF_NAME = "spk_mode"; public static String TAG = "SpkModePreferenceController"; public static final int FALLBACK_VALUE = 0; private final CharSequence[] mEntries; private final CharSequence[] mValues; private static final String SPK_MODE_BROADCAST = "android.intent.action.SPK_MODE"; private static final String SPK_MODE_PERSIST = "persist.realbom.spkmode"; public SpkModePreferenceController(Context context, String key) { super(context, key); mEntries = context.getResources().getStringArray(R.array.spk_mode_entries); mValues = context.getResources().getStringArray(R.array.spk_mode_values); } @Override public int getAvailabilityStatus() { return AVAILABLE; } @Override public void updateState(Preference preference) { final long curValue = Long.valueOf(SystemProperties.get(SPK_MODE_PERSIST,"0")); updatePreferenceDescription(preference, curValue); Log.d(TAG, "updateState currentValue= "+String.valueOf(curValue)); } public static CharSequence getDescription(long curValue, CharSequence[] entries, CharSequence[] values) { if (curValue < 0 || entries == null || values == null || values.length != entries.length) { return null; } for (int i = 0; i < values.length; i++) { long temp = Long.parseLong(values[i].toString()); if (curValue == temp) { Log.d(TAG,"Description entries == "+entries[i]); return entries[i]; } } return null; } private void updatePreferenceDescription(Preference preference,long curValue) { final CharSequence summary; summary = getDescription(curValue, mEntries, mValues); preference.setSummary(summary); } }
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/device_spk_mode"/>