android开发笔记之SubSettings界面跳转

android开发笔记之SubSettings界面跳转_第1张图片

曾经的疑惑

作为一名软件开发工程师,曾经对于如何确认当前activity的详细信息非常想知道,后来学会了一个命令:

adb shell dumpsys activity | grep -i foc

可以方便的查看当前activity的详细信息。

但是,凡事最怕有例外

此命令一向所向披靡,帮助我解决了许多问题。但是在settings应用中,我发现了一个非常可怕的现象。在许多settings界面中,我发现此命令都是输出说当前界面的activity信息是com.android.settings/.SubSettings,命令如下:

 adb shell dumpsys activity | grep -i foc
  * ContentProviderRecord{41b0d010 u0 com.google.android.gms/.ads.adinfo.AdvertisingInfoContentProvider}
  mFocusedActivity: ActivityRecord{41b60318 u0 com.android.settings/.SubSettings t6}

也就是说settings应用中,许多settings界面都是说当前界面的activity信息为:com.android.settings/.SubSettings

why?

我不小心掉坑里了

然后有一个订单项目,说要从一个任意的地方要跳转了settings应用的其中一个界面Dual SIM setting。
非常的不幸,这个Dual SIM setting界面,我们使用命令:adb shell dumpsys activity | grep -i foc,读取此界面的activity信息,正好为com.android.settings/.SubSettings。

而三方apk说要找我们要跳转接口,这……,一个activity的界面跳转,随便一个开发小菜鸟都能搞定,为什么要找我们要跳转接口呢?后来才明白,其实原因非常简单,就是他们不知道怎么跳转界面。

我感觉非常搞笑,一个界面跳转都搞不定吗?
好吧,我来试试。顺便看一下为什么settings应用下的界面为什么都只显示为com.android.settings/.SubSettings。

我是如何解决此跳转接口的:

在settings应用的源码中裸泳了一下,再结合了一下systemui应用的下拉状态栏跳转方式(base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java——startSettingsActivity),

特别是我发现Wi-fi界面也是显示为SubSettings,但是可以跳转,我就特别参考了Wi-fi界面来实现此跳转界面了:

先直接把实现方法列在这吧:

AndroidManifest.xml——-实现定义一下DualSimSettingsActivity:

此完全是参考WifiSettingsActivity和wifi.WifiSettings,来定义双卡设置界面,这主要是为了后面的界面跳转:

<activity android:name="Settings$DualSimSettingsActivity" android:taskAffinity="" android:label="@string/dual_sim_title">
                 <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <action android:name="android.intent.action.VIEW"/>
                    <action android:name="android.intent.action.AIRPLANE_MODE"/>
                 </intent-filter>
                 <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.DualSimSettings" />
                 <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" android:resource="@id/dual_sim_settings" />
</activity>

<activity-alias android:name="DualSimSettings" android:label="@string/dual_sim_title" android:exported="true" android:taskAffinity="com.android.settings" android:targetActivity="Settings$DualSimSettingsActivity" >
                 <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.DualSimSettings" />
                 <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" android:resource="@id/dual_sim_settings" />
</activity-alias>

在Settings.java—–文件中定义DualSimSettingsActivity和其中的fragment(DualSimSettings)
apps/Settings/src/com/android/settings/Settings.java

修改记录:

 import com.android.settings.wifi.AdvancedWifiSettings;
 import com.android.settings.wifi.WifiEnabler;
 import com.android.settings.wifi.WifiSettings;
 //这个主要是引入DualSimSettings定义
+import com.android.settings.DualSimSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
 import com.android.settings.audioprofile.AudioProfileSettings;

@@ -321,6 +322,7 @@ public class Settings extends PreferenceActivity private static final String[] ENTRY_FRAGMENTS = {
         WirelessSettings.class.getName(),
         WifiSettings.class.getName(),
          //这个主要是定义DualSimSettingsActivity中的frgments为DualSimSettings
+        DualSimSettings.class.getName(),
         AdvancedWifiSettings.class.getName(),
         BluetoothSettings.class.getName(),
         TetherSettings.class.getName(),
@@ -523,6 +525,7 @@ public class Settings extends PreferenceActivity // Some fragments want split ActionBar; these should stay in sync with
         // uiOptions for fragments also defined as activities in manifest.
         if (WifiSettings.class.getName().equals(fragmentName) ||
                   //这个主要是定义DualSimSettingsActivity中的frgments为DualSimSettings
+                DualSimSettings.class.getName().equals(fragmentName) ||
                 WifiP2pSettings.class.getName().equals(fragmentName) ||
                 BluetoothSettings.class.getName().equals(fragmentName) ||
                 DreamSettings.class.getName().equals(fragmentName) ||
@@ -1135,6 +1138,7 @@ public class Settings extends PreferenceActivity //public static class SchedulePowerOnOffActivity extends Settings { /* empty */ }
     public static class StorageSettingsActivity extends Settings { /* empty */ }
     public static class WifiSettingsActivity extends Settings { /* empty */ }
     //这个主要是定义DualSimSettingsActivity
+    public static class DualSimSettingsActivity extends Settings { /* empty */ }
     public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
     public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
     public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }

好了,准备工作做好了,下面就是正常的activity界面跳转了:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.android.settings",
                "com.android.settings.Settings$DualSimSettingsActivity"));
startActivity(intent);

ok,打完收工。界面可以像我们平常的activity跳转了。

任何一个小菜鸟都可以直接跳转了。

曾经的疑惑之释疑

看完settings应用的源码后,我们明白了为什么在settings界面下有这么多界面的activity信息为subsettings。

原因非常简单:

就是在./apps/Settings/src/com/android/settings/Settings.java文件中:
我们跳转到了SubSettings中了。
intent.setClass(this, SubSettings.class);

public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
            int titleRes, int shortTitleRes) {
        Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
                titleRes, shortTitleRes);

        // Some fragments want split ActionBar; these should stay in sync with
        // uiOptions for fragments also defined as activities in manifest.
        if (WifiSettings.class.getName().equals(fragmentName) ||
                DualSimSettings.class.getName().equals(fragmentName) ||
                WifiP2pSettings.class.getName().equals(fragmentName) ||
                BluetoothSettings.class.getName().equals(fragmentName) ||
                DreamSettings.class.getName().equals(fragmentName) ||
                LocationSettings.class.getName().equals(fragmentName) ||
                ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
                PrintSettingsFragment.class.getName().equals(fragmentName) ||
                PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
            intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
        }

        intent.setClass(this, SubSettings.class);
        return intent;
    }

而SubSettings 就继承至Settings,(SubSettings extends Settings),Settings是继承至PreferenceActivity(Settings extends PreferenceActivity)。

也就是说Subsettings就是当前的activity。只是这个Subsettings和一般的activity不一样,他添加不同的fragment就显示不同的界面,但是他本身还是Subsettings。

我们在./apps/Settings/res/xml/settings_headers.xml可以看到settings主要界面布局:

    <!-- Dual SIM Settings -->
    <!-- 这是双卡设置的fragment -->
    <header  android:id="@+id/dual_sim_settings" android:fragment="com.android.settings.DualSimSettings" android:icon="@drawable/ic_settings_dualsim" android:title="@string/dual_sim_title">
        <intent android:action="android.intent.action.MAIN"/>

    </header>

    <!-- Wifi -->
    <!-- 这是wifi设置的fragment -->
    <header  android:id="@+id/wifi_settings" android:fragment="com.android.settings.wifi.WifiSettings" android:title="@string/wifi_settings_title" android:icon="@drawable/ic_settings_wireless" />

然后,我们可以仿照上面的方法,任意的一个SubSettings界面跳转。

真的,我没有骗你。

你可能感兴趣的:(android,Settings,subsetting)