Skip to content

Commit 836033d

Browse files
jatinlodhiaAndroid (Google) Code Review
authored andcommitted
Merge "Update account list on account picker activity resume" into jb-mr1-dev
2 parents a87826c + 8d16778 commit 836033d

File tree

1 file changed

+169
-117
lines changed

1 file changed

+169
-117
lines changed

core/java/android/accounts/ChooseTypeAndAccountActivity.java

Lines changed: 169 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package android.accounts;
1717

18+
import com.google.android.collect.Sets;
19+
1820
import android.app.Activity;
1921
import android.content.Intent;
2022
import android.os.Bundle;
@@ -105,6 +107,13 @@ public class ChooseTypeAndAccountActivity extends Activity
105107

106108
private static final int SELECTED_ITEM_NONE = -1;
107109

110+
private Set<Account> mSetOfAllowableAccounts;
111+
private Set<String> mSetOfRelevantAccountTypes;
112+
private String mSelectedAccountName = null;
113+
private boolean mSelectedAddNewAccount = false;
114+
private boolean mAlwaysPromptForAccount = false;
115+
private String mDescriptionOverride;
116+
108117
private ArrayList<Account> mAccounts;
109118
private int mPendingRequest = REQUEST_NULL;
110119
private Parcelable[] mExistingAccounts = null;
@@ -120,22 +129,18 @@ public void onCreate(Bundle savedInstanceState) {
120129
}
121130

122131
// save some items we use frequently
123-
final AccountManager accountManager = AccountManager.get(this);
124132
final Intent intent = getIntent();
125133

126-
String selectedAccountName = null;
127-
boolean selectedAddNewAccount = false;
128-
129134
if (savedInstanceState != null) {
130135
mPendingRequest = savedInstanceState.getInt(KEY_INSTANCE_STATE_PENDING_REQUEST);
131136
mExistingAccounts =
132137
savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS);
133138

134139
// Makes sure that any user selection is preserved across orientation changes.
135-
selectedAccountName = savedInstanceState.getString(
140+
mSelectedAccountName = savedInstanceState.getString(
136141
KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);
137142

138-
selectedAddNewAccount = savedInstanceState.getBoolean(
143+
mSelectedAddNewAccount = savedInstanceState.getBoolean(
139144
KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
140145
} else {
141146
mPendingRequest = REQUEST_NULL;
@@ -144,147 +149,61 @@ public void onCreate(Bundle savedInstanceState) {
144149
// show is as pre-selected.
145150
Account selectedAccount = (Account) intent.getParcelableExtra(EXTRA_SELECTED_ACCOUNT);
146151
if (selectedAccount != null) {
147-
selectedAccountName = selectedAccount.name;
152+
mSelectedAccountName = selectedAccount.name;
148153
}
149154
}
150155

151156
if (Log.isLoggable(TAG, Log.VERBOSE)) {
152-
Log.v(TAG, "selected account name is " + selectedAccountName);
157+
Log.v(TAG, "selected account name is " + mSelectedAccountName);
153158
}
154159

155-
// build an efficiently queryable map of account types to authenticator descriptions
156-
final HashMap<String, AuthenticatorDescription> typeToAuthDescription =
157-
new HashMap<String, AuthenticatorDescription>();
158-
for(AuthenticatorDescription desc : accountManager.getAuthenticatorTypes()) {
159-
typeToAuthDescription.put(desc.type, desc);
160-
}
161-
162-
// Read the validAccounts, if present, and add them to the setOfAllowableAccounts
163-
Set<Account> setOfAllowableAccounts = null;
164-
final ArrayList<Parcelable> validAccounts =
165-
intent.getParcelableArrayListExtra(EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST);
166-
if (validAccounts != null) {
167-
setOfAllowableAccounts = new HashSet<Account>(validAccounts.size());
168-
for (Parcelable parcelable : validAccounts) {
169-
setOfAllowableAccounts.add((Account)parcelable);
170-
}
171-
}
172160

173-
// An account type is relevant iff it is allowed by the caller and supported by the account
174-
// manager.
175-
Set<String> setOfRelevantAccountTypes = null;
176-
final String[] allowedAccountTypes =
177-
intent.getStringArrayExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
178-
if (allowedAccountTypes != null) {
179-
180-
setOfRelevantAccountTypes = new HashSet<String>(allowedAccountTypes.length);
181-
Set<String> setOfAllowedAccountTypes = new HashSet<String>(allowedAccountTypes.length);
182-
for (String type : allowedAccountTypes) {
183-
setOfAllowedAccountTypes.add(type);
184-
}
185-
186-
AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
187-
Set<String> supportedAccountTypes = new HashSet<String>(descs.length);
188-
for (AuthenticatorDescription desc : descs) {
189-
supportedAccountTypes.add(desc.type);
190-
}
161+
mSetOfAllowableAccounts = getAllowableAccountSet(intent);
162+
mSetOfRelevantAccountTypes = getReleventAccountTypes(intent);
163+
mAlwaysPromptForAccount = intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false);
164+
mDescriptionOverride = intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
165+
}
191166

192-
for (String acctType : setOfAllowedAccountTypes) {
193-
if (supportedAccountTypes.contains(acctType)) {
194-
setOfRelevantAccountTypes.add(acctType);
195-
}
196-
}
197-
}
167+
@Override
168+
protected void onResume() {
169+
super.onResume();
170+
final AccountManager accountManager = AccountManager.get(this);
198171

199-
// Create a list of AccountInfo objects for each account that is allowable. Filter out
200-
// accounts that don't match the allowable types, if provided, or that don't match the
201-
// allowable accounts, if provided.
202-
final Account[] accounts = accountManager.getAccounts();
203-
mAccounts = new ArrayList<Account>(accounts.length);
204-
mSelectedItemIndex = SELECTED_ITEM_NONE;
205-
for (Account account : accounts) {
206-
if (setOfAllowableAccounts != null
207-
&& !setOfAllowableAccounts.contains(account)) {
208-
continue;
209-
}
210-
if (setOfRelevantAccountTypes != null
211-
&& !setOfRelevantAccountTypes.contains(account.type)) {
212-
continue;
213-
}
214-
if (account.name.equals(selectedAccountName)) {
215-
mSelectedItemIndex = mAccounts.size();
216-
}
217-
mAccounts.add(account);
218-
}
172+
mAccounts = getAcceptableAccountChoices(accountManager);
219173

174+
// In cases where the activity does not need to show an account picker, cut the chase
175+
// and return the result directly. Eg:
176+
// Single account -> select it directly
177+
// No account -> launch add account activity directly
220178
if (mPendingRequest == REQUEST_NULL) {
221179
// If there are no relevant accounts and only one relevant account type go directly to
222180
// add account. Otherwise let the user choose.
223181
if (mAccounts.isEmpty()) {
224-
if (setOfRelevantAccountTypes.size() == 1) {
225-
runAddAccountForAuthenticator(setOfRelevantAccountTypes.iterator().next());
182+
if (mSetOfRelevantAccountTypes.size() == 1) {
183+
runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
226184
} else {
227185
startChooseAccountTypeActivity();
228186
}
229187
return;
230188
}
231189

232190
// if there is only one allowable account return it
233-
if (!intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false)
234-
&& mAccounts.size() == 1) {
191+
if (!mAlwaysPromptForAccount && mAccounts.size() == 1) {
235192
Account account = mAccounts.get(0);
236193
setResultAndFinish(account.name, account.type);
237194
return;
238195
}
239196
}
240197

198+
String[] listItems = getListOfDisplayableOptions(mAccounts);
199+
mSelectedItemIndex = getItemIndexToSelect(
200+
mAccounts, mSelectedAccountName, mSelectedAddNewAccount);
201+
241202
// Cannot set content view until we know that mPendingRequest is not null, otherwise
242203
// would cause screen flicker.
243204
setContentView(R.layout.choose_type_and_account);
244-
245-
// Override the description text if supplied
246-
final String descriptionOverride =
247-
intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
248-
TextView descriptionView = (TextView) findViewById(R.id.description);
249-
if (!TextUtils.isEmpty(descriptionOverride)) {
250-
descriptionView.setText(descriptionOverride);
251-
} else {
252-
descriptionView.setVisibility(View.GONE);
253-
}
254-
255-
// List of options includes all accounts found together with "Add new account" as the
256-
// last item in the list.
257-
String[] listItems = new String[mAccounts.size() + 1];
258-
for (int i = 0; i < mAccounts.size(); i++) {
259-
listItems[i] = mAccounts.get(i).name;
260-
}
261-
listItems[mAccounts.size()] = getResources().getString(
262-
R.string.add_account_button_label);
263-
264-
ListView list = (ListView) findViewById(android.R.id.list);
265-
list.setAdapter(new ArrayAdapter<String>(this,
266-
android.R.layout.simple_list_item_single_choice, listItems));
267-
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
268-
list.setItemsCanFocus(false);
269-
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
270-
@Override
271-
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
272-
mSelectedItemIndex = position;
273-
mOkButton.setEnabled(true);
274-
}
275-
});
276-
277-
// If "Add account" option was previously selected by user, preserve it across
278-
// orientation changes.
279-
if (selectedAddNewAccount) {
280-
mSelectedItemIndex = mAccounts.size();
281-
}
282-
if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
283-
list.setItemChecked(mSelectedItemIndex, true);
284-
if (Log.isLoggable(TAG, Log.VERBOSE)) {
285-
Log.v(TAG, "List item " + mSelectedItemIndex + " should be selected");
286-
}
287-
}
205+
overrideDescriptionIfSupplied(mDescriptionOverride);
206+
populateUIAccountList(listItems);
288207

289208
// Only enable "OK" button if something has been selected.
290209
mOkButton = (Button) findViewById(android.R.id.button2);
@@ -480,4 +399,137 @@ private void startChooseAccountTypeActivity() {
480399
startActivityForResult(intent, REQUEST_CHOOSE_TYPE);
481400
mPendingRequest = REQUEST_CHOOSE_TYPE;
482401
}
402+
403+
/**
404+
* @return a value between 0 (inclusive) and accounts.size() (inclusive) or SELECTED_ITEM_NONE.
405+
* An index value of accounts.size() indicates 'Add account' option.
406+
*/
407+
private int getItemIndexToSelect(ArrayList<Account> accounts, String selectedAccountName,
408+
boolean selectedAddNewAccount) {
409+
// If "Add account" option was previously selected by user, preserve it across
410+
// orientation changes.
411+
if (selectedAddNewAccount) {
412+
return accounts.size();
413+
}
414+
// search for the selected account name if present
415+
for (int i = 0; i < accounts.size(); i++) {
416+
if (accounts.get(i).name.equals(selectedAccountName)) {
417+
return i;
418+
}
419+
}
420+
// no account selected.
421+
return SELECTED_ITEM_NONE;
422+
}
423+
424+
private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) {
425+
// List of options includes all accounts found together with "Add new account" as the
426+
// last item in the list.
427+
String[] listItems = new String[accounts.size() + 1];
428+
for (int i = 0; i < accounts.size(); i++) {
429+
listItems[i] = accounts.get(i).name;
430+
}
431+
listItems[accounts.size()] = getResources().getString(
432+
R.string.add_account_button_label);
433+
return listItems;
434+
}
435+
436+
/**
437+
* Create a list of Account objects for each account that is acceptable. Filter out
438+
* accounts that don't match the allowable types, if provided, or that don't match the
439+
* allowable accounts, if provided.
440+
*/
441+
private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
442+
final Account[] accounts = accountManager.getAccounts();
443+
ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
444+
for (Account account : accounts) {
445+
if (mSetOfAllowableAccounts != null
446+
&& !mSetOfAllowableAccounts.contains(account)) {
447+
continue;
448+
}
449+
if (mSetOfRelevantAccountTypes != null
450+
&& !mSetOfRelevantAccountTypes.contains(account.type)) {
451+
continue;
452+
}
453+
accountsToPopulate.add(account);
454+
}
455+
return accountsToPopulate;
456+
}
457+
458+
/**
459+
* Return a set of account types speficied by the intent as well as supported by the
460+
* AccountManager.
461+
*/
462+
private Set<String> getReleventAccountTypes(final Intent intent) {
463+
// An account type is relevant iff it is allowed by the caller and supported by the account
464+
// manager.
465+
Set<String> setOfRelevantAccountTypes = null;
466+
final String[] allowedAccountTypes =
467+
intent.getStringArrayExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
468+
if (allowedAccountTypes != null) {
469+
setOfRelevantAccountTypes = Sets.newHashSet(allowedAccountTypes);
470+
AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
471+
Set<String> supportedAccountTypes = new HashSet<String>(descs.length);
472+
for (AuthenticatorDescription desc : descs) {
473+
supportedAccountTypes.add(desc.type);
474+
}
475+
setOfRelevantAccountTypes.retainAll(supportedAccountTypes);
476+
}
477+
return setOfRelevantAccountTypes;
478+
}
479+
480+
/**
481+
* Returns a set of whitelisted accounts given by the intent or null if none specified by the
482+
* intent.
483+
*/
484+
private Set<Account> getAllowableAccountSet(final Intent intent) {
485+
Set<Account> setOfAllowableAccounts = null;
486+
final ArrayList<Parcelable> validAccounts =
487+
intent.getParcelableArrayListExtra(EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST);
488+
if (validAccounts != null) {
489+
setOfAllowableAccounts = new HashSet<Account>(validAccounts.size());
490+
for (Parcelable parcelable : validAccounts) {
491+
setOfAllowableAccounts.add((Account)parcelable);
492+
}
493+
}
494+
return setOfAllowableAccounts;
495+
}
496+
497+
/**
498+
* Overrides the description text view for the picker activity if specified by the intent.
499+
* If not specified then makes the description invisible.
500+
*/
501+
private void overrideDescriptionIfSupplied(String descriptionOverride) {
502+
TextView descriptionView = (TextView) findViewById(R.id.description);
503+
if (!TextUtils.isEmpty(descriptionOverride)) {
504+
descriptionView.setText(descriptionOverride);
505+
} else {
506+
descriptionView.setVisibility(View.GONE);
507+
}
508+
}
509+
510+
/**
511+
* Populates the UI ListView with the given list of items and selects an item
512+
* based on {@code mSelectedItemIndex} member variable.
513+
*/
514+
private final void populateUIAccountList(String[] listItems) {
515+
ListView list = (ListView) findViewById(android.R.id.list);
516+
list.setAdapter(new ArrayAdapter<String>(this,
517+
android.R.layout.simple_list_item_single_choice, listItems));
518+
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
519+
list.setItemsCanFocus(false);
520+
list.setOnItemClickListener(
521+
new AdapterView.OnItemClickListener() {
522+
@Override
523+
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
524+
mSelectedItemIndex = position;
525+
mOkButton.setEnabled(true);
526+
}
527+
});
528+
if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
529+
list.setItemChecked(mSelectedItemIndex, true);
530+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
531+
Log.v(TAG, "List item " + mSelectedItemIndex + " should be selected");
532+
}
533+
}
534+
}
483535
}

0 commit comments

Comments
 (0)