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