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