MessageList.java revision 2127964d0f73df889460b23c81d463bbc871efed
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.activity; 18 19import com.android.email.Controller; 20import com.android.email.ControllerResultUiThreadWrapper; 21import com.android.email.Email; 22import com.android.email.R; 23import com.android.email.Utility; 24import com.android.email.activity.setup.AccountSecurity; 25import com.android.email.activity.setup.AccountSettings; 26import com.android.email.mail.AuthenticationFailedException; 27import com.android.email.mail.CertificateValidationException; 28import com.android.email.mail.MessagingException; 29import com.android.email.provider.EmailContent; 30import com.android.email.provider.EmailContent.Account; 31import com.android.email.provider.EmailContent.AccountColumns; 32import com.android.email.provider.EmailContent.Mailbox; 33import com.android.email.provider.EmailContent.MailboxColumns; 34import com.android.email.service.MailService; 35 36import android.app.Activity; 37import android.app.NotificationManager; 38import android.content.ContentResolver; 39import android.content.Context; 40import android.content.Intent; 41import android.database.Cursor; 42import android.net.Uri; 43import android.os.AsyncTask; 44import android.os.Bundle; 45import android.os.Handler; 46import android.view.Menu; 47import android.view.MenuItem; 48import android.view.View; 49import android.view.View.OnClickListener; 50import android.view.animation.Animation; 51import android.view.animation.Animation.AnimationListener; 52import android.view.animation.AnimationUtils; 53import android.widget.Button; 54import android.widget.ProgressBar; 55import android.widget.TextView; 56 57public class MessageList extends Activity implements OnClickListener, 58 AnimationListener, MessageListFragment.Callback { 59 // Intent extras (internal to this activity) 60 private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity._ACCOUNT_ID"; 61 private static final String EXTRA_MAILBOX_TYPE = "com.android.email.activity.MAILBOX_TYPE"; 62 private static final String EXTRA_MAILBOX_ID = "com.android.email.activity.MAILBOX_ID"; 63 64 private static final int REQUEST_SECURITY = 0; 65 66 // UI support 67 private MessageListFragment mListFragment; 68 private View mMultiSelectPanel; 69 private Button mReadUnreadButton; 70 private Button mFavoriteButton; 71 private Button mDeleteButton; 72 private TextView mErrorBanner; 73 74 private final Controller mController = Controller.getInstance(getApplication()); 75 private ControllerResultUiThreadWrapper<ControllerResults> mControllerCallback; 76 77 private TextView mLeftTitle; 78 private ProgressBar mProgressIcon; 79 80 // DB access 81 private ContentResolver mResolver; 82 private SetTitleTask mSetTitleTask; 83 84 private MailboxFinder mMailboxFinder; 85 private MailboxFinderCallback mMailboxFinderCallback = new MailboxFinderCallback(); 86 87 private static final int MAILBOX_NAME_COLUMN_ID = 0; 88 private static final int MAILBOX_NAME_COLUMN_ACCOUNT_KEY = 1; 89 private static final int MAILBOX_NAME_COLUMN_TYPE = 2; 90 private static final String[] MAILBOX_NAME_PROJECTION = new String[] { 91 MailboxColumns.DISPLAY_NAME, MailboxColumns.ACCOUNT_KEY, 92 MailboxColumns.TYPE}; 93 94 private static final int ACCOUNT_DISPLAY_NAME_COLUMN_ID = 0; 95 private static final String[] ACCOUNT_NAME_PROJECTION = new String[] { 96 AccountColumns.DISPLAY_NAME }; 97 98 private static final String ID_SELECTION = EmailContent.RECORD_ID + "=?"; 99 100 /* package */ MessageListFragment getListFragmentForTest() { 101 return mListFragment; 102 } 103 104 /** 105 * Open a specific mailbox. 106 * 107 * TODO This should just shortcut to a more generic version that can accept a list of 108 * accounts/mailboxes (e.g. merged inboxes). 109 * 110 * @param context 111 * @param id mailbox key 112 */ 113 public static void actionHandleMailbox(Context context, long id) { 114 context.startActivity(createIntent(context, -1, id, -1)); 115 } 116 117 /** 118 * Open a specific mailbox by account & type 119 * 120 * @param context The caller's context (for generating an intent) 121 * @param accountId The account to open 122 * @param mailboxType the type of mailbox to open (e.g. @see EmailContent.Mailbox.TYPE_INBOX) 123 */ 124 public static void actionHandleAccount(Context context, long accountId, int mailboxType) { 125 context.startActivity(createIntent(context, accountId, -1, mailboxType)); 126 } 127 128 /** 129 * Open the inbox of the account with a UUID. It's used to handle old style 130 * (Android <= 1.6) desktop shortcut intents. 131 */ 132 public static void actionOpenAccountInboxUuid(Context context, String accountUuid) { 133 Intent i = createIntent(context, -1, -1, Mailbox.TYPE_INBOX); 134 i.setData(Account.getShortcutSafeUriFromUuid(accountUuid)); 135 context.startActivity(i); 136 } 137 138 /** 139 * Return an intent to open a specific mailbox by account & type. 140 * 141 * @param context The caller's context (for generating an intent) 142 * @param accountId The account to open, or -1 143 * @param mailboxId the ID of the mailbox to open, or -1 144 * @param mailboxType the type of mailbox to open (e.g. @see Mailbox.TYPE_INBOX) or -1 145 */ 146 public static Intent createIntent(Context context, long accountId, long mailboxId, 147 int mailboxType) { 148 Intent intent = new Intent(context, MessageList.class); 149 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 150 if (accountId != -1) intent.putExtra(EXTRA_ACCOUNT_ID, accountId); 151 if (mailboxId != -1) intent.putExtra(EXTRA_MAILBOX_ID, mailboxId); 152 if (mailboxType != -1) intent.putExtra(EXTRA_MAILBOX_TYPE, mailboxType); 153 return intent; 154 } 155 156 /** 157 * Create and return an intent for a desktop shortcut for an account. 158 * 159 * @param context Calling context for building the intent 160 * @param account The account of interest 161 * @param mailboxType The folder name to open (typically Mailbox.TYPE_INBOX) 162 * @return an Intent which can be used to view that account 163 */ 164 public static Intent createAccountIntentForShortcut(Context context, Account account, 165 int mailboxType) { 166 Intent i = createIntent(context, -1, -1, mailboxType); 167 i.setData(account.getShortcutSafeUri()); 168 return i; 169 } 170 171 @Override 172 public void onCreate(Bundle icicle) { 173 super.onCreate(icicle); 174 setContentView(R.layout.message_list); 175 176 mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>( 177 new Handler(), new ControllerResults()); 178 mListFragment = (MessageListFragment) findFragmentById(R.id.message_list_fragment); 179 mMultiSelectPanel = findViewById(R.id.footer_organize); 180 mReadUnreadButton = (Button) findViewById(R.id.btn_read_unread); 181 mFavoriteButton = (Button) findViewById(R.id.btn_multi_favorite); 182 mDeleteButton = (Button) findViewById(R.id.btn_multi_delete); 183 mLeftTitle = (TextView) findViewById(R.id.title_left_text); 184 mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon); 185 mErrorBanner = (TextView) findViewById(R.id.connection_error_text); 186 187 mReadUnreadButton.setOnClickListener(this); 188 mFavoriteButton.setOnClickListener(this); 189 mDeleteButton.setOnClickListener(this); 190 ((Button) findViewById(R.id.account_title_button)).setOnClickListener(this); 191 192 mListFragment.setCallback(this); 193 194 mResolver = getContentResolver(); 195 196 // Show the appropriate account/mailbox specified by an {@link Intent}. 197 selectAccountAndMailbox(getIntent()); 198 } 199 200 /** 201 * Show the appropriate account/mailbox specified by an {@link Intent}. 202 */ 203 private void selectAccountAndMailbox(Intent intent) { 204 long mailboxId = intent.getLongExtra(EXTRA_MAILBOX_ID, -1); 205 if (mailboxId != -1) { 206 // Specific mailbox ID was provided - go directly to it 207 mSetTitleTask = new SetTitleTask(mailboxId); 208 mSetTitleTask.execute(); 209 mListFragment.openMailbox(mailboxId); 210 } else { 211 int mailboxType = intent.getIntExtra(EXTRA_MAILBOX_TYPE, Mailbox.TYPE_INBOX); 212 Uri uri = intent.getData(); 213 // TODO Possible ANR. getAccountIdFromShortcutSafeUri accesses DB. 214 long accountId = (uri == null) ? -1 215 : Account.getAccountIdFromShortcutSafeUri(this, uri); 216 if (accountId == -1) { 217 accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1); 218 } 219 if (accountId == -1) { 220 launchWelcomeAndFinish(); 221 return; 222 } 223 mMailboxFinder = new MailboxFinder(this, accountId, mailboxType, 224 mMailboxFinderCallback); 225 mMailboxFinder.startLookup(); 226 } 227 // TODO set title to "account > mailbox (#unread)" 228 } 229 230 @Override 231 public void onPause() { 232 super.onPause(); 233 mController.removeResultCallback(mControllerCallback); 234 } 235 236 @Override 237 public void onResume() { 238 super.onResume(); 239 mController.addResultCallback(mControllerCallback); 240 241 // clear notifications here 242 NotificationManager notificationManager = (NotificationManager) 243 getSystemService(Context.NOTIFICATION_SERVICE); 244 notificationManager.cancel(MailService.NOTIFICATION_ID_NEW_MESSAGES); 245 246 // Exit immediately if the accounts list has changed (e.g. externally deleted) 247 if (Email.getNotifyUiAccountsChanged()) { 248 Welcome.actionStart(this); 249 finish(); 250 return; 251 } 252 } 253 254 @Override 255 protected void onDestroy() { 256 super.onDestroy(); 257 258 if (mMailboxFinder != null) { 259 mMailboxFinder.close(); 260 mMailboxFinder = null; 261 } 262 Utility.cancelTaskInterrupt(mSetTitleTask); 263 mSetTitleTask = null; 264 } 265 266 267 private void launchWelcomeAndFinish() { 268 Welcome.actionStart(this); 269 finish(); 270 } 271 272 /** 273 * Called when the list fragment can't find mailbox/account. 274 */ 275 public void onMailboxNotFound() { 276 finish(); 277 } 278 279 @Override 280 public void onMessageOpen(long messageId, long messageMailboxId, long listMailboxId, int type) { 281 if (type == MessageListFragment.Callback.TYPE_DRAFT) { 282 MessageCompose.actionEditDraft(this, messageId); 283 } else { 284 final boolean disableReply = (type == MessageListFragment.Callback.TYPE_TRASH); 285 // WARNING: here we pass "listMailboxId", which can be the negative id of 286 // a compound mailbox, instead of the mailboxId of the particular message that 287 // is opened. This is to support the next/prev buttons on the message view 288 // properly even for combined mailboxes. 289 MessageView.actionView(this, messageId, listMailboxId, disableReply); 290 } 291 } 292 293 public void onClick(View v) { 294 switch (v.getId()) { 295 case R.id.btn_read_unread: 296 mListFragment.onMultiToggleRead(); 297 break; 298 case R.id.btn_multi_favorite: 299 mListFragment.onMultiToggleFavorite(); 300 break; 301 case R.id.btn_multi_delete: 302 mListFragment.onMultiDelete(); 303 break; 304 case R.id.account_title_button: 305 onAccounts(); 306 break; 307 } 308 } 309 310 public void onAnimationEnd(Animation animation) { 311 // TODO: If the button panel hides the only selected item, scroll the list to make it 312 // visible again. 313 } 314 315 public void onAnimationRepeat(Animation animation) { 316 } 317 318 public void onAnimationStart(Animation animation) { 319 } 320 321 @Override 322 public boolean onPrepareOptionsMenu(Menu menu) { 323 // Re-create menu every time. (We may not know the mailbox id yet) 324 menu.clear(); 325 if (mListFragment.isMagicMailbox()) { 326 getMenuInflater().inflate(R.menu.message_list_option_smart_folder, menu); 327 } else { 328 getMenuInflater().inflate(R.menu.message_list_option, menu); 329 } 330 boolean showDeselect = mListFragment.getSelectedCount() > 0; 331 menu.setGroupVisible(R.id.deselect_all_group, showDeselect); 332 return true; 333 } 334 335 @Override 336 public boolean onOptionsItemSelected(MenuItem item) { 337 switch (item.getItemId()) { 338 case R.id.refresh: 339 mListFragment.onRefresh(); 340 return true; 341 case R.id.folders: 342 onFolders(); 343 return true; 344 case R.id.accounts: 345 onAccounts(); 346 return true; 347 case R.id.compose: 348 onCompose(); 349 return true; 350 case R.id.account_settings: 351 onEditAccount(); 352 return true; 353 case R.id.deselect_all: 354 mListFragment.onDeselectAll(); 355 return true; 356 default: 357 return super.onOptionsItemSelected(item); 358 } 359 } 360 361 private void onFolders() { 362 if (!mListFragment.isMagicMailbox()) { // Magic boxes don't have "folders" option. 363 // TODO smaller projection 364 Mailbox mailbox = Mailbox.restoreMailboxWithId(this, mListFragment.getMailboxId()); 365 if (mailbox != null) { 366 MailboxList.actionHandleAccount(this, mailbox.mAccountKey); 367 finish(); 368 } 369 } 370 } 371 372 private void onAccounts() { 373 AccountFolderList.actionShowAccounts(this); 374 finish(); 375 } 376 377 private void onCompose() { 378 MessageCompose.actionCompose(this, mListFragment.getAccountId()); 379 } 380 381 private void onEditAccount() { 382 if (!mListFragment.isMagicMailbox()) { // Magic boxes don't have "accout settings" option. 383 AccountSettings.actionSettings(this, mListFragment.getAccountId()); 384 } 385 } 386 387 /** 388 * Show multi-selection panel, if one or more messages are selected. Button labels will be 389 * updated too. 390 * 391 * @deprecated not used any longer. remove them. 392 */ 393 public void onSelectionChanged() { 394 showMultiPanel(mListFragment.getSelectedCount() > 0); 395 } 396 397 /** 398 * @deprecated not used any longer. remove them. (with associated resources, strings, 399 * members, etc) 400 */ 401 private void updateFooterButtonNames () { 402 // Show "unread_action" when one or more read messages are selected. 403 if (mListFragment.doesSelectionContainReadMessage()) { 404 mReadUnreadButton.setText(R.string.unread_action); 405 } else { 406 mReadUnreadButton.setText(R.string.read_action); 407 } 408 // Show "set_star_action" when one or more un-starred messages are selected. 409 if (mListFragment.doesSelectionContainNonStarredMessage()) { 410 mFavoriteButton.setText(R.string.set_star_action); 411 } else { 412 mFavoriteButton.setText(R.string.remove_star_action); 413 } 414 } 415 416 /** 417 * Show or hide the panel of multi-select options 418 * 419 * @deprecated not used any longer. remove them. 420 */ 421 private void showMultiPanel(boolean show) { 422 if (show && mMultiSelectPanel.getVisibility() != View.VISIBLE) { 423 mMultiSelectPanel.setVisibility(View.VISIBLE); 424 Animation animation = AnimationUtils.loadAnimation(this, R.anim.footer_appear); 425 animation.setAnimationListener(this); 426 mMultiSelectPanel.startAnimation(animation); 427 } else if (!show && mMultiSelectPanel.getVisibility() != View.GONE) { 428 mMultiSelectPanel.setVisibility(View.GONE); 429 mMultiSelectPanel.startAnimation( 430 AnimationUtils.loadAnimation(this, R.anim.footer_disappear)); 431 } 432 if (show) { 433 updateFooterButtonNames(); 434 } 435 } 436 437 /** 438 * Handle the eventual result from the security update activity 439 * 440 * Note, this is extremely coarse, and it simply returns the user to the Accounts list. 441 * Anything more requires refactoring of this Activity. 442 */ 443 @Override 444 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 445 switch (requestCode) { 446 case REQUEST_SECURITY: 447 onAccounts(); 448 } 449 super.onActivityResult(requestCode, resultCode, data); 450 } 451 452 private class SetTitleTask extends AsyncTask<Void, Void, Object[]> { 453 454 private long mMailboxKey; 455 456 public SetTitleTask(long mailboxKey) { 457 mMailboxKey = mailboxKey; 458 } 459 460 @Override 461 protected Object[] doInBackground(Void... params) { 462 // Check special Mailboxes 463 int resIdSpecialMailbox = 0; 464 if (mMailboxKey == Mailbox.QUERY_ALL_INBOXES) { 465 resIdSpecialMailbox = R.string.account_folder_list_summary_inbox; 466 } else if (mMailboxKey == Mailbox.QUERY_ALL_FAVORITES) { 467 resIdSpecialMailbox = R.string.account_folder_list_summary_starred; 468 } else if (mMailboxKey == Mailbox.QUERY_ALL_DRAFTS) { 469 resIdSpecialMailbox = R.string.account_folder_list_summary_drafts; 470 } else if (mMailboxKey == Mailbox.QUERY_ALL_OUTBOX) { 471 resIdSpecialMailbox = R.string.account_folder_list_summary_outbox; 472 } 473 if (resIdSpecialMailbox != 0) { 474 return new Object[] {null, getString(resIdSpecialMailbox), 0}; 475 } 476 477 String accountName = null; 478 String mailboxName = null; 479 String accountKey = null; 480 Cursor c = MessageList.this.mResolver.query(Mailbox.CONTENT_URI, 481 MAILBOX_NAME_PROJECTION, ID_SELECTION, 482 new String[] { Long.toString(mMailboxKey) }, null); 483 try { 484 if (c.moveToFirst()) { 485 mailboxName = Utility.FolderProperties.getInstance(MessageList.this) 486 .getDisplayName(c.getInt(MAILBOX_NAME_COLUMN_TYPE)); 487 if (mailboxName == null) { 488 mailboxName = c.getString(MAILBOX_NAME_COLUMN_ID); 489 } 490 accountKey = c.getString(MAILBOX_NAME_COLUMN_ACCOUNT_KEY); 491 } 492 } finally { 493 c.close(); 494 } 495 if (accountKey != null) { 496 c = MessageList.this.mResolver.query(Account.CONTENT_URI, 497 ACCOUNT_NAME_PROJECTION, ID_SELECTION, new String[] { accountKey }, 498 null); 499 try { 500 if (c.moveToFirst()) { 501 accountName = c.getString(ACCOUNT_DISPLAY_NAME_COLUMN_ID); 502 } 503 } finally { 504 c.close(); 505 } 506 } 507 int nAccounts = EmailContent.count(MessageList.this, Account.CONTENT_URI, null, null); 508 return new Object[] {accountName, mailboxName, nAccounts}; 509 } 510 511 @Override 512 protected void onPostExecute(Object[] result) { 513 if (result == null) { 514 return; 515 } 516 517 final int nAccounts = (Integer) result[2]; 518 if (result[0] != null) { 519 setTitleAccountName((String) result[0], nAccounts > 1); 520 } 521 522 if (result[1] != null) { 523 mLeftTitle.setText((String) result[1]); 524 } 525 } 526 } 527 528 private void setTitleAccountName(String accountName, boolean showAccountsButton) { 529 TextView accountsButton = (TextView) findViewById(R.id.account_title_button); 530 TextView textPlain = (TextView) findViewById(R.id.title_right_text); 531 if (showAccountsButton) { 532 accountsButton.setVisibility(View.VISIBLE); 533 textPlain.setVisibility(View.GONE); 534 accountsButton.setText(accountName); 535 } else { 536 accountsButton.setVisibility(View.GONE); 537 textPlain.setVisibility(View.VISIBLE); 538 textPlain.setText(accountName); 539 } 540 } 541 542 private void showProgressIcon(boolean show) { 543 int visibility = show ? View.VISIBLE : View.GONE; 544 mProgressIcon.setVisibility(visibility); 545 mListFragment.showProgressIcon(show); 546 } 547 548 private void showErrorBanner(String message) { 549 boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE; 550 if (message != null) { 551 mErrorBanner.setText(message); 552 if (!isVisible) { 553 mErrorBanner.setVisibility(View.VISIBLE); 554 mErrorBanner.startAnimation( 555 AnimationUtils.loadAnimation( 556 MessageList.this, R.anim.header_appear)); 557 } 558 } else { 559 if (isVisible) { 560 mErrorBanner.setVisibility(View.GONE); 561 mErrorBanner.startAnimation( 562 AnimationUtils.loadAnimation( 563 MessageList.this, R.anim.header_disappear)); 564 } 565 } 566 } 567 568 /** 569 * Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper}, 570 * so all methods are called on the UI thread. 571 */ 572 private class ControllerResults extends Controller.Result { 573 574 // This is used to alter the connection banner operation for sending messages 575 private MessagingException mSendMessageException; 576 577 // TODO check accountKey and only react to relevant notifications 578 @Override 579 public void updateMailboxCallback(MessagingException result, long accountKey, 580 long mailboxKey, int progress, int numNewMessages) { 581 updateBanner(result, progress, mailboxKey); 582 if (result != null || progress == 100) { 583 Email.updateMailboxRefreshTime(mailboxKey); 584 } 585 updateProgress(result, progress); 586 } 587 588 /** 589 * We alter the updateBanner hysteresis here to capture any failures and handle 590 * them just once at the end. This callback is overly overloaded: 591 * result == null, messageId == -1, progress == 0: start batch send 592 * result == null, messageId == xx, progress == 0: start sending one message 593 * result == xxxx, messageId == xx, progress == 0; failed sending one message 594 * result == null, messageId == -1, progres == 100; finish sending batch 595 */ 596 @Override 597 public void sendMailCallback(MessagingException result, long accountId, long messageId, 598 int progress) { 599 if (mListFragment.isOutbox()) { 600 // reset captured error when we start sending one or more messages 601 if (messageId == -1 && result == null && progress == 0) { 602 mSendMessageException = null; 603 } 604 // capture first exception that comes along 605 if (result != null && mSendMessageException == null) { 606 mSendMessageException = result; 607 } 608 // if we're completing the sequence, change the banner state 609 if (messageId == -1 && progress == 100) { 610 updateBanner(mSendMessageException, progress, mListFragment.getMailboxId()); 611 } 612 // always update the spinner, which has less state to worry about 613 updateProgress(result, progress); 614 } 615 } 616 617 private void updateProgress(MessagingException result, int progress) { 618 showProgressIcon(result == null && progress < 100); 619 } 620 621 /** 622 * Show or hide the connection error banner, and convert the various MessagingException 623 * variants into localizable text. There is hysteresis in the show/hide logic: Once shown, 624 * the banner will remain visible until some progress is made on the connection. The 625 * goal is to keep it from flickering during retries in a bad connection state. 626 * 627 * @param result 628 * @param progress 629 */ 630 private void updateBanner(MessagingException result, int progress, long mailboxKey) { 631 if (mailboxKey != mListFragment.getMailboxId()) { 632 return; 633 } 634 if (result != null) { 635 int id = R.string.status_network_error; 636 if (result instanceof AuthenticationFailedException) { 637 id = R.string.account_setup_failed_dlg_auth_message; 638 } else if (result instanceof CertificateValidationException) { 639 id = R.string.account_setup_failed_dlg_certificate_message; 640 } else { 641 switch (result.getExceptionType()) { 642 case MessagingException.IOERROR: 643 id = R.string.account_setup_failed_ioerror; 644 break; 645 case MessagingException.TLS_REQUIRED: 646 id = R.string.account_setup_failed_tls_required; 647 break; 648 case MessagingException.AUTH_REQUIRED: 649 id = R.string.account_setup_failed_auth_required; 650 break; 651 case MessagingException.GENERAL_SECURITY: 652 id = R.string.account_setup_failed_security; 653 break; 654 // TODO Generate a unique string for this case, which is the case 655 // where the security policy needs to be updated. 656 case MessagingException.SECURITY_POLICIES_REQUIRED: 657 id = R.string.account_setup_failed_security; 658 break; 659 } 660 } 661 showErrorBanner(getString(id)); 662 } else if (progress > 0) { 663 showErrorBanner(null); 664 } 665 } 666 } 667 668 private class MailboxFinderCallback implements MailboxFinder.Callback { 669 @Override 670 public void onMailboxFound(long accountId, long mailboxId) { 671 mSetTitleTask = new SetTitleTask(mailboxId); 672 mSetTitleTask.execute(); 673 mListFragment.openMailbox(mailboxId); 674 } 675 676 @Override 677 public void onAccountNotFound() { 678 // Let the Welcome activity show the default screen. 679 launchWelcomeAndFinish(); 680 } 681 682 @Override 683 public void onMailboxNotFound(long accountId) { 684 // Let the Welcome activity show the default screen. 685 launchWelcomeAndFinish(); 686 } 687 688 @Override 689 public void onAccountSecurityHold(long accountId) { 690 // launch the security setup activity 691 Intent i = AccountSecurity.actionUpdateSecurityIntent( 692 MessageList.this, accountId); 693 MessageList.this.startActivityForResult(i, REQUEST_SECURITY); 694 } 695 } 696} 697