User management screens

Customized Settings for restricted users
- Only some top-level settings panels available

User management
- Primary user can add and remove users
- User details screen to change name and list of enabled apps

Change-Id: Ia6beb991b427197a4ec2724ca3c9222073f6cf7d
This commit is contained in:
Amith Yamasani
2012-03-25 10:12:26 -07:00
parent 7014dbca85
commit b810a0ddf9
11 changed files with 600 additions and 13 deletions

View File

@@ -11,6 +11,7 @@
-keep class com.android.settings.MasterClearConfirm -keep class com.android.settings.MasterClearConfirm
-keep class com.android.settings.accounts.* -keep class com.android.settings.accounts.*
-keep class com.android.settings.fuelgauge.* -keep class com.android.settings.fuelgauge.*
-keep class com.android.settings.users.*
# Keep click responders # Keep click responders
-keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity { -keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity {

View File

@@ -724,4 +724,22 @@
<!-- Status message when VPN is failed. --> <!-- Status message when VPN is failed. -->
<item>Unsuccessful</item> <item>Unsuccessful</item>
</string-array> </string-array>
<!-- User content ratings for restricted users [CHAR LIMIT=30] -->
<string-array name="user_content_ratings_entries">
<item>Ascended being</item>
<item>Human</item>
<item>Neanderthal</item>
<item>Chimp</item>
<item>Monkey</item>
</string-array>
<!-- Values for user content ratings for restricted users -->
<string-array name="user_content_ratings_values" translatable="false">
<item>5</item>
<item>4</item>
<item>3</item>
<item>2</item>
<item>1</item>
</string-array>
</resources> </resources>

View File

@@ -29,4 +29,7 @@
<!-- Whether the bluetooth activation confirmation dialogs should be auto dismissed. <!-- Whether the bluetooth activation confirmation dialogs should be auto dismissed.
Can be overridden for specific product builds. --> Can be overridden for specific product builds. -->
<bool name="auto_confirm_bluetooth_activation_dialog">false</bool> <bool name="auto_confirm_bluetooth_activation_dialog">false</bool>
<!-- Whether User management screen is available -->
<bool name="enable_user_management">false</bool>
</resources> </resources>

View File

@@ -3854,4 +3854,43 @@
"system_update_settings_list_item_title" in this project. [CHAR LIMIT=25] --> "system_update_settings_list_item_title" in this project. [CHAR LIMIT=25] -->
<string name="additional_system_update_settings_list_item_title">Additional system updates</string> <string name="additional_system_update_settings_list_item_title">Additional system updates</string>
<!-- User settings -->
<skip/>
<!-- User settings screen title [CHAR LIMIT=25] -->
<string name="user_settings_title">Users &amp; restrictions</string>
<!-- User settings user list section header [CHAR LIMIT=30] -->
<string name="user_list_title">Users</string>
<!-- User settings add user menu [CHAR LIMIT=20] -->
<string name="user_add_user_menu">Add user</string>
<!-- User details -->
<skip/>
<!-- User details screen title [CHAR LIMIT=25] -->
<string name="user_details_title">Edit details</string>
<!-- User information section title [CHAR LIMIT=30] -->
<string name="user_information_heading">User information</string>
<!-- User name title [CHAR LIMIT=25] -->
<string name="user_name_title">Name</string>
<!-- User restrictions section title [CHAR LIMIT=30] -->
<string name="user_restrictions_heading">Content restrictions</string>
<!-- User restrictions, does market require PIN protection [CHAR LIMIT=25] -->
<string name="user_market_requires_pin">Downloads require PIN</string>
<!-- User restrictions, maximum content rating for apps [CHAR LIMIT=25] -->
<string name="user_max_content_rating">Content rating</string>
<!-- Section title for list of system apps [CHAR LIMIT=30] -->
<string name="user_system_apps_heading">System apps to enable</string>
<!-- Section title for list of downloaded apps [CHAR LIMIT=30] -->
<string name="user_market_apps_heading">Installed apps to enable</string>
<!-- User details discard user menu [CHAR LIMIT=20] -->
<string name="user_discard_user_menu">Discard</string>
<!-- User details remove user menu [CHAR LIMIT=20] -->
<string name="user_remove_user_menu">Remove user</string>
<!-- User details new user name [CHAR LIMIT=30] -->
<string name="user_new_user_name">Pesky kid</string>
<!-- User removal confirmation title [CHAR LIMIT=25] -->
<string name="user_confirm_remove_title">Remove user?</string>
<!-- User removal confirmation message [CHAR LIMIT=none] -->
<string name="user_confirm_remove_message">Are you sure you want to remove the user and all associated data from the device?</string>
</resources> </resources>

View File

@@ -106,6 +106,13 @@
<!-- PERSONAL --> <!-- PERSONAL -->
<header android:title="@string/header_category_personal" /> <header android:title="@string/header_category_personal" />
<!-- Manage users -->
<header
android:fragment="com.android.settings.users.UserSettings"
android:icon="@drawable/ic_settings_sync"
android:title="@string/user_settings_title"
android:id="@+id/user_settings" />
<!-- Data Sync. The settings activity will ensure this is resolved to an <!-- Data Sync. The settings activity will ensure this is resolved to an
activity on the system image, otherwise it will remove this activity on the system image, otherwise it will remove this
preference. --> preference. -->

62
res/xml/user_details.xml Normal file
View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/user_details_title">
<PreferenceCategory
android:key="information_category"
android:title="@string/user_information_heading">
<EditTextPreference
android:key="user_name"
android:title="@string/user_name_title"
android:persistent="false"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="restrictions_category"
android:title="@string/user_restrictions_heading">
<CheckBoxPreference
android:key="market_requires_pin"
android:title="@string/user_market_requires_pin"
android:persistent="false"
android:enabled="false"
/>
<ListPreference
android:key="content_rating"
android:title="@string/user_max_content_rating"
android:entries="@array/user_content_ratings_entries"
android:entryValues="@array/user_content_ratings_values"
android:persistent="false"
android:enabled="false"
/>
</PreferenceCategory>
<PreferenceCategory
android:key="system_apps_category"
android:title="@string/user_system_apps_heading">
<!-- Dynamically added content -->
</PreferenceCategory>
<PreferenceCategory
android:key="market_apps_category"
android:title="@string/user_market_apps_heading">
<!-- Dynamically added content -->
</PreferenceCategory>
</PreferenceScreen>

26
res/xml/user_settings.xml Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/user_settings_title">
<PreferenceCategory
android:key="user_list"
android:title="@string/user_list_title">
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserId;
import android.os.Vibrator; import android.os.Vibrator;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
@@ -140,6 +141,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
DevicePolicyManager dpm = DevicePolicyManager dpm =
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
if (UserId.myUserId() == 0) {
switch (dpm.getStorageEncryptionStatus()) { switch (dpm.getStorageEncryptionStatus()) {
case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
// The device is currently encrypted. // The device is currently encrypted.
@@ -150,6 +152,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
addPreferencesFromResource(R.xml.security_settings_unencrypted); addPreferencesFromResource(R.xml.security_settings_unencrypted);
break; break;
} }
}
// lock after preference // lock after preference
mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT); mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
@@ -190,6 +193,11 @@ public class SecuritySettings extends SettingsPreferenceFragment
} }
} }
if (UserId.myUserId() > 0) {
return root;
}
// Rest are for primary user...
// Append the rest of the settings // Append the rest of the settings
addPreferencesFromResource(R.xml.security_settings_misc); addPreferencesFromResource(R.xml.security_settings_misc);
@@ -246,9 +254,11 @@ public class SecuritySettings extends SettingsPreferenceFragment
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) { if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) {
setNonMarketAppsAllowed(true); setNonMarketAppsAllowed(true);
if (mToggleAppInstallation != null) {
mToggleAppInstallation.setChecked(true); mToggleAppInstallation.setChecked(true);
} }
} }
}
@Override @Override
public void onDestroy() { public void onDestroy() {
@@ -343,12 +353,16 @@ public class SecuritySettings extends SettingsPreferenceFragment
mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks()); mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks());
} }
if (mShowPassword != null) {
mShowPassword.setChecked(Settings.System.getInt(getContentResolver(), mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
}
KeyStore.State state = KeyStore.getInstance().state(); KeyStore.State state = KeyStore.getInstance().state();
if (mResetCredentials != null) {
mResetCredentials.setEnabled(state != KeyStore.State.UNINITIALIZED); mResetCredentials.setEnabled(state != KeyStore.State.UNINITIALIZED);
} }
}
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {

View File

@@ -16,6 +16,7 @@
package com.android.settings; package com.android.settings;
import com.android.internal.util.ArrayUtils;
import com.android.settings.accounts.AccountSyncSettings; import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.bluetooth.BluetoothEnabler; import com.android.settings.bluetooth.BluetoothEnabler;
import com.android.settings.deviceinfo.Memory; import com.android.settings.deviceinfo.Memory;
@@ -29,6 +30,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserId;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
@@ -76,6 +78,17 @@ public class Settings extends PreferenceActivity implements ButtonBarHandler {
private Header mParentHeader; private Header mParentHeader;
private boolean mInLocalHeaderSwitch; private boolean mInLocalHeaderSwitch;
// Show only these settings for restricted users
private int[] SETTINGS_FOR_RESTRICTED = {
R.id.wifi_settings,
R.id.bluetooth_settings,
R.id.sound_settings,
R.id.display_settings,
//R.id.security_settings,
R.id.sync_settings,
R.id.about_settings
};
// TODO: Update Call Settings based on airplane mode state. // TODO: Update Call Settings based on airplane mode state.
protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>(); protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
@@ -337,6 +350,16 @@ public class Settings extends PreferenceActivity implements ButtonBarHandler {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) { if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
target.remove(header); target.remove(header);
} }
} else if (id == R.id.user_settings) {
if (!UserId.MU_ENABLED || UserId.myUserId() != 0
|| !getResources().getBoolean(R.bool.enable_user_management)
|| Utils.isMonkeyRunning()) {
target.remove(header);
}
}
if (UserId.MU_ENABLED && UserId.myUserId() != 0
&& !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
target.remove(header);
} }
// Increment if the current one wasn't removed by the Utils code. // Increment if the current one wasn't removed by the Utils code.

View File

@@ -0,0 +1,285 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.users;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import java.util.HashMap;
import java.util.List;
public class UserDetailsSettings extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener, DialogCreatable {
private static final String TAG = "UserDetailsSettings";
private static final int MENU_REMOVE_USER = Menu.FIRST;
private static final int DIALOG_CONFIRM_REMOVE = 1;
private static final String KEY_USER_NAME = "user_name";
private static final String KEY_INSTALLED_APPS = "market_apps_category";
private static final String KEY_SYSTEM_APPS = "system_apps_category";
public static final String EXTRA_USER_ID = "user_id";
private static final String[] SYSTEM_APPS = {
"com.google.android.browser",
"com.google.android.gm",
"com.google.android.youtube"
};
static class AppState {
boolean dirty;
boolean enabled;
AppState(boolean enabled) {
this.enabled = enabled;
}
}
private HashMap<String, AppState> mAppStates = new HashMap<String, AppState>();
private PreferenceGroup mSystemAppGroup;
private PreferenceGroup mInstalledAppGroup;
private EditTextPreference mNamePref;
private IPackageManager mIPm;
private PackageManager mPm;
private int mUserId;
private boolean mNewUser;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.user_details);
Bundle args = getArguments();
mNewUser = args == null || args.getInt(EXTRA_USER_ID, -1) == -1;
mUserId = mNewUser ? -1 : args.getInt(EXTRA_USER_ID, -1);
mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
if (mUserId == -1) {
try {
mUserId = mIPm.createUser(getString(R.string.user_new_user_name), 0).id;
} catch (RemoteException re) {
}
}
mSystemAppGroup = (PreferenceGroup) findPreference(KEY_SYSTEM_APPS);
mInstalledAppGroup = (PreferenceGroup) findPreference(KEY_INSTALLED_APPS);
mNamePref = (EditTextPreference) findPreference(KEY_USER_NAME);
mNamePref.setOnPreferenceChangeListener(this);
setHasOptionsMenu(true);
}
@Override
public void onResume() {
super.onResume();
mPm = getActivity().getPackageManager();
if (mUserId > 0) {
initExistingUser();
} else {
initNewUser();
}
refreshApps();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem addAccountItem = menu.add(0, MENU_REMOVE_USER, 0,
mNewUser ? R.string.user_discard_user_menu : R.string.user_remove_user_menu);
addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int itemId = item.getItemId();
if (itemId == MENU_REMOVE_USER) {
onRemoveUserClicked();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void initExistingUser() {
List<UserInfo> users = mPm.getUsers();
UserInfo foundUser = null;
for (UserInfo user : users) {
if (user.id == mUserId) {
foundUser = user;
break;
}
}
if (foundUser != null) {
mNamePref.setSummary(foundUser.name);
mNamePref.setText(foundUser.name);
}
}
private void initNewUser() {
// TODO: Check if there's already a "New user" and localize
mNamePref.setText(getString(R.string.user_new_user_name));
mNamePref.setSummary(getString(R.string.user_new_user_name));
}
private void onRemoveUserClicked() {
if (mNewUser) {
removeUserNow();
} else {
showDialog(DIALOG_CONFIRM_REMOVE);
}
}
private void removeUserNow() {
try {
mIPm.removeUser(mUserId);
} catch (RemoteException re) {
// Couldn't remove user. Shouldn't happen
Log.e(TAG, "Couldn't remove user " + mUserId + "\n" + re);
}
finish();
}
private void insertAppInfo(PreferenceGroup group, HashMap<String, AppState> appStateMap,
PackageInfo info, boolean defaultState) {
if (info != null) {
String pkgName = info.packageName;
String name = info.applicationInfo.loadLabel(mPm).toString();
Drawable icon = info.applicationInfo.loadIcon(mPm);
AppState appState = appStateMap.get(info.packageName);
boolean enabled = appState == null ? defaultState : appState.enabled;
CheckBoxPreference appPref = new CheckBoxPreference(getActivity());
appPref.setTitle(name != null ? name : pkgName);
appPref.setIcon(icon);
appPref.setChecked(enabled);
appPref.setKey(pkgName);
appPref.setPersistent(false);
appPref.setOnPreferenceChangeListener(this);
group.addPreference(appPref);
}
}
private void refreshApps() {
mSystemAppGroup.removeAll();
mInstalledAppGroup.removeAll();
boolean firstTime = mAppStates.isEmpty();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> apps = mPm.queryIntentActivities(mainIntent, 0);
for (ResolveInfo resolveInfo : apps) {
PackageInfo info;
try {
info = mIPm.getPackageInfo(resolveInfo.activityInfo.packageName,
0 /* flags */,
mUserId < 0 ? 0 : mUserId);
} catch (RemoteException re) {
continue;
}
if (firstTime) {
mAppStates.put(resolveInfo.activityInfo.packageName,
new AppState(info.applicationInfo.enabled));
}
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (mSystemAppGroup.findPreference(info.packageName) != null) {
continue;
}
insertAppInfo(mSystemAppGroup, mAppStates, info, false);
} else {
if (mInstalledAppGroup.findPreference(info.packageName) != null) {
continue;
}
insertAppInfo(mInstalledAppGroup, mAppStates, info, false);
}
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference instanceof CheckBoxPreference) {
String packageName = preference.getKey();
int newState = ((Boolean) newValue) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
try {
mIPm.setApplicationEnabledSetting(packageName, newState, 0, mUserId);
} catch (RemoteException re) {
Log.e(TAG, "Unable to change enabled state of package " + packageName
+ " for user " + mUserId);
}
} else if (preference == mNamePref) {
String name = (String) newValue;
if (TextUtils.isEmpty(name)) {
return false;
}
try {
mIPm.updateUserName(mUserId, (String) newValue);
mNamePref.setSummary((String) newValue);
} catch (RemoteException re) {
return false;
}
}
return true;
}
@Override
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DIALOG_CONFIRM_REMOVE:
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.user_confirm_remove_title)
.setMessage(R.string.user_confirm_remove_message)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
removeUserNow();
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
default:
return null;
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.users;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import java.util.List;
public class UserSettings extends SettingsPreferenceFragment
implements OnPreferenceClickListener {
private static final String KEY_USER_LIST = "user_list";
private static final int MENU_ADD_USER = Menu.FIRST;
private PreferenceGroup mUserListCategory;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.user_settings);
mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
setHasOptionsMenu(true);
}
@Override
public void onResume() {
super.onResume();
updateUserList();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem addAccountItem = menu.add(0, MENU_ADD_USER, 0, R.string.user_add_user_menu);
addAccountItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int itemId = item.getItemId();
if (itemId == MENU_ADD_USER) {
onAddUserClicked();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void onAddUserClicked() {
((PreferenceActivity) getActivity()).startPreferencePanel(
UserDetailsSettings.class.getName(), null, R.string.user_details_title,
null, this, 0);
}
private void updateUserList() {
List<UserInfo> users = getActivity().getPackageManager().getUsers();
mUserListCategory.removeAll();
for (UserInfo user : users) {
if (user.id == 0) continue;
Preference pref = new Preference(getActivity());
pref.setTitle(user.name);
pref.setOnPreferenceClickListener(this);
pref.setKey("id=" + user.id);
mUserListCategory.addPreference(pref);
}
}
@Override
public boolean onPreferenceClick(Preference pref) {
String sid = pref.getKey();
if (sid != null && sid.startsWith("id=")) {
int id = Integer.parseInt(sid.substring(3));
Bundle args = new Bundle();
args.putInt(UserDetailsSettings.EXTRA_USER_ID, id);
((PreferenceActivity) getActivity()).startPreferencePanel(
UserDetailsSettings.class.getName(),
args, 0, pref.getTitle(), this, 0);
return true;
}
return false;
}
}