Android 6.0 Setting模块解析(一)
这几天在学习 Android Settings 设置菜单的相关内容,原本打算一篇搞定,谁知入坑后发现 Android 6.0、7.0、8.0 设置菜单的加载方式各有千秋,妈耶,好坑,所以接下来我会从 6.0、7.0、8.0 去分别分析设置界面是怎么加载出来的。预计会分为三篇,本篇是第一篇 6.0 分析,下面请各位跟我的教程一步步走,喂喂喂!!说你呢,小本本拿好,我要开讲啦!!
前言
偷偷告诉你 Android 源码和本篇文章结合起来看效果更好哦。
Android 源码查看地址:https://www.androidos.net.cn/sourcecode 。
另外本系列文章所涉及的所有 Android 源码在此网站上都可以找到,最后来看看 6.0 系统的设置菜单到底长什么样,瞅图:
6.0设置界面加载
首先我们来看 Settings 模块中的 AndroidManifest.xml 文件,这里会展示四大组件,默认启动入口Activity等信息,具体路径如下:/packages/apps/Settings/AndroidManifest.xml。
···
<activity android:name="Settings"
android:taskAffinity="com.android.settings"
android:label="@string/settings_label_launcher"
android:launchMode="singleTask">
<intent-filter android:priority="1">
<action android:name="android.settings.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
//activity-alias可用来设置某个Activity的快捷入口,可以放在桌面上或者通过该别名被其他组件快速调起。
//android:targetActivity为目标Activity.
<activity-alias android:name="Settings"
android:taskAffinity="com.android.settings" android:label="@string/settings_label_launcher"
android:launchMode="singleTask"
android:targetActivity="Settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
···
可以看出入口Activity为Settings。
Settings
具体路径:/packages/apps/Settings/src/com/android/settings/Settings.java
public class Settings extends SettingsActivity {
public static class BluetoothSettingsActivity extends SettingsActivity {
/* empty */ }
public static class WirelessSettingsActivity extends SettingsActivity {
/* empty */ }
public static class SimSettingsActivity extends SettingsActivity {
/* empty */ }
···
}
可以看出 Settings 继承于 SettingsActivity ,而且其内部都是类的空实现。所以我们看其父类 SettingsActivity。
SettingsActivity
查看其类会发现,SettingsActivity 便是加载菜单的主 Activity。
它的具体路径为:/packages/apps/Settings/src/com/android/settings/SettingsActivity.java
首先来分析 onCreate() 方法
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
···
//获取AndroidManiFest.xml中mate数据,从Settings(或桌面快捷图标)进入时获取是null
getMetaData();
//布局窗口UI
final Intent intent = getIntent();
if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
}
···
}
getMetaData() 代码如下
private void getMetaData() {
try {
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
if (ai == null || ai.metaData == null) return;
//private static final String META_DATA_KEY_FRAGMENT_CLASS =
//"com.android.settings.FRAGMENT_CLASS";
mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
} catch (NameNotFoundException nnfe) {
···
}
}
由此可知,getMetaData() 会在加载对应的设置项时会从 节点下获取到 fragmentclass 的值,即为含有 com.android.settings.FRAGMENT_CLASS 标签的值,进行加载。
接下来看getIntent()代码: