AccountSetupIncomingFragment.java revision 064726d9f9fb7c38a252fc9c4fe2b7cf645eade0
1/* 2 * Copyright (C) 2010 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 android.app.Activity; 20import android.content.Context; 21import android.content.Intent; 22import android.content.Loader; 23import android.net.Uri; 24import android.os.Bundle; 25import android.text.Editable; 26import android.text.TextUtils; 27import android.text.TextWatcher; 28import android.text.method.DigitsKeyListener; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.ViewGroup; 32import android.view.inputmethod.EditorInfo; 33import android.widget.AdapterView; 34import android.widget.ArrayAdapter; 35import android.widget.EditText; 36import android.widget.Spinner; 37import android.widget.TextView; 38 39import com.android.email.R; 40import com.android.email.activity.UiUtilities; 41import com.android.email.activity.setup.AuthenticationView.AuthenticationCallback; 42import com.android.email.provider.AccountBackupRestore; 43import com.android.email.service.EmailServiceUtils.EmailServiceInfo; 44import com.android.email.view.CertificateSelector; 45import com.android.email.view.CertificateSelector.HostCallback; 46import com.android.emailcommon.Device; 47import com.android.emailcommon.provider.Account; 48import com.android.emailcommon.provider.Credential; 49import com.android.emailcommon.provider.HostAuth; 50import com.android.emailcommon.utility.CertificateRequestor; 51import com.android.emailcommon.utility.Utility; 52import com.android.mail.ui.MailAsyncTaskLoader; 53import com.android.mail.utils.LogUtils; 54 55import java.io.IOException; 56import java.util.ArrayList; 57 58/** 59 * Provides UI for IMAP/POP account settings. 60 * 61 * This fragment is used by AccountSetupIncoming (for creating accounts) and by AccountSettingsXL 62 * (for editing existing accounts). 63 */ 64public class AccountSetupIncomingFragment extends AccountServerBaseFragment 65 implements HostCallback, AuthenticationCallback { 66 67 private static final int CERTIFICATE_REQUEST = 0; 68 private static final int SIGN_IN_REQUEST = 1; 69 70 private final static String STATE_KEY_CREDENTIAL = "AccountSetupIncomingFragment.credential"; 71 private final static String STATE_KEY_LOADED = "AccountSetupIncomingFragment.loaded"; 72 73 private EditText mUsernameView; 74 private AuthenticationView mAuthenticationView; 75 private TextView mAuthenticationLabel; 76 private TextView mServerLabelView; 77 private EditText mServerView; 78 private EditText mPortView; 79 private Spinner mSecurityTypeView; 80 private TextView mDeletePolicyLabelView; 81 private Spinner mDeletePolicyView; 82 private CertificateSelector mClientCertificateSelector; 83 private View mDeviceIdSection; 84 private View mImapPathPrefixSectionView; 85 private EditText mImapPathPrefixView; 86 // Delete policy as loaded from the device 87 private int mLoadedDeletePolicy; 88 89 private TextWatcher mValidationTextWatcher; 90 91 // Support for lifecycle 92 private boolean mLoaded; 93 private String mCacheLoginCredential; 94 private EmailServiceInfo mServiceInfo; 95 96 public static AccountSetupIncomingFragment newInstance(boolean settingsMode) { 97 final AccountSetupIncomingFragment f = new AccountSetupIncomingFragment(); 98 f.setArguments(getArgs(settingsMode)); 99 return f; 100 } 101 102 // Public no-args constructor needed for fragment re-instantiation 103 public AccountSetupIncomingFragment() {} 104 105 /** 106 * Called to do initial creation of a fragment. This is called after 107 * {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}. 108 */ 109 @Override 110 public void onCreate(Bundle savedInstanceState) { 111 super.onCreate(savedInstanceState); 112 113 if (savedInstanceState != null) { 114 mCacheLoginCredential = savedInstanceState.getString(STATE_KEY_CREDENTIAL); 115 mLoaded = savedInstanceState.getBoolean(STATE_KEY_LOADED, false); 116 } 117 } 118 119 @Override 120 public View onCreateView(LayoutInflater inflater, ViewGroup container, 121 Bundle savedInstanceState) { 122 final int layoutId = mSettingsMode 123 ? R.layout.account_settings_incoming_fragment 124 : R.layout.account_setup_incoming_fragment; 125 126 final View view = inflater.inflate(layoutId, container, false); 127 128 mUsernameView = UiUtilities.getView(view, R.id.account_username); 129 mServerLabelView = UiUtilities.getView(view, R.id.account_server_label); 130 mServerView = UiUtilities.getView(view, R.id.account_server); 131 mPortView = UiUtilities.getView(view, R.id.account_port); 132 mSecurityTypeView = UiUtilities.getView(view, R.id.account_security_type); 133 mDeletePolicyLabelView = UiUtilities.getView(view, R.id.account_delete_policy_label); 134 mDeletePolicyView = UiUtilities.getView(view, R.id.account_delete_policy); 135 mImapPathPrefixSectionView = UiUtilities.getView(view, R.id.imap_path_prefix_section); 136 mImapPathPrefixView = UiUtilities.getView(view, R.id.imap_path_prefix); 137 mAuthenticationView = UiUtilities.getView(view, R.id.authentication_view); 138 mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector); 139 mDeviceIdSection = UiUtilities.getView(view, R.id.device_id_section); 140 // Don't use UiUtilities here. In some configurations this view does not exist, and 141 // UiUtilities throws an exception in this case. 142 mAuthenticationLabel = (TextView)view.findViewById(R.id.authentication_label); 143 144 // Updates the port when the user changes the security type. This allows 145 // us to show a reasonable default which the user can change. 146 mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 147 @Override 148 public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { 149 updatePortFromSecurityType(); 150 } 151 152 @Override 153 public void onNothingSelected(AdapterView<?> arg0) { } 154 }); 155 156 // After any text edits, call validateFields() which enables or disables the Next button 157 mValidationTextWatcher = new TextWatcher() { 158 @Override 159 public void afterTextChanged(Editable s) { 160 validateFields(); 161 } 162 163 @Override 164 public void beforeTextChanged(CharSequence s, int start, int count, int after) { } 165 @Override 166 public void onTextChanged(CharSequence s, int start, int before, int count) { } 167 }; 168 // We're editing an existing account; don't allow modification of the user name 169 if (mSettingsMode) { 170 makeTextViewUneditable(mUsernameView, 171 getString(R.string.account_setup_username_uneditable_error)); 172 } 173 mUsernameView.addTextChangedListener(mValidationTextWatcher); 174 mServerView.addTextChangedListener(mValidationTextWatcher); 175 mPortView.addTextChangedListener(mValidationTextWatcher); 176 177 // Only allow digits in the port field. 178 mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789")); 179 180 // Additional setup only used while in "settings" mode 181 onCreateViewSettingsMode(view); 182 183 mAuthenticationView.setAuthenticationCallback(this); 184 185 return view; 186 } 187 188 @Override 189 public void onActivityCreated(Bundle savedInstanceState) { 190 super.onActivityCreated(savedInstanceState); 191 mClientCertificateSelector.setHostCallback(this); 192 193 final Context context = getActivity(); 194 final SetupDataFragment.SetupDataContainer container = 195 (SetupDataFragment.SetupDataContainer) context; 196 mSetupData = container.getSetupData(); 197 final Account account = mSetupData.getAccount(); 198 final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext); 199 200 // Pre-fill info as appropriate 201 if (!mSetupData.isIncomingCredLoaded()) { 202 recvAuth.mLogin = mSetupData.getEmail(); 203 AccountSetupCredentialsFragment.populateHostAuthWithResults(context, recvAuth, 204 mSetupData.getCredentialResults()); 205 final String[] emailParts = mSetupData.getEmail().split("@"); 206 final String domain = emailParts[1]; 207 recvAuth.setConnection(recvAuth.mProtocol, domain, HostAuth.PORT_UNKNOWN, 208 HostAuth.FLAG_NONE); 209 mSetupData.setIncomingCredLoaded(true); 210 } 211 212 mServiceInfo = mSetupData.getIncomingServiceInfo(context); 213 214 if (mServiceInfo.offerLocalDeletes) { 215 SpinnerOption deletePolicies[] = { 216 new SpinnerOption(Account.DELETE_POLICY_NEVER, 217 context.getString( 218 R.string.account_setup_incoming_delete_policy_never_label)), 219 new SpinnerOption(Account.DELETE_POLICY_ON_DELETE, 220 context.getString( 221 R.string.account_setup_incoming_delete_policy_delete_label)), 222 }; 223 ArrayAdapter<SpinnerOption> deletePoliciesAdapter = 224 new ArrayAdapter<SpinnerOption>(context, 225 android.R.layout.simple_spinner_item, deletePolicies); 226 deletePoliciesAdapter.setDropDownViewResource( 227 android.R.layout.simple_spinner_dropdown_item); 228 mDeletePolicyView.setAdapter(deletePoliciesAdapter); 229 } 230 231 // Set up security type spinner 232 ArrayList<SpinnerOption> securityTypes = new ArrayList<SpinnerOption>(); 233 securityTypes.add( 234 new SpinnerOption(HostAuth.FLAG_NONE, context.getString( 235 R.string.account_setup_incoming_security_none_label))); 236 securityTypes.add( 237 new SpinnerOption(HostAuth.FLAG_SSL, context.getString( 238 R.string.account_setup_incoming_security_ssl_label))); 239 securityTypes.add( 240 new SpinnerOption(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, context.getString( 241 R.string.account_setup_incoming_security_ssl_trust_certificates_label))); 242 if (mServiceInfo.offerTls) { 243 securityTypes.add( 244 new SpinnerOption(HostAuth.FLAG_TLS, context.getString( 245 R.string.account_setup_incoming_security_tls_label))); 246 securityTypes.add(new SpinnerOption(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL, 247 context.getString(R.string 248 .account_setup_incoming_security_tls_trust_certificates_label))); 249 } 250 ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>( 251 context, android.R.layout.simple_spinner_item, securityTypes); 252 securityTypesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 253 mSecurityTypeView.setAdapter(securityTypesAdapter); 254 255 configureEditor(); 256 loadSettings(); 257 } 258 259 /** 260 * Called when the fragment is visible to the user and actively running. 261 */ 262 @Override 263 public void onResume() { 264 super.onResume(); 265 validateFields(); 266 } 267 268 @Override 269 public void onDestroyView() { 270 // Make sure we don't get callbacks after the views are supposed to be destroyed 271 // and also don't hold onto them longer than we need 272 if (mUsernameView != null) { 273 mUsernameView.removeTextChangedListener(mValidationTextWatcher); 274 } 275 mUsernameView = null; 276 mServerLabelView = null; 277 if (mServerView != null) { 278 mServerView.removeTextChangedListener(mValidationTextWatcher); 279 } 280 mServerView = null; 281 if (mPortView != null) { 282 mPortView.removeTextChangedListener(mValidationTextWatcher); 283 } 284 mPortView = null; 285 if (mSecurityTypeView != null) { 286 mSecurityTypeView.setOnItemSelectedListener(null); 287 } 288 mSecurityTypeView = null; 289 mDeletePolicyLabelView = null; 290 mDeletePolicyView = null; 291 mImapPathPrefixSectionView = null; 292 mImapPathPrefixView = null; 293 mDeviceIdSection = null; 294 mClientCertificateSelector = null; 295 296 super.onDestroyView(); 297 } 298 299 @Override 300 public void onSaveInstanceState(Bundle outState) { 301 super.onSaveInstanceState(outState); 302 303 outState.putString(STATE_KEY_CREDENTIAL, mCacheLoginCredential); 304 outState.putBoolean(STATE_KEY_LOADED, mLoaded); 305 } 306 307 /** 308 * Configure the editor for the account type 309 */ 310 private void configureEditor() { 311 final Account account = mSetupData.getAccount(); 312 if (account == null || account.mHostAuthRecv == null) { 313 LogUtils.e(LogUtils.TAG, 314 "null account or host auth. account null: %b host auth null: %b", 315 account == null, account == null || account.mHostAuthRecv == null); 316 return; 317 } 318 TextView lastView = mImapPathPrefixView; 319 mBaseScheme = account.mHostAuthRecv.mProtocol; 320 mServerLabelView.setText(R.string.account_setup_incoming_server_label); 321 mServerView.setContentDescription(getResources().getText( 322 R.string.account_setup_incoming_server_label)); 323 if (!mServiceInfo.offerPrefix) { 324 mImapPathPrefixSectionView.setVisibility(View.GONE); 325 lastView = mPortView; 326 } 327 if (!mServiceInfo.offerLocalDeletes) { 328 mDeletePolicyLabelView.setVisibility(View.GONE); 329 mDeletePolicyView.setVisibility(View.GONE); 330 mPortView.setImeOptions(EditorInfo.IME_ACTION_NEXT); 331 } 332 lastView.setOnEditorActionListener(mDismissImeOnDoneListener); 333 } 334 335 /** 336 * Load the current settings into the UI 337 */ 338 private void loadSettings() { 339 if (mLoaded) return; 340 341 final Account account = mSetupData.getAccount(); 342 final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext); 343 mServiceInfo = mSetupData.getIncomingServiceInfo(getActivity()); 344 mAuthenticationView.setAuthInfo(mServiceInfo.offerOAuth, recvAuth); 345 if (mAuthenticationLabel != null) { 346 if (mServiceInfo.offerOAuth) { 347 mAuthenticationLabel.setText(R.string.authentication_label); 348 } else { 349 mAuthenticationLabel.setText(R.string.password_label); 350 } 351 } 352 353 final String username = recvAuth.mLogin; 354 if (username != null) { 355 //*** For eas? 356 // Add a backslash to the start of the username, but only if the username has no 357 // backslash in it. 358 //if (userName.indexOf('\\') < 0) { 359 // userName = "\\" + userName; 360 //} 361 mUsernameView.setText(username); 362 } 363 364 if (mServiceInfo.offerPrefix) { 365 final String prefix = recvAuth.mDomain; 366 if (prefix != null && prefix.length() > 0) { 367 mImapPathPrefixView.setText(prefix.substring(1)); 368 } 369 } 370 371 // The delete policy is set for all legacy accounts. For POP3 accounts, the user sets 372 // the policy explicitly. For IMAP accounts, the policy is set when the Account object 373 // is created. @see AccountSetupBasics#populateSetupData 374 mLoadedDeletePolicy = account.getDeletePolicy(); 375 SpinnerOption.setSpinnerOptionValue(mDeletePolicyView, mLoadedDeletePolicy); 376 377 int flags = recvAuth.mFlags; 378 if (mServiceInfo.defaultSsl) { 379 flags |= HostAuth.FLAG_SSL; 380 } 381 // Strip out any flags that are not related to security type. 382 int securityTypeFlags = (flags & HostAuth.FLAG_TRANSPORTSECURITY_MASK); 383 SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, securityTypeFlags); 384 385 final String hostname = recvAuth.mAddress; 386 if (hostname != null) { 387 mServerView.setText(hostname); 388 } 389 390 final int port = recvAuth.mPort; 391 if (port != HostAuth.PORT_UNKNOWN) { 392 mPortView.setText(Integer.toString(port)); 393 } else { 394 updatePortFromSecurityType(); 395 } 396 397 mLoadedRecvAuth = recvAuth; 398 mLoaded = true; 399 validateFields(); 400 } 401 402 /** 403 * Check the values in the fields and decide if it makes sense to enable the "next" button 404 */ 405 private void validateFields() { 406 if (!mLoaded) return; 407 enableNextButton(!TextUtils.isEmpty(mUsernameView.getText()) 408 && mAuthenticationView.getAuthValid() 409 && Utility.isServerNameValid(mServerView) 410 && Utility.isPortFieldValid(mPortView)); 411 412 mCacheLoginCredential = mUsernameView.getText().toString().trim(); 413 } 414 415 private int getPortFromSecurityType(boolean useSsl) { 416 return useSsl ? mServiceInfo.portSsl : mServiceInfo.port; 417 } 418 419 private boolean getSslSelected() { 420 final int securityType = 421 (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value; 422 return ((securityType & HostAuth.FLAG_SSL) != 0); 423 } 424 425 public void onUseSslChanged(boolean useSsl) { 426 if (mServiceInfo.offerCerts) { 427 final int mode = useSsl ? View.VISIBLE : View.GONE; 428 mClientCertificateSelector.setVisibility(mode); 429 String deviceId = ""; 430 try { 431 deviceId = Device.getDeviceId(mAppContext); 432 } catch (IOException e) { 433 // Not required 434 } 435 ((TextView) UiUtilities.getView(getView(), R.id.device_id)).setText(deviceId); 436 437 mDeviceIdSection.setVisibility(mode); 438 } 439 } 440 441 private void updatePortFromSecurityType() { 442 final boolean sslSelected = getSslSelected(); 443 final int port = getPortFromSecurityType(sslSelected); 444 mPortView.setText(Integer.toString(port)); 445 onUseSslChanged(sslSelected); 446 } 447 448 private static class SaveSettingsLoader extends MailAsyncTaskLoader<Boolean> { 449 private final SetupDataFragment mSetupData; 450 private final boolean mSettingsMode; 451 452 private SaveSettingsLoader(Context context, SetupDataFragment setupData, 453 boolean settingsMode) { 454 super(context); 455 mSetupData = setupData; 456 mSettingsMode = settingsMode; 457 } 458 459 @Override 460 public Boolean loadInBackground() { 461 if (mSettingsMode) { 462 saveSettingsAfterEdit(getContext(), mSetupData); 463 } else { 464 saveSettingsAfterSetup(getContext(), mSetupData); 465 } 466 return true; 467 } 468 469 @Override 470 protected void onDiscardResult(Boolean result) {} 471 } 472 473 @Override 474 public Loader<Boolean> getSaveSettingsLoader() { 475 return new SaveSettingsLoader(mAppContext, mSetupData, mSettingsMode); 476 } 477 478 /** 479 * Entry point from Activity after editing settings and verifying them. Must be FLOW_MODE_EDIT. 480 * Note, we update account here (as well as the account.mHostAuthRecv) because we edit 481 * account's delete policy here. 482 * Blocking - do not call from UI Thread. 483 */ 484 public static void saveSettingsAfterEdit(Context context, SetupDataFragment setupData) { 485 final Account account = setupData.getAccount(); 486 account.update(context, account.toContentValues()); 487 final Credential cred = account.mHostAuthRecv.mCredential; 488 if (cred != null) { 489 if (cred.isSaved()) { 490 cred.update(context, cred.toContentValues()); 491 } else { 492 cred.save(context); 493 account.mHostAuthRecv.mCredentialKey = cred.mId; 494 } 495 } 496 account.mHostAuthRecv.update(context, account.mHostAuthRecv.toContentValues()); 497 // Update the backup (side copy) of the accounts 498 AccountBackupRestore.backup(context); 499 } 500 501 /** 502 * Entry point from Activity after entering new settings and verifying them. For setup mode. 503 */ 504 public static void saveSettingsAfterSetup(Context context, SetupDataFragment setupData) { 505 final Account account = setupData.getAccount(); 506 final HostAuth recvAuth = account.getOrCreateHostAuthRecv(context); 507 final HostAuth sendAuth = account.getOrCreateHostAuthSend(context); 508 509 // Set the username and password for the outgoing settings to the username and 510 // password the user just set for incoming. Use the verified host address to try and 511 // pick a smarter outgoing address. 512 final String hostName = 513 AccountSettingsUtils.inferServerName(context, recvAuth.mAddress, null, "smtp"); 514 sendAuth.setLogin(recvAuth.mLogin, recvAuth.mPassword); 515 sendAuth.setConnection(sendAuth.mProtocol, hostName, sendAuth.mPort, sendAuth.mFlags); 516 } 517 518 /** 519 * Entry point from Activity, when "next" button is clicked 520 */ 521 @Override 522 public void collectUserInput() { 523 final Account account = mSetupData.getAccount(); 524 525 // Make sure delete policy is an valid option before using it; otherwise, the results are 526 // indeterminate, I suspect... 527 if (mDeletePolicyView.getVisibility() == View.VISIBLE) { 528 account.setDeletePolicy( 529 (Integer) ((SpinnerOption) mDeletePolicyView.getSelectedItem()).value); 530 } 531 532 final HostAuth recvAuth = account.getOrCreateHostAuthRecv(mAppContext); 533 final String userName = mUsernameView.getText().toString().trim(); 534 final String userPassword = mAuthenticationView.getPassword(); 535 recvAuth.setLogin(userName, userPassword); 536 if (!TextUtils.isEmpty(mAuthenticationView.getOAuthProvider())) { 537 Credential cred = recvAuth.getOrCreateCredential(getActivity()); 538 cred.mProviderId = mAuthenticationView.getOAuthProvider(); 539 } 540 541 final String serverAddress = mServerView.getText().toString().trim(); 542 int serverPort; 543 try { 544 serverPort = Integer.parseInt(mPortView.getText().toString().trim()); 545 } catch (NumberFormatException e) { 546 serverPort = getPortFromSecurityType(getSslSelected()); 547 LogUtils.d(LogUtils.TAG, "Non-integer server port; using '" + serverPort + "'"); 548 } 549 final int securityType = 550 (Integer) ((SpinnerOption) mSecurityTypeView.getSelectedItem()).value; 551 recvAuth.setConnection(mBaseScheme, serverAddress, serverPort, securityType); 552 if (mServiceInfo.offerPrefix) { 553 final String prefix = mImapPathPrefixView.getText().toString().trim(); 554 recvAuth.mDomain = TextUtils.isEmpty(prefix) ? null : ("/" + prefix); 555 } else { 556 recvAuth.mDomain = null; 557 } 558 recvAuth.mClientCertAlias = mClientCertificateSelector.getCertificate(); 559 560 final Callback callback = (Callback) getActivity(); 561 callback.onAccountServerUIComplete(SetupDataFragment.CHECK_INCOMING); 562 } 563 564 @Override 565 public boolean haveSettingsChanged() { 566 final boolean deletePolicyChanged; 567 568 // Only verify the delete policy if the control is visible (i.e. is a pop3 account) 569 if (mDeletePolicyView != null && mDeletePolicyView.getVisibility() == View.VISIBLE) { 570 int newDeletePolicy = 571 (Integer)((SpinnerOption)mDeletePolicyView.getSelectedItem()).value; 572 deletePolicyChanged = mLoadedDeletePolicy != newDeletePolicy; 573 } else { 574 deletePolicyChanged = false; 575 } 576 577 return deletePolicyChanged || super.haveSettingsChanged(); 578 } 579 580 @Override 581 public void onValidateStateChanged() { 582 validateFields(); 583 } 584 585 @Override 586 public void onRequestSignIn() { 587 // Launch the credentials activity. 588 final String protocol = 589 mSetupData.getAccount().getOrCreateHostAuthRecv(mAppContext).mProtocol; 590 final Intent intent = AccountCredentials.getAccountCredentialsIntent(getActivity(), 591 mUsernameView.getText().toString(), protocol); 592 startActivityForResult(intent, SIGN_IN_REQUEST); 593 } 594 595 @Override 596 public void onCertificateRequested() { 597 // XXX reimplement 598 final Intent intent = new Intent(CertificateRequestor.ACTION_REQUEST_CERT); 599 intent.setData(Uri.parse("eas://com.android.emailcommon/certrequest")); 600 startActivityForResult(intent, CERTIFICATE_REQUEST); 601 } 602 603 @Override 604 public void onActivityResult(int requestCode, int resultCode, Intent data) { 605 if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) { 606 final String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS); 607 if (certAlias != null) { 608 mClientCertificateSelector.setCertificate(certAlias); 609 } 610 } else if (requestCode == SIGN_IN_REQUEST && resultCode == Activity.RESULT_OK) { 611 final Account account = mSetupData.getAccount(); 612 final HostAuth recvAuth = account.getOrCreateHostAuthRecv(getActivity()); 613 AccountSetupCredentialsFragment.populateHostAuthWithResults(mAppContext, recvAuth, 614 data.getExtras()); 615 mAuthenticationView.setAuthInfo(mServiceInfo.offerOAuth, recvAuth); 616 } 617 } 618} 619