1616package android .accounts ;
1717
1818import android .app .Activity ;
19- import android .content .Context ;
2019import android .content .Intent ;
21- import android .content .pm .PackageManager ;
22- import android .content .res .Resources ;
23- import android .graphics .drawable .Drawable ;
2420import android .os .Bundle ;
2521import android .os .Parcelable ;
2622import android .text .TextUtils ;
2723import android .util .Log ;
28- import android .view .LayoutInflater ;
2924import android .view .View ;
3025import android .view .ViewGroup ;
3126import android .widget .AdapterView ;
3227import android .widget .ArrayAdapter ;
3328import android .widget .Button ;
34- import android .widget .ImageView ;
3529import android .widget .ListView ;
3630import android .widget .TextView ;
31+
3732import com .android .internal .R ;
3833
3934import java .io .IOException ;
@@ -106,10 +101,16 @@ public class ChooseTypeAndAccountActivity extends Activity
106101
107102 private static final String KEY_INSTANCE_STATE_PENDING_REQUEST = "pendingRequest" ;
108103 private static final String KEY_INSTANCE_STATE_EXISTING_ACCOUNTS = "existingAccounts" ;
104+ private static final String KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME = "selectedAccountName" ;
105+ private static final String KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT = "selectedAddAccount" ;
106+
107+ private static final int SELECTED_ITEM_NONE = -1 ;
109108
110- private ArrayList <AccountInfo > mAccountInfos ;
109+ private ArrayList <Account > mAccounts ;
111110 private int mPendingRequest = REQUEST_NULL ;
112111 private Parcelable [] mExistingAccounts = null ;
112+ private int mSelectedItemIndex ;
113+ private Button mOkButton ;
113114
114115 @ Override
115116 public void onCreate (Bundle savedInstanceState ) {
@@ -119,31 +120,39 @@ public void onCreate(Bundle savedInstanceState) {
119120 + savedInstanceState + ")" );
120121 }
121122
123+ // save some items we use frequently
124+ final AccountManager accountManager = AccountManager .get (this );
125+ final Intent intent = getIntent ();
126+
127+ String selectedAccountName = null ;
128+ boolean selectedAddNewAccount = false ;
129+
122130 if (savedInstanceState != null ) {
123131 mPendingRequest = savedInstanceState .getInt (KEY_INSTANCE_STATE_PENDING_REQUEST );
124132 mExistingAccounts =
125133 savedInstanceState .getParcelableArray (KEY_INSTANCE_STATE_EXISTING_ACCOUNTS );
134+
135+ // Makes sure that any user selection is preserved across orientation changes.
136+ selectedAccountName = savedInstanceState .getString (
137+ KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME );
138+
139+ selectedAddNewAccount = savedInstanceState .getBoolean (
140+ KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT , false );
126141 } else {
127142 mPendingRequest = REQUEST_NULL ;
128143 mExistingAccounts = null ;
144+ // If the selected account as specified in the intent matches one in the list we will
145+ // show is as pre-selected.
146+ Account selectedAccount = (Account ) intent .getParcelableExtra (EXTRA_SELECTED_ACCOUNT );
147+ if (selectedAccount != null ) {
148+ selectedAccountName = selectedAccount .name ;
149+ }
129150 }
130151
131- // save some items we use frequently
132- final AccountManager accountManager = AccountManager .get (this );
133- final Intent intent = getIntent ();
134-
135- // override the description text if supplied
136- final String descriptionOverride =
137- intent .getStringExtra (EXTRA_DESCRIPTION_TEXT_OVERRIDE );
138- if (!TextUtils .isEmpty (descriptionOverride )) {
139- ((TextView )findViewById (R .id .description )).setText (descriptionOverride );
152+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
153+ Log .v (TAG , "selected account name is " + selectedAccountName );
140154 }
141155
142- // If the selected account matches one in the list we will place a
143- // checkmark next to it.
144- final Account selectedAccount =
145- (Account )intent .getParcelableExtra (EXTRA_SELECTED_ACCOUNT );
146-
147156 // build an efficiently queryable map of account types to authenticator descriptions
148157 final HashMap <String , AuthenticatorDescription > typeToAuthDescription =
149158 new HashMap <String , AuthenticatorDescription >();
@@ -192,7 +201,8 @@ public void onCreate(Bundle savedInstanceState) {
192201 // accounts that don't match the allowable types, if provided, or that don't match the
193202 // allowable accounts, if provided.
194203 final Account [] accounts = accountManager .getAccounts ();
195- mAccountInfos = new ArrayList <AccountInfo >(accounts .length );
204+ mAccounts = new ArrayList <Account >(accounts .length );
205+ mSelectedItemIndex = SELECTED_ITEM_NONE ;
196206 for (Account account : accounts ) {
197207 if (setOfAllowableAccounts != null
198208 && !setOfAllowableAccounts .contains (account )) {
@@ -202,15 +212,16 @@ public void onCreate(Bundle savedInstanceState) {
202212 && !setOfRelevantAccountTypes .contains (account .type )) {
203213 continue ;
204214 }
205- mAccountInfos .add (new AccountInfo (account ,
206- getDrawableForType (typeToAuthDescription , account .type ),
207- account .equals (selectedAccount )));
215+ if (account .name .equals (selectedAccountName )) {
216+ mSelectedItemIndex = mAccounts .size ();
217+ }
218+ mAccounts .add (account );
208219 }
209220
210221 if (mPendingRequest == REQUEST_NULL ) {
211- // If there are no relevant accounts and only one relevant account typoe go directly to
222+ // If there are no relevant accounts and only one relevant account type go directly to
212223 // add account. Otherwise let the user choose.
213- if (mAccountInfos .isEmpty ()) {
224+ if (mAccounts .isEmpty ()) {
214225 if (setOfRelevantAccountTypes .size () == 1 ) {
215226 runAddAccountForAuthenticator (setOfRelevantAccountTypes .iterator ().next ());
216227 } else {
@@ -221,36 +232,71 @@ public void onCreate(Bundle savedInstanceState) {
221232
222233 // if there is only one allowable account return it
223234 if (!intent .getBooleanExtra (EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT , false )
224- && mAccountInfos .size () == 1 ) {
225- Account account = mAccountInfos .get (0 ). account ;
235+ && mAccounts .size () == 1 ) {
236+ Account account = mAccounts .get (0 );
226237 setResultAndFinish (account .name , account .type );
227238 return ;
228239 }
229240 }
230241
242+ // Cannot set content view until we know that mPendingRequest is not null, otherwise
243+ // would cause screen flicker.
231244 setContentView (R .layout .choose_type_and_account );
232245
233- // there is more than one allowable account. initialize the list adapter to allow
234- // the user to select an account.
246+ // Override the description text if supplied
247+ final String descriptionOverride =
248+ intent .getStringExtra (EXTRA_DESCRIPTION_TEXT_OVERRIDE );
249+ TextView descriptionView = (TextView ) findViewById (R .id .description );
250+ if (!TextUtils .isEmpty (descriptionOverride )) {
251+ descriptionView .setText (descriptionOverride );
252+ } else {
253+ descriptionView .setVisibility (View .GONE );
254+ }
255+
256+ // List of options includes all accounts found together with "Add new account" as the
257+ // last item in the list.
258+ String [] listItems = new String [mAccounts .size () + 1 ];
259+ for (int i = 0 ; i < mAccounts .size (); i ++) {
260+ listItems [i ] = mAccounts .get (i ).name ;
261+ }
262+ listItems [mAccounts .size ()] = getResources ().getString (
263+ R .string .add_account_button_label );
264+
235265 ListView list = (ListView ) findViewById (android .R .id .list );
236- list .setAdapter (new AccountArrayAdapter (this ,
237- android .R .layout .simple_list_item_1 , mAccountInfos ));
266+ list .setAdapter (new ArrayAdapter < String > (this ,
267+ android .R .layout .simple_list_item_single_choice , listItems ));
238268 list .setChoiceMode (ListView .CHOICE_MODE_SINGLE );
269+ list .setItemsCanFocus (false );
239270 list .setOnItemClickListener (new AdapterView .OnItemClickListener () {
240271 @ Override
241272 public void onItemClick (AdapterView <?> parent , View v , int position , long id ) {
242- onListItemClick ((ListView )parent , v , position , id );
273+ mSelectedItemIndex = position ;
274+ mOkButton .setEnabled (true );
243275 }
244276 });
245277
246- // set the listener for the addAccount button
247- Button addAccountButton = (Button ) findViewById (R .id .addAccount );
248- addAccountButton .setOnClickListener (new View .OnClickListener () {
249- @ Override
250- public void onClick (final View v ) {
251- startChooseAccountTypeActivity ();
278+ // If "Add account" option was previously selected by user, preserve it across
279+ // orientation changes.
280+ if (selectedAddNewAccount ) {
281+ mSelectedItemIndex = mAccounts .size ();
282+ }
283+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
284+ Log .v (TAG , "mSelectedItemIndex is " + mSelectedItemIndex );
285+ }
286+
287+ ViewGroup buttonBar = (ViewGroup ) findViewById (R .id .button_bar );
288+ if (buttonBar != null ) {
289+ mOkButton = (Button ) buttonBar .findViewById (android .R .id .button2 );
290+ if (mSelectedItemIndex != SELECTED_ITEM_NONE ) {
291+ // If caller specified a selectedAccount, then display that as selected and enable
292+ // the "OK" button by default.
293+ list .setSelection (mSelectedItemIndex );
294+ mOkButton .setEnabled (true );
295+ } else {
296+ // Otherwise "OK" button is disabled since nothing is pre-selected.
297+ mOkButton .setEnabled (false );
252298 }
253- });
299+ }
254300 }
255301
256302 @ Override
@@ -268,6 +314,28 @@ protected void onSaveInstanceState(final Bundle outState) {
268314 if (mPendingRequest == REQUEST_ADD_ACCOUNT ) {
269315 outState .putParcelableArray (KEY_INSTANCE_STATE_EXISTING_ACCOUNTS , mExistingAccounts );
270316 }
317+ if (mSelectedItemIndex != SELECTED_ITEM_NONE ) {
318+ if (mSelectedItemIndex == mAccounts .size ()) {
319+ outState .putBoolean (KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT , true );
320+ } else {
321+ outState .putBoolean (KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT , false );
322+ outState .putString (KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME ,
323+ mAccounts .get (mSelectedItemIndex ).name );
324+ }
325+ }
326+ }
327+
328+ public void onCancelButtonClicked (View view ) {
329+ onBackPressed ();
330+ }
331+
332+ public void onOkButtonClicked (View view ) {
333+ if (mSelectedItemIndex == mAccounts .size ()) {
334+ // Selected "Add New Account" option
335+ startChooseAccountTypeActivity ();
336+ } else if (mSelectedItemIndex != SELECTED_ITEM_NONE ) {
337+ onAccountSelected (mAccounts .get (mSelectedItemIndex ));
338+ }
271339 }
272340
273341 // Called when the choose account type activity (for adding an account) returns.
@@ -287,9 +355,9 @@ protected void onActivityResult(final int requestCode, final int resultCode,
287355 mPendingRequest = REQUEST_NULL ;
288356
289357 if (resultCode == RESULT_CANCELED ) {
290- // if cancelling out of addAccount and the original state caused us to skip this,
358+ // if canceling out of addAccount and the original state caused us to skip this,
291359 // finish this activity
292- if (mAccountInfos .isEmpty ()) {
360+ if (mAccounts .isEmpty ()) {
293361 setResult (Activity .RESULT_CANCELED );
294362 finish ();
295363 }
@@ -360,6 +428,7 @@ protected void runAddAccountForAuthenticator(String type) {
360428 options , null /* activity */ , this /* callback */ , null /* Handler */ );
361429 }
362430
431+ @ Override
363432 public void run (final AccountManagerFuture <Bundle > accountManagerFuture ) {
364433 try {
365434 final Bundle accountManagerResult = accountManagerFuture .getResult ();
@@ -385,34 +454,9 @@ public void run(final AccountManagerFuture<Bundle> accountManagerFuture) {
385454 finish ();
386455 }
387456
388- private Drawable getDrawableForType (
389- final HashMap <String , AuthenticatorDescription > typeToAuthDescription ,
390- String accountType ) {
391- Drawable icon = null ;
392- if (typeToAuthDescription .containsKey (accountType )) {
393- try {
394- AuthenticatorDescription desc = typeToAuthDescription .get (accountType );
395- Context authContext = createPackageContext (desc .packageName , 0 );
396- icon = authContext .getResources ().getDrawable (desc .iconId );
397- } catch (PackageManager .NameNotFoundException e ) {
398- // Nothing we can do much here, just log
399- if (Log .isLoggable (TAG , Log .WARN )) {
400- Log .w (TAG , "No icon name for account type " + accountType );
401- }
402- } catch (Resources .NotFoundException e ) {
403- // Nothing we can do much here, just log
404- if (Log .isLoggable (TAG , Log .WARN )) {
405- Log .w (TAG , "No icon resource for account type " + accountType );
406- }
407- }
408- }
409- return icon ;
410- }
411-
412- protected void onListItemClick (ListView l , View v , int position , long id ) {
413- AccountInfo accountInfo = mAccountInfos .get (position );
414- Log .d (TAG , "selected account " + accountInfo .account );
415- setResultAndFinish (accountInfo .account .name , accountInfo .account .type );
457+ private void onAccountSelected (Account account ) {
458+ Log .d (TAG , "selected account " + account );
459+ setResultAndFinish (account .name , account .type );
416460 }
417461
418462 private void setResultAndFinish (final String accountName , final String accountType ) {
@@ -444,58 +488,4 @@ private void startChooseAccountTypeActivity() {
444488 startActivityForResult (intent , REQUEST_CHOOSE_TYPE );
445489 mPendingRequest = REQUEST_CHOOSE_TYPE ;
446490 }
447-
448- private static class AccountInfo {
449- final Account account ;
450- final Drawable drawable ;
451- private final boolean checked ;
452-
453- AccountInfo (Account account , Drawable drawable , boolean checked ) {
454- this .account = account ;
455- this .drawable = drawable ;
456- this .checked = checked ;
457- }
458- }
459-
460- private static class ViewHolder {
461- ImageView icon ;
462- TextView text ;
463- ImageView checkmark ;
464- }
465-
466- private static class AccountArrayAdapter extends ArrayAdapter <AccountInfo > {
467- private LayoutInflater mLayoutInflater ;
468- private ArrayList <AccountInfo > mInfos ;
469-
470- public AccountArrayAdapter (Context context , int textViewResourceId ,
471- ArrayList <AccountInfo > infos ) {
472- super (context , textViewResourceId , infos );
473- mInfos = infos ;
474- mLayoutInflater = (LayoutInflater ) context .getSystemService (
475- Context .LAYOUT_INFLATER_SERVICE );
476- }
477-
478- @ Override
479- public View getView (int position , View convertView , ViewGroup parent ) {
480- ViewHolder holder ;
481-
482- if (convertView == null ) {
483- convertView = mLayoutInflater .inflate (R .layout .choose_selected_account_row , null );
484- holder = new ViewHolder ();
485- holder .text = (TextView ) convertView .findViewById (R .id .account_row_text );
486- holder .icon = (ImageView ) convertView .findViewById (R .id .account_row_icon );
487- holder .checkmark = (ImageView ) convertView .findViewById (R .id .account_row_checkmark );
488- convertView .setTag (holder );
489- } else {
490- holder = (ViewHolder ) convertView .getTag ();
491- }
492-
493- holder .text .setText (mInfos .get (position ).account .name );
494- holder .icon .setImageDrawable (mInfos .get (position ).drawable );
495- final int displayCheckmark =
496- mInfos .get (position ).checked ? View .VISIBLE : View .INVISIBLE ;
497- holder .checkmark .setVisibility (displayCheckmark );
498- return convertView ;
499- }
500- }
501491}
0 commit comments