AccountSetupNames.java revision d71d0b223a5cd02e2a8f1ec5c3f8cebab170d65f
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.AccountBackupRestore;
20import com.android.email.R;
21import com.android.email.Utility;
22import com.android.email.provider.EmailContent;
23import com.android.email.provider.EmailContent.Account;
24import com.android.email.provider.EmailContent.AccountColumns;
25
26import android.app.Activity;
27import android.content.ContentUris;
28import android.content.ContentValues;
29import android.content.Intent;
30import android.database.Cursor;
31import android.os.AsyncTask;
32import android.os.Bundle;
33import android.text.Editable;
34import android.text.TextWatcher;
35import android.text.method.TextKeyListener;
36import android.text.method.TextKeyListener.Capitalize;
37import android.view.View;
38import android.view.View.OnClickListener;
39import android.widget.Button;
40import android.widget.EditText;
41
42public class AccountSetupNames extends Activity implements OnClickListener {
43    private static final String EXTRA_ACCOUNT_ID = "accountId";
44    private static final String EXTRA_EAS_FLOW = "easFlow";
45    private static final int REQUEST_SECURITY = 0;
46
47    private EditText mDescription;
48    private EditText mName;
49    private Account mAccount;
50    private Button mDoneButton;
51
52    private CheckAccountStateTask mCheckAccountStateTask;
53
54    private static final int ACCOUNT_INFO_COLUMN_FLAGS = 0;
55    private static final int ACCOUNT_INFO_COLUMN_SECURITY_FLAGS = 1;
56    private static final String[] ACCOUNT_INFO_PROJECTION = new String[] {
57            AccountColumns.FLAGS, AccountColumns.SECURITY_FLAGS };
58
59    public static void actionSetNames(Activity fromActivity, long accountId, boolean easFlowMode) {
60        Intent i = new Intent(fromActivity, AccountSetupNames.class);
61        i.putExtra(EXTRA_ACCOUNT_ID, accountId);
62        i.putExtra(EXTRA_EAS_FLOW, easFlowMode);
63        fromActivity.startActivity(i);
64    }
65
66    @Override
67    public void onCreate(Bundle savedInstanceState) {
68        super.onCreate(savedInstanceState);
69        setContentView(R.layout.account_setup_names);
70        mDescription = (EditText)findViewById(R.id.account_description);
71        mName = (EditText)findViewById(R.id.account_name);
72        mDoneButton = (Button)findViewById(R.id.done);
73        mDoneButton.setOnClickListener(this);
74
75        TextWatcher validationTextWatcher = new TextWatcher() {
76            public void afterTextChanged(Editable s) {
77                validateFields();
78            }
79
80            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
81            }
82
83            public void onTextChanged(CharSequence s, int start, int before, int count) {
84            }
85        };
86        mName.addTextChangedListener(validationTextWatcher);
87
88        mName.setKeyListener(TextKeyListener.getInstance(false, Capitalize.WORDS));
89
90        long accountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
91        mAccount = EmailContent.Account.restoreAccountWithId(this, accountId);
92
93        /*
94         * Since this field is considered optional, we don't set this here. If
95         * the user fills in a value we'll reset the current value, otherwise we
96         * just leave the saved value alone.
97         */
98        // mDescription.setText(mAccount.getDescription());
99        if (mAccount != null && mAccount.getSenderName() != null) {
100            mName.setText(mAccount.getSenderName());
101        }
102        if (!Utility.requiredFieldValid(mName)) {
103            mDoneButton.setEnabled(false);
104        }
105    }
106
107    @Override
108    protected void onDestroy() {
109        super.onDestroy();
110
111        if (mCheckAccountStateTask != null &&
112                mCheckAccountStateTask.getStatus() != CheckAccountStateTask.Status.FINISHED) {
113            mCheckAccountStateTask.cancel(true);
114            mCheckAccountStateTask = null;
115        }
116    }
117
118    /**
119     * TODO: Validator should also trim the name string before checking it.
120     */
121    private void validateFields() {
122        mDoneButton.setEnabled(Utility.requiredFieldValid(mName));
123        Utility.setCompoundDrawablesAlpha(mDoneButton, mDoneButton.isEnabled() ? 255 : 128);
124    }
125
126    @Override
127    public void onBackPressed() {
128        boolean easFlowMode = getIntent().getBooleanExtra(EXTRA_EAS_FLOW, false);
129        if (easFlowMode) {
130            AccountSetupBasics.actionAccountCreateFinishedEas(this);
131        } else {
132            AccountSetupBasics.actionAccountCreateFinished(this, mAccount.mId);
133        }
134        finish();
135    }
136
137    /**
138     * After having a chance to input the display names, we normally jump directly to the
139     * inbox for the new account.  However if we're in EAS flow mode (externally-launched
140     * account creation) we simply "pop" here which should return us to the Accounts activities.
141     *
142     * TODO: Validator should also trim the description string before checking it.
143     */
144    private void onNext() {
145        if (Utility.requiredFieldValid(mDescription)) {
146            mAccount.setDisplayName(mDescription.getText().toString());
147        }
148        String name = mName.getText().toString();
149        mAccount.setSenderName(name);
150        ContentValues cv = new ContentValues();
151        cv.put(AccountColumns.DISPLAY_NAME, mAccount.getDisplayName());
152        cv.put(AccountColumns.SENDER_NAME, name);
153        mAccount.update(this, cv);
154        // Update the backup (side copy) of the accounts
155        AccountBackupRestore.backupAccounts(this);
156
157        // Before proceeding, launch an AsyncTask to test the account for any syncing problems,
158        // and if there's a problem, bring up the UI to update the security level.
159        mCheckAccountStateTask = new CheckAccountStateTask(mAccount.mId);
160        mCheckAccountStateTask.execute();
161    }
162
163    public void onClick(View v) {
164        switch (v.getId()) {
165            case R.id.done:
166                onNext();
167                break;
168        }
169    }
170
171    /**
172     * This async task is launched just before exiting.  It's a last chance test, before leaving
173     * this activity, for the account being in a "hold" state, and gives the user a chance to
174     * update security, enter a device PIN, etc. for a more seamless account setup experience.
175     *
176     * TODO: If there was *any* indication that security might be required, we could at least
177     * force the DeviceAdmin activation step, without waiting for the initial sync/handshake
178     * to fail.
179     * TODO: If the user doesn't update the security, don't go to the MessageList.
180     */
181    private class CheckAccountStateTask extends AsyncTask<Void, Void, Boolean> {
182
183        private long mAccountId;
184
185        public CheckAccountStateTask(long accountId) {
186            mAccountId = accountId;
187        }
188
189        @Override
190        protected Boolean doInBackground(Void... params) {
191            Cursor c = AccountSetupNames.this.getContentResolver().query(
192                    ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId),
193                    ACCOUNT_INFO_PROJECTION, null, null, null);
194            try {
195                if (c.moveToFirst()) {
196                    int flags = c.getInt(ACCOUNT_INFO_COLUMN_FLAGS);
197                    int securityFlags = c.getInt(ACCOUNT_INFO_COLUMN_SECURITY_FLAGS);
198                    if ((flags & Account.FLAGS_SECURITY_HOLD) != 0) {
199                        return Boolean.TRUE;
200                    }
201                }
202            } finally {
203                c.close();
204            }
205
206            return Boolean.FALSE;
207        }
208
209        @Override
210        protected void onPostExecute(Boolean isSecurityHold) {
211            if (!isCancelled()) {
212                if (isSecurityHold) {
213                    Intent i = AccountSecurity.actionUpdateSecurityIntent(
214                            AccountSetupNames.this, mAccountId);
215                    AccountSetupNames.this.startActivityForResult(i, REQUEST_SECURITY);
216                } else {
217                    onBackPressed();
218                }
219            }
220        }
221    }
222
223    /**
224     * Handle the eventual result from the security update activity
225     *
226     * TODO: If the user doesn't update the security, don't go to the MessageList.
227     */
228    @Override
229    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
230        switch (requestCode) {
231            case REQUEST_SECURITY:
232                onBackPressed();
233        }
234        super.onActivityResult(requestCode, resultCode, data);
235    }
236
237}
238