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