平台
RK3288 + Android 7.1
需求
在设置主界面添加设置项.
解决方案
修改文件
|-- packages/apps/Settings/AndroidManifest.xml
<!-- SCREENSHOT --> <activity android:name="Settings$ScreenshotSettingsActivity" android:label="@string/screenshot_manager" android:icon="@drawable/capture" android:taskAffinity="" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.VOICE_LAUNCH" /> <category android:name="com.android.settings.SHORTCUT" /> </intent-filter> <intent-filter android:priority="6"> <action android:name="com.android.settings.action.SETTINGS" /> </intent-filter> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.device" /> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.ScreenshotSetting" /> </activity> <!--添加 UsbSwitch, label随便用了一个字符串(SD卡), 图标用了跟截屏设置一样的 --> <activity android:name="Settings$UsbSwitchActivity" android:label="@string/sdcard_setting" android:icon="@drawable/capture" android:taskAffinity="" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.VOICE_LAUNCH" /> <category android:name="com.android.settings.SHORTCUT" /> </intent-filter> <intent-filter> <action android:name="com.android.settings.action.SETTINGS" /> </intent-filter> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.device" /> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.UsbSettings" /> </activity>
|-- packages/apps/Settings/src/com/android/settings/Settings.java
public class Settings extends SettingsActivity { /* * Settings subclasses for launching independently. */ public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ } public static class WirelessSettingsActivity extends SettingsActivity { /* empty */ } public static class SimSettingsActivity extends SettingsActivity { /* empty */ } public static class TetherSettingsActivity extends SettingsActivity { /* empty */ } public static class VpnSettingsActivity extends SettingsActivity { /* empty */ } public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ } public static class StorageSettingsActivity extends SettingsActivity { /* empty */ } public static class PrivateVolumeForgetActivity extends SettingsActivity { /* empty */ } public static class PrivateVolumeSettingsActivity extends SettingsActivity { /* empty */ } public static class PublicVolumeSettingsActivity extends SettingsActivity { /* empty */ } public static class WifiSettingsActivity extends SettingsActivity { /* empty */ } public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ } public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ } public static class AvailableVirtualKeyboardActivity extends SettingsActivity { /* empty */ } public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ } public static class PhysicalKeyboardActivity extends SettingsActivity { /* empty */ } public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ } public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ } public static class LocalePickerActivity extends SettingsActivity { /* empty */ } public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ } public static class HomeSettingsActivity extends SettingsActivity { /* empty */ } public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ } public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ } public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ } public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ } public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ } public static class ManageAssistActivity extends SettingsActivity { /* empty */ } public static class AllApplicationsActivity extends SettingsActivity { /* empty */ } public static class HighPowerApplicationsActivity extends SettingsActivity { /* empty */ } public static class ScreenshotSettingsActivity extends SettingsActivity { /* empty */ } //增加UsbSwitchActivity, 此类将用于AndroidManifest.xml 和 SettingsActivity public static class UsbSwitchActivity extends SettingsActivity { /* empty */ } public static class HdmiSettingsActivity extends SettingsActivity { /* empty */ } ... }
packages/apps/Settings/src/com/android/settings/SettingsActivity.java
// Show only these settings for restricted users private String[] SETTINGS_FOR_RESTRICTED = { //wireless_section WifiSettingsActivity.class.getName(), Settings.BluetoothSettingsActivity.class.getName(), Settings.DataUsageSummaryActivity.class.getName(), Settings.SimSettingsActivity.class.getName(), Settings.WirelessSettingsActivity.class.getName(), //device_section Settings.HomeSettingsActivity.class.getName(), Settings.SoundSettingsActivity.class.getName(), Settings.DisplaySettingsActivity.class.getName(), Settings.StorageSettingsActivity.class.getName(), Settings.ManageApplicationsActivity.class.getName(), Settings.PowerUsageSummaryActivity.class.getName(), Settings.GestureSettingsActivity.class.getName(), Settings.ScreenshotSettingsActivity.class.getName(), //增加UsbSwitchActivity Settings.UsbSwitchActivity.class.getName(), //personal_section Settings.LocationSettingsActivity.class.getName(), Settings.SecuritySettingsActivity.class.getName(), Settings.InputMethodAndLanguageSettingsActivity.class.getName(), Settings.UserSettingsActivity.class.getName(), Settings.AccountSettingsActivity.class.getName(), //system_section Settings.DateTimeSettingsActivity.class.getName(), Settings.DeviceInfoSettingsActivity.class.getName(), Settings.AccessibilitySettingsActivity.class.getName(), Settings.PrintSettingsActivity.class.getName(), Settings.PaymentSettingsActivity.class.getName(), Settings.HdmiSettingsActivity.class.getName() }; private static final String[] ENTRY_FRAGMENTS = { WirelessSettings.class.getName(), WifiSettings.class.getName(), AdvancedWifiSettings.class.getName(), SavedAccessPointsWifiSettings.class.getName(), BluetoothSettings.class.getName(), SimSettings.class.getName(), TetherSettings.class.getName(), WifiP2pSettings.class.getName(), VpnSettings.class.getName(), DateTimeSettings.class.getName(), LocaleListEditor.class.getName(), InputMethodAndLanguageSettings.class.getName(), AvailableVirtualKeyboardFragment.class.getName(), SpellCheckersSettings.class.getName(), UserDictionaryList.class.getName(), UserDictionarySettings.class.getName(), HomeSettings.class.getName(), DisplaySettings.class.getName(), DeviceInfoSettings.class.getName(), ManageApplications.class.getName(), NotificationApps.class.getName(), ManageAssist.class.getName(), ProcessStatsUi.class.getName(), NotificationStation.class.getName(), LocationSettings.class.getName(), SecuritySettings.class.getName(), UsageAccessDetails.class.getName(), PrivacySettings.class.getName(), DeviceAdminSettings.class.getName(), AccessibilitySettings.class.getName(), AccessibilitySettingsForSetupWizard.class.getName(), CaptionPropertiesFragment.class.getName(), com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(), TextToSpeechSettings.class.getName(), StorageSettings.class.getName(), PrivateVolumeForget.class.getName(), PrivateVolumeSettings.class.getName(), PublicVolumeSettings.class.getName(), DevelopmentSettings.class.getName(), AndroidBeam.class.getName(), WifiDisplaySettings.class.getName(), PowerUsageSummary.class.getName(), AccountSyncSettings.class.getName(), AccountSettings.class.getName(), GestureSettings.class.getName(), CryptKeeperSettings.class.getName(), DataUsageSummary.class.getName(), DreamSettings.class.getName(), UserSettings.class.getName(), NotificationAccessSettings.class.getName(), ZenAccessSettings.class.getName(), PrintSettingsFragment.class.getName(), PrintJobSettingsFragment.class.getName(), TrustedCredentialsSettings.class.getName(), PaymentSettings.class.getName(), KeyboardLayoutPickerFragment.class.getName(), KeyboardLayoutPickerFragment2.class.getName(), PhysicalKeyboardFragment.class.getName(), ZenModeSettings.class.getName(), SoundSettings.class.getName(), ConfigureNotificationSettings.class.getName(), ChooseLockPassword.ChooseLockPasswordFragment.class.getName(), ChooseLockPattern.ChooseLockPatternFragment.class.getName(), InstalledAppDetails.class.getName(), BatterySaverSettings.class.getName(), AppNotificationSettings.class.getName(), OtherSoundSettings.class.getName(), ApnSettings.class.getName(), ApnEditor.class.getName(), WifiCallingSettings.class.getName(), ZenModePrioritySettings.class.getName(), ZenModeAutomationSettings.class.getName(), ZenModeScheduleRuleSettings.class.getName(), ZenModeEventRuleSettings.class.getName(), ZenModeVisualInterruptionSettings.class.getName(), ProcessStatsUi.class.getName(), PowerUsageDetail.class.getName(), ProcessStatsSummary.class.getName(), DrawOverlayDetails.class.getName(), WriteSettingsDetails.class.getName(), AdvancedAppSettings.class.getName(), WallpaperTypeSettings.class.getName(), VrListenerSettings.class.getName(), ManagedProfileSettings.class.getName(), ChooseAccountActivity.class.getName(), IccLockSettings.class.getName(), ImeiInformation.class.getName(), SimStatus.class.getName(), Status.class.getName(), TestingSettings.class.getName(), WifiAPITest.class.getName(), WifiInfo.class.getName(), MasterClear.class.getName(), NightDisplaySettings.class.getName(), ScreenshotSetting.class.getName(), //添加UsbSettings UsbSettings.class.getName(), HdmiSettings.class.getName(), ManageDomainUrls.class.getName(), AutomaticStorageManagerSettings.class.getName() }; private void doUpdateTilesList() { PackageManager pm = getPackageManager(); final UserManager um = UserManager.get(this); final boolean isAdmin = um.isAdminUser(); String packageName = getPackageName(); ... final boolean showDev = mDevelopmentPreferences.getBoolean( DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng")) && !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES); setTileEnabled(new ComponentName(packageName, Settings.DevelopmentSettingsActivity.class.getName()), showDev, isAdmin, pm); if(!SystemProperties.get("ro.build.characteristics","null").equals("tablet")) { setTileEnabled(new ComponentName(packageName, Settings.ScreenshotSettingsActivity.class.getName()), false, isAdmin, pm); } //使能组件UsbSwitchActivity. setTileEnabled(new ComponentName(packageName, Settings.UsbSwitchActivity.class.getName()), true, isAdmin, pm); // Reveal development-only quick settings tiles DevelopmentTiles.setTilesEnabled(this, showDev); ... }
增加文件
packages/apps/Settings/src/com/android/settings/UsbSettings.java
package com.android.settings; import java.util.Timer; import java.util.TimerTask; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Bundle; import android.os.Handler; //新设置引和了support.v7 import android.support.v7.preference.CheckBoxPreference; import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.provider.Settings; import android.util.Log; import android.view.Gravity; import android.view.WindowManager; import android.view.ViewGroup.LayoutParams; import android.widget.TextView; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.os.SystemProperties; import android.content.res.Resources; public class UsbSettings extends SettingsPreferenceFragment implements OnPreferenceChangeListener { ... }
效果如图:
扩展说明
在组件定义中, 以下声明不可删除, 用于过滤Tiles(设备项)用:
<intent-filter> <action android:name="com.android.settings.action.SETTINGS" /> </intent-filter>
选项分类, 声明此选项将显示在 设备 组下, 其它分类见下面 TileUtils.java中定义:
<!-- com.android.settings.category.wireless com.android.settings.category.device com.android.settings.category.personal com.android.settings.category.system --> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.device" />
|-- frameworks/base/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
public class TileUtils { private static final boolean DEBUG = false; private static final boolean DEBUG_TIMING = false; private static final String LOG_TAG = "TileUtils"; /** * Settings will search for system activities of this action and add them as a top level * settings tile using the following parameters. * * <p>A category must be specified in the meta-data for the activity named * {@link #EXTRA_CATEGORY_KEY} * * <p>The title may be defined by meta-data named {@link #META_DATA_PREFERENCE_TITLE} * otherwise the label for the activity will be used. * * <p>The icon may be defined by meta-data named {@link #META_DATA_PREFERENCE_ICON} * otherwise the icon for the activity will be used. * * <p>A summary my be defined by meta-data named {@link #META_DATA_PREFERENCE_SUMMARY} */ private static final String EXTRA_SETTINGS_ACTION = "com.android.settings.action.EXTRA_SETTINGS"; /** * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities. */ private static final String SETTINGS_ACTION = "com.android.settings.action.SETTINGS"; private static final String OPERATOR_SETTINGS = "com.android.settings.OPERATOR_APPLICATION_SETTING"; private static final String OPERATOR_DEFAULT_CATEGORY = "com.android.settings.category.wireless"; private static final String MANUFACTURER_SETTINGS = "com.android.settings.MANUFACTURER_APPLICATION_SETTING"; private static final String MANUFACTURER_DEFAULT_CATEGORY = "com.android.settings.category.device"; /** * The key used to get the category from metadata of activities of action * {@link #EXTRA_SETTINGS_ACTION} * The value must be one of: * <li>com.android.settings.category.wireless</li> * <li>com.android.settings.category.device</li> * <li>com.android.settings.category.personal</li> * <li>com.android.settings.category.system</li> */ ... private static void getTilesForAction(Context context, UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) { Intent intent = new Intent(action); if (requireSettings) { intent.setPackage(SETTING_PKG); } getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles, requireSettings, true); } public static void getTilesForIntent(Context context, UserHandle user, Intent intent, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, boolean usePriority, boolean checkCategory) { PackageManager pm = context.getPackageManager(); List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, user.getIdentifier()); for (ResolveInfo resolved : results) { if (!resolved.system) { // Do not allow any app to add to settings, only system ones. continue; } ActivityInfo activityInfo = resolved.activityInfo; Bundle metaData = activityInfo.metaData; String categoryKey = defaultCategory; if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY)) && categoryKey == null) { Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent " + intent + " missing metadata " + (metaData == null ? "" : EXTRA_CATEGORY_KEY)); continue; } else { categoryKey = metaData.getString(EXTRA_CATEGORY_KEY); } Pair<String, String> key = new Pair<String, String>(activityInfo.packageName, activityInfo.name); Tile tile = addedCache.get(key); if (tile == null) { tile = new Tile(); tile.intent = new Intent().setClassName( activityInfo.packageName, activityInfo.name); tile.category = categoryKey; tile.priority = usePriority ? resolved.priority : 0; tile.metaData = activityInfo.metaData; updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, pm); if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title); addedCache.put(key, tile); } if (!tile.userHandle.contains(user)) { tile.userHandle.add(user); } if (!outTiles.contains(tile)) { outTiles.add(tile); } } } }