赞
踩
最近要修改Settings相关的东西,就顺便研究下Setings的代码结构,特做个记录
由于修改的是Android4.4的平台,所以以下都是在Android4.4基础上分析的。
从packages/apps/settings/AndroidManifestxml找到Settings模块的入口:
- <activity android:name="Settings"
- android:label="@string/settings_label_launcher"
- android:taskAffinity="com.android.settings"
- android:launchMode="singleTask">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <action android:name="android.settings.SETTINGS" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
说明进入settings的第一个Activity为Settings.java
settings继承与preverenceActivity,所以我们要主要两个重载函数onBuildHeaders和setListAdapter
onbuildHeaders负责加载xml布局文件,这里的xml文件settings_headers使用的是Preference Headers,没有使用传统的PreferenceScreen。
每个Header对应一个子界面,一般为Fragment
关于这点可以参考http://www.xuebuyuan.com/549370.html
- @Override
- public void onBuildHeaders(List<Header> headers) {
- if (!onIsHidingHeaders()) {
- loadHeadersFromResource(R.xml.settings_headers, headers);
- updateHeaderList(headers);
- }
- }
2)setListAdapter
PreferenceActivity继承于ListActivity,所以这里可以使用需要ListView创建Adapter,这里的自定义Adapter对不同子菜单的分别处理有关键性作用
@Override public void setListAdapter(ListAdapter adapter) { if (adapter == null) { super.setListAdapter(null); } else { DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper, dpm)); } }
自定义Adapter:
- private static class HeaderAdapter extends ArrayAdapter<Header> {
- static final int HEADER_TYPE_CATEGORY = 0;
- static final int HEADER_TYPE_NORMAL = 1;
- static final int HEADER_TYPE_SWITCH = 2;
- static final int HEADER_TYPE_BUTTON = 3;
- private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
-
- private final WifiEnabler mWifiEnabler;
- private final BluetoothEnabler mBluetoothEnabler;
- private AuthenticatorHelper mAuthHelper;
- private DevicePolicyManager mDevicePolicyManager;
-
- private static class HeaderViewHolder {
- ImageView icon;
- TextView title;
- TextView summary;
- Switch switch_;
- ImageButton button_;
- View divider_;
- }
-
- private LayoutInflater mInflater;
-
- static int getHeaderType(Header header) {
- if (header.fragment == null && header.intent == null) {
- return HEADER_TYPE_CATEGORY;
- } else if (header.id == R.id.security_settings) {
- return HEADER_TYPE_BUTTON;
- } else {
- return HEADER_TYPE_NORMAL;
- }
- }
-
- @Override
- public int getItemViewType(int position) {
- Header header = getItem(position);
- return getHeaderType(header);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false; // because of categories
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItemViewType(position) != HEADER_TYPE_CATEGORY;
- }
-
- @Override
- public int getViewTypeCount() {
- return HEADER_TYPE_COUNT;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public HeaderAdapter(Context context, List<Header> objects,
- AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
- super(context, 0, objects);
-
- mAuthHelper = authenticatorHelper;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- // Temp Switches provided as placeholder until the adapter replaces these with actual
- // Switches inflated from their layouts. Must be done before adapter is set in super
- mWifiEnabler = new WifiEnabler(context, new Switch(context));
- mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
- mDevicePolicyManager = dpm;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- HeaderViewHolder holder;
- Header header = getItem(position);
- int headerType = getHeaderType(header);
- View view = null;
-
- if (convertView == null) {
- holder = new HeaderViewHolder();
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- view = new TextView(getContext(), null,
- android.R.attr.listSeparatorTextViewStyle);
- holder.title = (TextView) view;
- break;
-
- case HEADER_TYPE_SWITCH:
- view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
- break;
-
- case HEADER_TYPE_BUTTON:
- view = mInflater.inflate(R.layout.preference_header_button_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.button_ = (ImageButton) view.findViewById(R.id.buttonWidget);
- holder.divider_ = view.findViewById(R.id.divider);
- break;
-
- case HEADER_TYPE_NORMAL:
- view = mInflater.inflate(
- R.layout.preference_header_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- break;
- }
- view.setTag(holder);
- } else {
- view = convertView;
- holder = (HeaderViewHolder) view.getTag();
- }
-
- // All view fields must be updated every time, because the view may be recycled
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- holder.title.setText(header.getTitle(getContext().getResources()));
- break;
-
- case HEADER_TYPE_SWITCH:
- // Would need a different treatment if the main menu had more switches
- if (header.id == R.id.wifi_settings) {
- mWifiEnabler.setSwitch(holder.switch_);
- } else {
- mBluetoothEnabler.setSwitch(holder.switch_);
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_BUTTON:
- if (header.id == R.id.security_settings) {
- boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
- if (hasCert) {
- holder.button_.setVisibility(View.VISIBLE);
- holder.divider_.setVisibility(View.VISIBLE);
- boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
- if (isManaged) {
- holder.button_.setImageResource(R.drawable.ic_settings_about);
- } else {
- holder.button_.setImageResource(
- android.R.drawable.stat_notify_error);
- }
- holder.button_.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(
- android.provider.Settings.ACTION_MONITORING_CERT_INFO);
- getContext().startActivity(intent);
- }
- });
- } else {
- holder.button_.setVisibility(View.GONE);
- holder.divider_.setVisibility(View.GONE);
- }
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_NORMAL:
- updateCommonHeaderView(header, holder);
- break;
- }
-
- return view;
- }
3、settings设置数据的保存
虽然preference是可以记录状态,并保存在sharedpreference文件中,但是有很多状态值是全局的,比如wifi,蓝牙等。所以这里涉及到全局数据的保存
以蓝牙为例,蓝牙打开关闭的操作在BluetoothEnabler.java里面
当按下蓝牙开关时,调用mLocalAdapter.setBluetoothEnabled(isChecked);-->BluetoothAdapter.enable()-->BluetoothAdapter:mManagerService.enable();-->BluetoothManagerService:enable-->BluetoothManagerService:persistBluetoothSetting
- private void persistBluetoothSetting(int value) {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.BLUETOOTH_ON,
- value);
- }
最终改的是Settings.Global.BLUETOOTH_ON的值,而这个默认值则在DatabaseHelper.java中设置
- loadBooleanSetting(stmt, Settings.Global.BLUETOOTH_ON,
- R.bool.def_bluetooth_on);
其他的值,比如wifi开关,默认语言等,都类似于这个过程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。