以跳转到蓝牙控制面板为例,控制面板如图所示:

其 Fragment 所在的位置是:
packages/apps/Settings/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
第一步
要在 Settings的主要 Activity 中定义继承同一个父类的内部类,作为启动时承载BluetoothDashboardFragment 的 Activity:
packages/apps/Settings/src/com/android/settings/Settings.java
diff --git a/apps/Settings/src/com/android/settings/Settings.java b/apps/Settings/src/com/android/settings/Settings.java
index e94e647ff..959f6fbf8 100644
--- a/apps/Settings/src/com/android/settings/Settings.java
+++ b/apps/Settings/src/com/android/settings/Settings.java
@@ -230,6 +230,9 @@ public class Settings extends SettingsActivity {
     // Top level categories for new IA
     public static class NetworkDashboardActivity extends SettingsActivity {}
     public static class ConnectedDeviceDashboardActivity extends SettingsActivity {}
+    //Add by huanghoufu
+    public static class BluetoothDashboardActivity extends SettingsActivity {}
+    //end
     public static class PowerUsageSummaryActivity extends SettingsActivity { /* empty */ }
     public static class AppAndNotificationDashboardActivity extends SettingsActivity {}
     public static class StorageDashboardActivity extends SettingsActivity {}
第二步
将BluetoothDashboardActivity添加到 SettingsBaseActivity 的自动更新Fragment列表中,代码逻辑如下:
packages/apps/Settings/src/com/android/settings/SettingsActivity.java
(1) 更新方法及关键注释
    private void updateTilesList() {
        // Generally the items that are will be changing from these updates will
        // not be in the top list of tiles, so run it in the background and the
        // SettingsBaseActivity will pick up on the updates automatically.
        AsyncTask.execute(() -> doUpdateTilesList());
    }(2)添加位置
diff --git a/apps/Settings/src/com/android/settings/SettingsActivity.java b/apps/Settings/src/com/android/settings/SettingsActivity.java
index 76739f049..ccd7051fd 100644
--- a/apps/Settings/src/com/android/settings/SettingsActivity.java
+++ b/apps/Settings/src/com/android/settings/SettingsActivity.java
@@ -627,6 +627,14 @@ public class SettingsActivity extends SettingsBaseActivity
private void doUpdateTilesList() {
 ……
+       //Add by huanghoufu
+        somethingChanged = setTileEnabled(changedList,
+                new ComponentName(packageName,
+                        Settings.BluetoothDashboardActivity.class.getName()),
+                !UserManager.isDeviceInDemoMode(this) /* enabled */,
+                isAdmin) || somethingChanged;
+       //end
+
         somethingChanged = setTileEnabled(changedList, new ComponentName(packageName,
                         Settings.PowerUsageSummaryActivity.class.getName()),
                 mBatteryPresent, isAdmin) || somethingChanged;
第三步
为了安全考虑,在切换Fragment时,程序会检查将要切换 Fragment 是否在可显示列表中:
packages/apps/Settings/src/com/android/settings/SettingsActivity.java
    /**
     * Switch to a specific Fragment with taking care of validation, Title and BackStack
     */
    private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
            int titleResId, CharSequence title) {
        Log.d(LOG_TAG, "Switching to fragment " + fragmentName);
        if (validate && !isValidFragment(fragmentName)) {
            throw new IllegalArgumentException("Invalid fragment for this activity: "
                    + fragmentName);
        }
        Fragment f = Utils.getTargetFragment(this, fragmentName, args);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.main_content, f);
        if (titleResId > 0) {
            transaction.setBreadCrumbTitle(titleResId);
        } else if (title != null) {
            transaction.setBreadCrumbTitle(title);
        }
        transaction.commitAllowingStateLoss();
        getSupportFragmentManager().executePendingTransactions();
        Log.d(LOG_TAG, "Executed frag manager pendingTransactions");
        return f;
    }如果将要切换的 Fragment 不在显示列表中,则会抛出“Invalid fragment for this activity……”的异常,例如:
07-26 17:15:36.574  2151  2151 D SettingsActivity: Starting onCreate
07-26 17:15:36.632  2151  2151 D SettingsActivity: Starting to set activity title
07-26 17:15:36.633  2151  2151 D SettingsActivity: Done setting title
07-26 17:15:36.633  2151  2151 D SettingsActivity: Switching to fragment com.android.settings.connecteddevice.BluetoothDashboardFragment
07-26 17:15:36.669  2151  2151 D AndroidRuntime: Shutting down VM
07-26 17:15:36.670  2151  2151 E AndroidRuntime: FATAL EXCEPTION: main
07-26 17:15:36.670  2151  2151 E AndroidRuntime: Process: com.android.settings, PID: 2151
07-26 17:15:36.670  2151  2151 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.settings/com.android.settings.Settings$BluetoothDashboardActivity}: java.lang.IllegalArgumentException: Invalid fragment for this activity: com.android.settings.connecteddevice.BluetoothDashboardFragment
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3431)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:223)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7664)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: Invalid fragment for this activity: com.android.settings.connecteddevice.BluetoothDashboardFragment
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at com.android.settings.SettingsActivity.switchToFragment(SettingsActivity.java:577)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at com.android.settings.SettingsActivity.launchSettingFragment(SettingsActivity.java:377)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at com.android.settings.SettingsActivity.onCreate(SettingsActivity.java:285)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8053)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8037)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
07-26 17:15:36.670  2151  2151 E AndroidRuntime: 	... 11 more
因此,需要在可显示名单中添加相应Fragment:
diff --git a/apps/Settings/src/com/android/settings/core/gateway/SettingsGateway.java b/apps/Settings/src/com/android/settings/core/gateway/SettingsGateway.java
index 77adbf040..76804a99b 100644
--- a/apps/Settings/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/apps/Settings/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -63,6 +63,7 @@ import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
 import com.android.settings.bugreporthandler.BugReportHandlerPicker;
 import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
+import com.android.settings.connecteddevice.BluetoothDashboardFragment;
 import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment;
 import com.android.settings.connecteddevice.usb.UsbDetailsFragment;
 import com.android.settings.datausage.DataSaverSummary;
@@ -313,7 +314,10 @@ public class 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 = {
             GestureNavigationSettingsFragment.class.getName(),
             InteractAcrossProfilesSettings.class.getName(),
             InteractAcrossProfilesDetails.class.getName(),
-            MediaControlsSettings.class.getName()
+            MediaControlsSettings.class.getName(),
+           //Add by huanghoufu
+            BluetoothDashboardFragment.class.getName()
+           //end
     };
 
     public static final String[] SETTINGS_FOR_RESTRICTED = {
@@ -356,5 +360,8 @@ public class SettingsGateway {
             UserBackupSettingsActivity.class.getName(),
             // Home page > Display
             Settings.HdmiSettingsActivity.class.getName(),
+           //Add by huanghoufu
+            Settings.BluetoothDashboardActivity.class.getName()
+           //end
     };
 }
第四步
为 Fragment 在清单文件中添加隐试启动的意图即可:
注意,这里用于启动的自定义 action 是 android.settings.BLUETOOTH_DASHBOARD
diff --git a/apps/Settings/AndroidManifest.xml b/apps/Settings/AndroidManifest.xml
index e74734b98..faa34330e 100644
--- a/apps/Settings/AndroidManifest.xml
+++ b/apps/Settings/AndroidManifest.xml
@@ -233,6 +231,21 @@
                 android:value="true" />
         </activity>
 
+       <!-- Add by huanghoufu -->
+       <activity
+            android:name=".Settings$BluetoothDashboardActivity">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.BLUETOOTH_DASHBOARD" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.connecteddevice.BluetoothDashboardFragment"/>
+           <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+       </activity>
+       <!-- end -->
+
+



















