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