AccountSetupOptions.java revision 2959a7e073c87e2fa5fab42ec543b352a91cf187
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.setup;
18
19import com.android.email.Email;
20import com.android.email.ExchangeUtils;
21import com.android.email.R;
22import com.android.email.SecurityPolicy.PolicySet;
23import com.android.email.activity.ActivityHelper;
24import com.android.email.mail.Store;
25import com.android.email.provider.EmailContent;
26import com.android.email.provider.EmailContent.Account;
27import com.android.email.service.MailService;
28
29import android.accounts.AccountManagerCallback;
30import android.accounts.AccountManagerFuture;
31import android.accounts.AuthenticatorException;
32import android.accounts.OperationCanceledException;
33import android.app.Activity;
34import android.app.AlertDialog;
35import android.content.DialogInterface;
36import android.content.Intent;
37import android.os.Bundle;
38import android.os.Handler;
39import android.util.Log;
40import android.view.View;
41import android.view.View.OnClickListener;
42import android.widget.ArrayAdapter;
43import android.widget.CheckBox;
44import android.widget.Spinner;
45
46import java.io.IOException;
47
48public class AccountSetupOptions extends AccountSetupActivity implements OnClickListener {
49
50    private Spinner mCheckFrequencyView;
51    private Spinner mSyncWindowView;
52    private CheckBox mDefaultView;
53    private CheckBox mNotifyView;
54    private CheckBox mSyncContactsView;
55    private CheckBox mSyncCalendarView;
56    private CheckBox mSyncEmailView;
57    private Handler mHandler = new Handler();
58    private boolean mDonePressed = false;
59
60    public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
61
62    /** Default sync window for new EAS accounts */
63    private static final int SYNC_WINDOW_EAS_DEFAULT = com.android.email.Account.SYNC_WINDOW_3_DAYS;
64
65    public static void actionOptions(Activity fromActivity) {
66        fromActivity.startActivity(new Intent(fromActivity, AccountSetupOptions.class));
67    }
68
69    @Override
70    public void onCreate(Bundle savedInstanceState) {
71        super.onCreate(savedInstanceState);
72        ActivityHelper.debugSetWindowFlags(this);
73        setContentView(R.layout.account_setup_options);
74
75        mCheckFrequencyView = (Spinner)findViewById(R.id.account_check_frequency);
76        mSyncWindowView = (Spinner) findViewById(R.id.account_sync_window);
77        mDefaultView = (CheckBox)findViewById(R.id.account_default);
78        mNotifyView = (CheckBox)findViewById(R.id.account_notify);
79        mSyncContactsView = (CheckBox) findViewById(R.id.account_sync_contacts);
80        mSyncCalendarView = (CheckBox) findViewById(R.id.account_sync_calendar);
81        mSyncEmailView = (CheckBox) findViewById(R.id.account_sync_email);
82        mSyncEmailView.setChecked(true);
83        findViewById(R.id.previous).setOnClickListener(this);
84        findViewById(R.id.next).setOnClickListener(this);
85
86        // Generate spinner entries using XML arrays used by the preferences
87        int frequencyValuesId;
88        int frequencyEntriesId;
89        Account account = SetupData.getAccount();
90        Store.StoreInfo info = Store.StoreInfo.getStoreInfo(account.getStoreUri(this), this);
91        if (info.mPushSupported) {
92            frequencyValuesId = R.array.account_settings_check_frequency_values_push;
93            frequencyEntriesId = R.array.account_settings_check_frequency_entries_push;
94        } else {
95            frequencyValuesId = R.array.account_settings_check_frequency_values;
96            frequencyEntriesId = R.array.account_settings_check_frequency_entries;
97        }
98        CharSequence[] frequencyValues = getResources().getTextArray(frequencyValuesId);
99        CharSequence[] frequencyEntries = getResources().getTextArray(frequencyEntriesId);
100
101        // Now create the array used by the Spinner
102        SpinnerOption[] checkFrequencies = new SpinnerOption[frequencyEntries.length];
103        for (int i = 0; i < frequencyEntries.length; i++) {
104            checkFrequencies[i] = new SpinnerOption(
105                    Integer.valueOf(frequencyValues[i].toString()), frequencyEntries[i].toString());
106        }
107
108        ArrayAdapter<SpinnerOption> checkFrequenciesAdapter = new ArrayAdapter<SpinnerOption>(this,
109                android.R.layout.simple_spinner_item, checkFrequencies);
110        checkFrequenciesAdapter
111                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
112        mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
113
114        if (info.mVisibleLimitDefault == -1) {
115            enableEASSyncWindowSpinner();
116        }
117
118        // Note:  It is OK to use mAccount.mIsDefault here *only* because the account
119        // has not been written to the DB yet.  Ordinarily, call Account.getDefaultAccountId().
120        if (account.mIsDefault || SetupData.isDefault()) {
121            mDefaultView.setChecked(true);
122        }
123        mNotifyView.setChecked(
124                (account.getFlags() & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL) != 0);
125        SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, account.getSyncInterval());
126
127        // Setup any additional items to support EAS & EAS flow mode
128        if ("eas".equals(info.mScheme)) {
129            // "also sync contacts" == "true"
130            mSyncContactsView.setVisibility(View.VISIBLE);
131            mSyncContactsView.setChecked(true);
132            mSyncCalendarView.setVisibility(View.VISIBLE);
133            mSyncCalendarView.setChecked(true);
134            // Show the associated dividers
135            findViewById(R.id.account_sync_contacts_divider).setVisibility(View.VISIBLE);
136            findViewById(R.id.account_sync_calendar_divider).setVisibility(View.VISIBLE);
137        }
138
139        // If we are just visiting here to fill in details, exit immediately
140        if (SetupData.isAutoSetup() ||
141                SetupData.getFlowMode() == SetupData.FLOW_MODE_FORCE_CREATE) {
142            onDone();
143        }
144    }
145
146    /**
147     * Respond to clicks in the "Next" or "Previous" buttons
148     */
149    @Override
150    public void onClick(View view) {
151        switch (view.getId()) {
152            case R.id.next:
153                // Don't allow this more than once (Exchange accounts call an async method
154                // before finish()'ing the Activity, which allows this code to potentially be
155                // executed multiple times
156                if (!mDonePressed) {
157                    onDone();
158                    mDonePressed = true;
159                }
160                break;
161            case R.id.previous:
162                onBackPressed();
163                break;
164        }
165    }
166
167    AccountManagerCallback<Bundle> mAccountManagerCallback = new AccountManagerCallback<Bundle>() {
168        public void run(AccountManagerFuture<Bundle> future) {
169            try {
170                Bundle bundle = future.getResult();
171                bundle.keySet();
172                mHandler.post(new Runnable() {
173                    public void run() {
174                        optionsComplete();
175                    }
176                });
177                return;
178            } catch (OperationCanceledException e) {
179                Log.d(Email.LOG_TAG, "addAccount was canceled");
180            } catch (IOException e) {
181                Log.d(Email.LOG_TAG, "addAccount failed: " + e);
182            } catch (AuthenticatorException e) {
183                Log.d(Email.LOG_TAG, "addAccount failed: " + e);
184            }
185            showErrorDialog(R.string.account_setup_failed_dlg_auth_message,
186                    R.string.system_account_create_failed);
187        }
188    };
189
190    private void showErrorDialog(final int msgResId, final Object... args) {
191        mHandler.post(new Runnable() {
192            public void run() {
193                new AlertDialog.Builder(AccountSetupOptions.this)
194                        .setIcon(android.R.drawable.ic_dialog_alert)
195                        .setTitle(getString(R.string.account_setup_failed_dlg_title))
196                        .setMessage(getString(msgResId, args))
197                        .setCancelable(true)
198                        .setPositiveButton(
199                                getString(R.string.account_setup_failed_dlg_edit_details_action),
200                                new DialogInterface.OnClickListener() {
201                                    public void onClick(DialogInterface dialog, int which) {
202                                       finish();
203                                    }
204                                })
205                        .show();
206            }
207        });
208    }
209
210    @Override
211    public void onActivityResult(int requestCode, int resultCode, Intent data) {
212        saveAccountAndFinish();
213    }
214
215    private void optionsComplete() {
216        // If we've got policies for this account, ask the user to accept.
217        Account account = SetupData.getAccount();
218        if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
219            Intent intent = AccountSecurity.actionUpdateSecurityIntent(this, account.mId);
220            startActivityForResult(intent, AccountSetupOptions.REQUEST_CODE_ACCEPT_POLICIES);
221            return;
222        }
223        saveAccountAndFinish();
224    }
225
226    /**
227     * STOPSHIP most of this work needs to be async
228     */
229    private void saveAccountAndFinish() {
230        // Clear the incomplete/security hold flag now
231        Account account = SetupData.getAccount();
232        account.mFlags &= ~(Account.FLAGS_INCOMPLETE | Account.FLAGS_SECURITY_HOLD);
233        AccountSettingsUtils.commitSettings(this, account);
234        Email.setServicesEnabledSync(this);
235        AccountSetupNames.actionSetNames(this);
236        // Start up ExchangeService (if it isn't already running)
237        ExchangeUtils.startExchangeService(this);
238        finish();
239    }
240
241    private void onDone() {
242        Account account = SetupData.getAccount();
243        account.setDisplayName(account.getEmailAddress());
244        int newFlags = account.getFlags() & ~(EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL);
245        if (mNotifyView.isChecked()) {
246            newFlags |= EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL;
247        }
248        account.setFlags(newFlags);
249        account.setSyncInterval((Integer)((SpinnerOption)mCheckFrequencyView
250                .getSelectedItem()).value);
251        if (findViewById(R.id.account_sync_window_row).getVisibility() == View.VISIBLE) {
252            int window = (Integer)((SpinnerOption)mSyncWindowView.getSelectedItem()).value;
253            account.setSyncLookback(window);
254        }
255        account.setDefaultAccount(mDefaultView.isChecked());
256
257        // Setup up the AccountManager account
258        if (!account.isSaved() && account.mHostAuthRecv != null) {
259            // Set the incomplete flag here to avoid reconciliation issues in ExchangeService
260            account.mFlags |= Account.FLAGS_INCOMPLETE;
261            boolean calendar = false;
262            boolean contacts = false;
263            boolean email = mSyncEmailView.isChecked();
264            if (account.mHostAuthRecv.mProtocol.equals("eas")) {
265                // Set security hold if necessary to prevent sync until policies are accepted
266                PolicySet policySet = SetupData.getPolicySet();
267                if (policySet != null && policySet.getSecurityCode() != 0) {
268                    account.mSecurityFlags = policySet.getSecurityCode();
269                    account.mFlags |= Account.FLAGS_SECURITY_HOLD;
270                }
271                // Get flags for contacts/calendar sync
272                contacts = mSyncContactsView.isChecked();
273                calendar = mSyncCalendarView.isChecked();
274            }
275            AccountSettingsUtils.commitSettings(this, account);
276            MailService.setupAccountManagerAccount(this, account, email, calendar, contacts,
277                    mAccountManagerCallback);
278        } else {
279            optionsComplete();
280        }
281    }
282
283    /**
284     * Enable an additional spinner using the arrays normally handled by preferences
285     */
286    private void enableEASSyncWindowSpinner() {
287        // Show everything
288        findViewById(R.id.account_sync_window_row).setVisibility(View.VISIBLE);
289
290        // Generate spinner entries using XML arrays used by the preferences
291        CharSequence[] windowValues = getResources().getTextArray(
292                R.array.account_settings_mail_window_values);
293        CharSequence[] windowEntries = getResources().getTextArray(
294                R.array.account_settings_mail_window_entries);
295
296        // Now create the array used by the Spinner
297        SpinnerOption[] windowOptions = new SpinnerOption[windowEntries.length];
298        int defaultIndex = -1;
299        for (int i = 0; i < windowEntries.length; i++) {
300            final int value = Integer.valueOf(windowValues[i].toString());
301            windowOptions[i] = new SpinnerOption(value, windowEntries[i].toString());
302            if (value == SYNC_WINDOW_EAS_DEFAULT) {
303                defaultIndex = i;
304            }
305        }
306
307        ArrayAdapter<SpinnerOption> windowOptionsAdapter = new ArrayAdapter<SpinnerOption>(this,
308                android.R.layout.simple_spinner_item, windowOptions);
309        windowOptionsAdapter
310                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
311        mSyncWindowView.setAdapter(windowOptionsAdapter);
312
313        SpinnerOption.setSpinnerOptionValue(mSyncWindowView,
314                SetupData.getAccount().getSyncLookback());
315        if (defaultIndex >= 0) {
316            mSyncWindowView.setSelection(defaultIndex);
317        }
318    }
319}
320