android开发笔记之SubSettings界面跳转

来源:互联网 发布:netbeans 如何配置php 编辑:程序博客网 时间:2024/06/16 13:29

这里写图片描述

曾经的疑惑

作为一名软件开发工程师,曾经对于如何确认当前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界面跳转。

真的,我没有骗你。

0 0
原创粉丝点击