平台
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);
}
}
}
}