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