AccountSetupExchange.java revision 9e2c6bd5f21f2d19eef7ebfe30e6fdf94ede0857
1/* 2 * Copyright (C) 2009 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.R; 20import com.android.email.Utility; 21import com.android.email.provider.EmailContent; 22 23import android.app.Activity; 24import android.content.Intent; 25import android.os.Bundle; 26import android.text.Editable; 27import android.text.TextUtils; 28import android.text.TextWatcher; 29import android.view.View; 30import android.view.View.OnClickListener; 31import android.widget.Button; 32import android.widget.CheckBox; 33import android.widget.EditText; 34 35import java.net.URI; 36import java.net.URISyntaxException; 37 38/** 39 * Provides generic setup for Exchange accounts. The following fields are supported: 40 * 41 * Email Address (from previous setup screen) 42 * Server 43 * Domain 44 * Requires SSL? 45 * User (login) 46 * Password 47 */ 48public class AccountSetupExchange extends Activity implements OnClickListener { 49 private static final String EXTRA_ACCOUNT = "account"; 50 private static final String EXTRA_MAKE_DEFAULT = "makeDefault"; 51 52 private EditText mUsernameView; 53 private EditText mPasswordView; 54 private EditText mServerView; 55 private EditText mDomainView; 56 private CheckBox mSslSecurityView; 57 58 private Button mNextButton; 59 private EmailContent.Account mAccount; 60 private boolean mMakeDefault; 61 62 public static void actionIncomingSettings(Activity fromActivity, EmailContent.Account account, 63 boolean makeDefault) { 64 Intent i = new Intent(fromActivity, AccountSetupExchange.class); 65 i.putExtra(EXTRA_ACCOUNT, account); 66 i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault); 67 fromActivity.startActivity(i); 68 } 69 70 public static void actionEditIncomingSettings(Activity fromActivity, EmailContent.Account account) 71 { 72 Intent i = new Intent(fromActivity, AccountSetupExchange.class); 73 i.setAction(Intent.ACTION_EDIT); 74 i.putExtra(EXTRA_ACCOUNT, account); 75 fromActivity.startActivity(i); 76 } 77 78 /** 79 * For now, we'll simply replicate outgoing, for the purpose of satisfying the 80 * account settings flow. 81 */ 82 public static void actionEditOutgoingSettings(Activity fromActivity, EmailContent.Account account) 83 { 84 Intent i = new Intent(fromActivity, AccountSetupExchange.class); 85 i.setAction(Intent.ACTION_EDIT); 86 i.putExtra(EXTRA_ACCOUNT, account); 87 fromActivity.startActivity(i); 88 } 89 90 @Override 91 public void onCreate(Bundle savedInstanceState) { 92 super.onCreate(savedInstanceState); 93 setContentView(R.layout.account_setup_exchange); 94 95 mUsernameView = (EditText) findViewById(R.id.account_username); 96 mPasswordView = (EditText) findViewById(R.id.account_password); 97 mServerView = (EditText) findViewById(R.id.account_server); 98 mDomainView = (EditText) findViewById(R.id.account_domain); 99 mSslSecurityView = (CheckBox) findViewById(R.id.account_ssl); 100 101 mNextButton = (Button)findViewById(R.id.next); 102 mNextButton.setOnClickListener(this); 103 104 /* 105 * Calls validateFields() which enables or disables the Next button 106 * based on the fields' validity. 107 */ 108 TextWatcher validationTextWatcher = new TextWatcher() { 109 public void afterTextChanged(Editable s) { 110 validateFields(); 111 } 112 113 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 114 } 115 116 public void onTextChanged(CharSequence s, int start, int before, int count) { 117 } 118 }; 119 mUsernameView.addTextChangedListener(validationTextWatcher); 120 mPasswordView.addTextChangedListener(validationTextWatcher); 121 mServerView.addTextChangedListener(validationTextWatcher); 122 mDomainView.addTextChangedListener(validationTextWatcher); 123 124 mAccount = (EmailContent.Account) getIntent().getParcelableExtra(EXTRA_ACCOUNT); 125 mMakeDefault = getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false); 126 127 /* 128 * If we're being reloaded we override the original account with the one 129 * we saved 130 */ 131 if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) { 132 mAccount = (EmailContent.Account) savedInstanceState.getParcelable(EXTRA_ACCOUNT); 133 } 134 135 try { 136 URI uri = new URI(mAccount.getStoreUri(this)); 137 String username = null; 138 String password = null; 139 if (uri.getUserInfo() != null) { 140 String[] userInfoParts = uri.getUserInfo().split(":", 2); 141 username = userInfoParts[0]; 142 if (userInfoParts.length > 1) { 143 password = userInfoParts[1]; 144 } 145 } 146 147 if (username != null) { 148 mUsernameView.setText(username); 149 } 150 151 if (password != null) { 152 mPasswordView.setText(password); 153 } 154 155 if (uri.getScheme().startsWith("eas")) { 156 // any other setup from mAccount can go here 157 } else { 158 throw new Error("Unknown account type: " + mAccount.getStoreUri(this)); 159 } 160 161 if (uri.getHost() != null) { 162 mServerView.setText(uri.getHost()); 163 } 164 165 String domain = uri.getPath(); 166 if (!TextUtils.isEmpty(domain)) { 167 mDomainView.setText(domain.substring(1)); 168 } 169 170 mSslSecurityView.setChecked(uri.getScheme().contains("ssl")); 171 172 } catch (URISyntaxException use) { 173 /* 174 * We should always be able to parse our own settings. 175 */ 176 throw new Error(use); 177 } 178 179 validateFields(); 180 } 181 182 @Override 183 public void onSaveInstanceState(Bundle outState) { 184 super.onSaveInstanceState(outState); 185 outState.putParcelable(EXTRA_ACCOUNT, mAccount); 186 } 187 188 /** 189 * Check the values in the fields and decide if it makes sense to enable the "next" button 190 * NOTE: Does it make sense to extract & combine with similar code in AccountSetupIncoming? 191 */ 192 private void validateFields() { 193 boolean enabled = Utility.requiredFieldValid(mUsernameView) 194 && Utility.requiredFieldValid(mPasswordView) 195 && Utility.requiredFieldValid(mServerView); 196 if (enabled) { 197 try { 198 URI uri = getUri(); 199 } catch (URISyntaxException use) { 200 enabled = false; 201 } 202 } 203 mNextButton.setEnabled(enabled); 204 Utility.setCompoundDrawablesAlpha(mNextButton, enabled ? 255 : 128); 205 } 206 207 @Override 208 public void onActivityResult(int requestCode, int resultCode, Intent data) { 209 if (resultCode == RESULT_OK) { 210 if (Intent.ACTION_EDIT.equals(getIntent().getAction())) { 211 // TODO Review carefully to make sure this is bulletproof 212 if (mAccount.isSaved()) { 213 mAccount.update(this, mAccount.toContentValues()); 214 } else { 215 mAccount.save(this); 216 } 217 finish(); 218 } else { 219 // Go directly to end - there is no 2nd screen for incoming settings 220 AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault); 221 finish(); 222 } 223 } 224 } 225 226 /** 227 * Attempt to create a URI from the fields provided. Throws URISyntaxException if there's 228 * a problem with the user input. 229 * @return a URI built from the account setup fields 230 */ 231 private URI getUri() throws URISyntaxException { 232 boolean sslRequired = mSslSecurityView.isChecked(); 233 String scheme = sslRequired ? "eas+ssl+" : "eas"; 234 String userInfo = mUsernameView.getText().toString().trim() + ":" + 235 mPasswordView.getText().toString().trim(); 236 String host = mServerView.getText().toString().trim(); 237 String domain = mDomainView.getText().toString().trim(); 238 String path = null; 239 if (domain.length() > 0) { 240 path = "/" + domain; 241 } 242 243 URI uri = new URI( 244 scheme, 245 userInfo, 246 host, 247 0, 248 path, 249 null, 250 null); 251 252 return uri; 253 } 254 255 /** 256 * Note, in EAS, store & sender are the same, so we always populate them together 257 */ 258 private void onNext() { 259 try { 260 URI uri = getUri(); 261 mAccount.setStoreUri(this, uri.toString()); 262 mAccount.setSenderUri(this, uri.toString()); 263 } catch (URISyntaxException use) { 264 /* 265 * It's unrecoverable if we cannot create a URI from components that 266 * we validated to be safe. 267 */ 268 throw new Error(use); 269 } 270 271 AccountSetupCheckSettings.actionCheckSettings(this, mAccount, true, false); 272 } 273 274 public void onClick(View v) { 275 switch (v.getId()) { 276 case R.id.next: 277 onNext(); 278 break; 279 } 280 } 281} 282