Welcome.java revision c1ca222b759ab5412ec732f6696f76e929f3cd01
1/* 2 * Copyright (C) 2008 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.Email; 20import com.android.email.ExchangeUtils; 21import com.android.email.R; 22import com.android.email.activity.setup.AccountSetupBasics; 23import com.android.email.provider.AccountBackupRestore; 24import com.android.email.service.MailService; 25import com.android.emailcommon.provider.EmailContent; 26import com.android.emailcommon.provider.EmailContent.Account; 27import com.android.emailcommon.utility.EmailAsyncTask; 28import com.android.emailcommon.utility.Utility; 29import com.google.common.annotations.VisibleForTesting; 30 31import android.app.Activity; 32import android.content.Context; 33import android.content.Intent; 34import android.net.Uri; 35import android.os.Bundle; 36import android.text.TextUtils; 37 38/** 39 * The Welcome activity initializes the application and decides what Activity 40 * the user should start with. 41 * 42 * This class knows which activity should be launched under the current configuration (screen size) 43 * and the number of accounts configured. So if you want to open an account or a mailbox, 44 * you should always do so via its static methods, such as {@link #actionOpenAccountInbox}. 45 */ 46public class Welcome extends Activity { 47 /* 48 * Commands for testing... 49 * Open 1 pane 50 adb shell am start -a android.intent.action.MAIN \ 51 -d '"content://ui.email.android.com/view/mailbox"' \ 52 -e DEBUG_PANE_MODE 1 53 54 * Open 2 pane 55 adb shell am start -a android.intent.action.MAIN \ 56 -d '"content://ui.email.android.com/view/mailbox"' \ 57 -e DEBUG_PANE_MODE 2 58 59 * Open an account (ID=1) in 2 pane 60 adb shell am start -a android.intent.action.MAIN \ 61 -d '"content://ui.email.android.com/view/mailbox?ACCOUNT_ID=1"' \ 62 -e DEBUG_PANE_MODE 2 63 64 * Open a message (account id=1, mailbox id=2, message id=3) 65 adb shell am start -a android.intent.action.MAIN \ 66 -d '"content://ui.email.android.com/view/mailbox?ACCOUNT_ID=1&MAILBOX_ID=2&MESSAGE_ID=3"' \ 67 -e DEBUG_PANE_MODE 2 \ 68 69 */ 70 71 /** 72 * Extra for debugging. Set 1 to force one-pane. Set 2 to force two-pane. 73 */ 74 private static final String EXTRA_DEBUG_PANE_MODE = "DEBUG_PANE_MODE"; 75 76 private static final String VIEW_MAILBOX_INTENT_URL_PATH = "/view/mailbox"; 77 78 private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker(); 79 80 /** 81 * Launch this activity. Note: It's assumed that this activity is only called as a means to 82 * 'reset' the UI state; Because of this, it is always launched with FLAG_ACTIVITY_CLEAR_TOP, 83 * which will drop any other activities on the stack (e.g. AccountFolderList or MessageList). 84 */ 85 public static void actionStart(Activity fromActivity) { 86 Intent i = IntentUtilities.createRestartAppIntent(fromActivity, Welcome.class); 87 fromActivity.startActivity(i); 88 } 89 90 /** 91 * Create an Intent to open email activity. If <code>accountId</code> is not -1, the 92 * specified account will be automatically be opened when the activity starts. 93 */ 94 public static Intent createOpenAccountInboxIntent(Context context, long accountId) { 95 final Uri.Builder b = IntentUtilities.createActivityIntentUrlBuilder( 96 VIEW_MAILBOX_INTENT_URL_PATH); 97 IntentUtilities.setAccountId(b, accountId); 98 return IntentUtilities.createRestartAppIntent(b.build()); 99 } 100 101 /** 102 * Create an Intent to open a message. 103 */ 104 public static Intent createOpenMessageIntent(Context context, long accountId, 105 long mailboxId, long messageId) { 106 final Uri.Builder b = IntentUtilities.createActivityIntentUrlBuilder( 107 VIEW_MAILBOX_INTENT_URL_PATH); 108 IntentUtilities.setAccountId(b, accountId); 109 IntentUtilities.setMailboxId(b, mailboxId); 110 IntentUtilities.setMessageId(b, messageId); 111 return IntentUtilities.createRestartAppIntent(b.build()); 112 } 113 114 /** 115 * Open account's inbox. 116 */ 117 public static void actionOpenAccountInbox(Activity fromActivity, long accountId) { 118 fromActivity.startActivity(createOpenAccountInboxIntent(fromActivity, accountId)); 119 } 120 121 /** 122 * Create an {@link Intent} for account shortcuts. The returned intent stores the account's 123 * UUID rather than the account ID, which will be changed after account restore. 124 */ 125 public static Intent createAccountShortcutIntent(Context context, Account account) { 126 final Uri.Builder b = IntentUtilities.createActivityIntentUrlBuilder( 127 VIEW_MAILBOX_INTENT_URL_PATH); 128 IntentUtilities.setAccountUuid(b, account.mCompatibilityUuid); 129 return IntentUtilities.createRestartAppIntent(b.build()); 130 } 131 132 /** 133 * Parse the {@link #EXTRA_DEBUG_PANE_MODE} extra and return 1 or 2, if it's set to "1" or "2". 134 * Return 0 otherwise. 135 */ 136 private static int getDebugPaneMode(Intent i) { 137 Bundle extras = i.getExtras(); 138 if (extras != null) { 139 String s = extras.getString(EXTRA_DEBUG_PANE_MODE); 140 if ("1".equals(s)) { 141 return 1; 142 } else if ("2".equals(s)) { 143 return 2; 144 } 145 } 146 return 0; 147 } 148 149 @Override 150 public void onCreate(Bundle icicle) { 151 super.onCreate(icicle); 152 ActivityHelper.debugSetWindowFlags(this); 153 154 // Reset the "accounts changed" notification, now that we're here 155 Email.setNotifyUiAccountsChanged(false); 156 157 // Restore accounts, if it has not happened already 158 // NOTE: This is blocking, which it should not be (in the UI thread) 159 // We're going to live with this for the short term and replace with something 160 // smarter. Long-term fix: Move this, and most of the code below, to an AsyncTask 161 // and do the DB work in a thread. Then post handler to finish() as appropriate. 162 AccountBackupRestore.restoreIfNeeded(this); 163 164 // Because the app could be reloaded (for debugging, etc.), we need to make sure that 165 // ExchangeService gets a chance to start. There is no harm to starting it if it has 166 // already been started 167 // When the service starts, it reconciles EAS accounts. 168 // TODO More completely separate ExchangeService from Email app 169 ExchangeUtils.startExchangeService(this); 170 171 new MainActivityLauncher(this, getIntent()).executeParallel(); 172 } 173 174 @Override 175 public void onDestroy() { 176 mTaskTracker.cancellAllInterrupt(); 177 super.onDestroy(); 178 } 179 180 /** 181 * Open an account with the Activity appropriate to the current configuration. 182 * If there's no accounts set up, open the "add account" screen. 183 * 184 * if {@code account} is -1, open the default account. 185 */ 186 @VisibleForTesting 187 static class MainActivityLauncher extends EmailAsyncTask<Void, Void, Void> { 188 private final Welcome mFromActivity; 189 private final int mDebugPaneMode; 190 private final long mAccountId; 191 private final long mMailboxId; 192 private final long mMessageId; 193 private final String mAccountUuid; 194 195 public MainActivityLauncher(Welcome fromActivity, Intent intent) { 196 super(fromActivity.mTaskTracker); 197 mFromActivity = fromActivity; 198 199 mAccountId = IntentUtilities.getAccountIdFromIntent(intent); 200 mMailboxId = IntentUtilities.getMailboxIdFromIntent(intent); 201 mMessageId = IntentUtilities.getMessageIdFromIntent(intent); 202 mAccountUuid = IntentUtilities.getAccountUuidFromIntent(intent); 203 mDebugPaneMode = getDebugPaneMode(intent); 204 } 205 206 private boolean isMailboxSelected() { 207 return mMailboxId != -1; 208 } 209 210 private boolean isMessageSelected() { 211 return mMessageId != -1; 212 } 213 214 @VisibleForTesting 215 static long resolveAccountId(Context context, long inputAccountId, String uuid) { 216 final long accountId; 217 218 if (!TextUtils.isEmpty(uuid)) { 219 accountId = Account.getAccountIdFromUuid(context, uuid); 220 // accountId will be NO_ACCOUNT if the UUID is invalid. 221 222 } else if (inputAccountId != Account.NO_ACCOUNT) { 223 if (Account.isValidId(context, inputAccountId)) { 224 accountId = inputAccountId; 225 } else { 226 accountId = Account.NO_ACCOUNT; 227 } 228 } else { 229 // Use the default (without showing the toast) 230 accountId = EmailContent.Account.getDefaultAccountId(context); 231 } 232 if (accountId != Account.NO_ACCOUNT) { 233 // Okay, the given account is valid. 234 return accountId; 235 } else { 236 // No, it's invalid. Show the warning toast and use the default. 237 Utility.showToast(context, R.string.toast_account_not_found); 238 return EmailContent.Account.getDefaultAccountId(context); 239 } 240 } 241 242 @Override 243 protected Void doInBackground(Void... params) { 244 // Reconcile POP/IMAP accounts. EAS accounts are taken care of by ExchangeService. 245 MailService.reconcilePopImapAccountsSync(mFromActivity); 246 247 final int numAccount = 248 EmailContent.count(mFromActivity, EmailContent.Account.CONTENT_URI); 249 if (numAccount == 0) { 250 AccountSetupBasics.actionNewAccount(mFromActivity); 251 } else { 252 final long accountId = resolveAccountId(mFromActivity, mAccountId, mAccountUuid); 253 254 final Intent i; 255 if (isMessageSelected()) { 256 i = EmailActivity.createOpenMessageIntent(mFromActivity, accountId, 257 mMailboxId, mMessageId); 258 } else if (isMailboxSelected()) { 259 i = EmailActivity.createOpenMailboxIntent(mFromActivity, accountId, 260 mMailboxId); 261 } else { 262 i = EmailActivity.createOpenAccountIntent(mFromActivity, accountId); 263 } 264 if (mDebugPaneMode != 0) { 265 EmailActivity.forcePaneMode(i, mDebugPaneMode == 2); 266 } 267 mFromActivity.startActivity(i); 268 } 269 return null; 270 } 271 272 @Override 273 protected void onPostExecute(Void result) { 274 mFromActivity.finish(); 275 } 276 } 277} 278