Merge AccountSetupNames and AccountSetupOptions

Change-Id: I5946e90e56b1fc725522d41e2e33d8125900a871
This commit is contained in:
Tony Mantler 2014-01-16 09:59:39 -08:00
parent 018ae522d7
commit 7e4daecc9a
21 changed files with 993 additions and 1197 deletions

View File

@ -268,16 +268,12 @@
android:label="@string/account_setup_outgoing_title"
>
</activity>
<!-- TODO: fix this label -->
<activity
android:name=".activity.setup.AccountSetupOptions"
android:name=".activity.setup.AccountSetupFinal"
android:label="@string/account_setup_options_title"
>
</activity>
<activity
android:name=".activity.setup.AccountSetupNames"
android:label="@string/account_setup_names_title"
>
</activity>
<!-- Must be exported in order for the AccountManager to launch it -->
<activity
android:name=".activity.setup.AccountSettings"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,39 +14,30 @@
limitations under the License.
-->
<!-- Account Names - XL - portrait - see layout/ for small-screen version -->
<!-- Account Setup Layout - XL - landscape - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right"
>
<RelativeLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right" >
<!-- Headline and hairline divider -->
<TextView
<!-- Headline and hairline divider -->
<!-- Set headline for first fragment, change in code as we progress through screens -->
<TextView
android:id="@+id/headline"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_names_headline"
android:text="@string/account_setup_options_headline"
android:textAppearance="@style/accountSetupHeadline" />
<View
<View
android:id="@+id/top_divider"
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
@ -54,34 +45,26 @@
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Frame on the top containing the (common) setup info -->
<FrameLayout
android:id="@+id/common"
<!-- Buttons on the right -->
<FrameLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/top_divider"
android:layout_alignParentRight="true"
android:id="@+id/buttons">
<include layout="@layout/account_setup_buttons" />
</FrameLayout>
<!-- Primary fragment on the left -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_toLeftOf="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dip"
android:paddingRight="64dip"
>
<include
layout="@layout/account_setup_names_common"
/>
</FrameLayout>
</RelativeLayout>
<!-- Button below that -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/setup_buttons_padding_bottom"
>
<Button
android:id="@+id/next"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
</RelativeLayout>
</LinearLayout>
<include layout="@layout/account_setup_fragment_container" />
</FrameLayout>
</RelativeLayout>
</ScrollView>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/previous"
android:layout_marginTop="@dimen/setup_buttons_padding_top"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/previous_action" />
<Button
android:id="@+id/next"
android:layout_below="@+id/previous"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
</RelativeLayout>

View File

@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Account Names - XL - landscape - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right"
>
<!-- Headline and hairline divider -->
<TextView
android:id="@+id/headline"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_names_headline"
android:textAppearance="@style/accountSetupHeadline" />
<View
android:id="@+id/top_divider"
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Button on the right -->
<Button
android:id="@+id/next"
android:layout_below="@+id/top_divider"
android:layout_alignParentRight="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
<!-- Frame on the left containing the (common) setup info -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/next"
android:layout_marginRight="64dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<include
layout="@layout/account_setup_names_common"
/>
</FrameLayout>
</RelativeLayout>
</ScrollView>

View File

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Account Options - XL - landscape - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right"
>
<!-- Headline and hairline divider -->
<TextView
android:id="@+id/headline"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_options_headline"
android:textAppearance="@style/accountSetupHeadline" />
<View
android:id="@+id/top_divider"
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Buttons on the right -->
<Button
android:id="@+id/previous"
android:layout_below="@+id/top_divider"
android:layout_alignParentRight="true"
android:layout_marginTop="@dimen/setup_buttons_padding_top"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/previous_action" />
<Button
android:id="@+id/next"
android:layout_below="@+id/previous"
android:layout_alignParentRight="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
<!-- Frame on the left containing the (common) setup info -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/next"
android:layout_marginRight="64dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<fragment
class="com.android.email.activity.setup.AccountSetupOptionsFragment"
android:id="@+id/options_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
</RelativeLayout>
</ScrollView>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Account Names - XL - portrait - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right"
>
<!-- Headline and hairline divider -->
<!-- Set headline for first fragment, change in code as we progress through screens -->
<TextView
android:id="@+id/headline"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_options_headline"
android:textAppearance="@style/accountSetupHeadline" />
<View
android:id="@+id/top_divider"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Primary fragment -->
<include layout="@layout/account_setup_fragment_container" />
<!-- Buttons below that -->
<include layout="@layout/account_setup_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Account Options - XL - portrait - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<!-- Headline and hairline divider -->
<TextView
android:id="@+id/headline"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_options_headline"
android:textAppearance="@style/accountSetupHeadline" />
<View
android:id="@+id/top_divider"
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Frame on the top containing the (common) setup info -->
<FrameLayout
android:id="@+id/common"
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<fragment
class="com.android.email.activity.setup.AccountSetupOptionsFragment"
android:id="@+id/options_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
</RelativeLayout>
<!-- Buttons below -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/setup_buttons_padding_bottom"
>
<Button
android:id="@+id/previous"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="@dimen/setup_buttons_padding_left"
style="@style/accountSetupButton"
android:text="@string/previous_action" />
<Button
android:id="@+id/next"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,35 +14,29 @@
limitations under the License.
-->
<!-- Account Setup Layout - standard -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_fragment_padding_top"
android:paddingLeft="@dimen/setup_fragment_padding_left"
android:paddingRight="@dimen/setup_fragment_padding_right" >
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_fragment_padding_top"
android:paddingLeft="@dimen/setup_fragment_padding_left"
android:paddingRight="@dimen/setup_fragment_padding_right" >
<!-- Headline -->
<!-- Set headline for first fragment, change in code as we progress through screens -->
<TextView
android:id="@+id/headline"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/account_setup_names_headline"
android:text="@string/account_setup_options_headline"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary" />
<fragment
android:id="@+id/names_fragment"
class="com.android.email.activity.setup.AccountSetupNamesFragment"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>
<Button
android:id="@+id/next"
android:layout_marginTop="16dip"
android:layout_gravity="right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
<include layout="@layout/account_setup_fragment_container"/>
<include layout="@layout/account_setup_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -14,23 +14,22 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/settings_buttons_padding_top"
android:paddingBottom="@dimen/settings_buttons_padding_bottom"
>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/setup_buttons_padding_bottom">
<Button
android:id="@+id/previous"
style="@style/accountSetupButton"
android:layout_width="0dip"
android:layout_weight="1"
android:text="@string/previous_action" />
android:id="@+id/previous"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="@dimen/setup_buttons_padding_left"
style="@style/accountSetupButton"
android:text="@string/previous_action" />
<Button
android:id="@+id/next"
style="@style/accountSetupButton"
android:layout_width="0dip"
android:layout_weight="1"
android:text="@string/next_action" />
</LinearLayout>
android:id="@+id/next"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginRight="@dimen/setup_buttons_padding_right"
style="@style/accountSetupButton"
android:text="@string/next_action" />
</RelativeLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,21 +14,13 @@
limitations under the License.
-->
<!-- Common data-entry area of account name setup screen - account nickname, user name. -->
<!-- tablet version -->
<LinearLayout
<!-- Fragment view -->
<FrameLayout
android:id="@+id/setup_fragment_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="@dimen/setup_item_inset_left"
android:paddingRight="@dimen/setup_item_inset_right" >
<fragment
android:id="@+id/names_fragment"
class="com.android.email.activity.setup.AccountSetupNamesFragment"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>
</LinearLayout>
<!-- Don't include the fragment itself here, or we won't be able to swap it out later -->
</FrameLayout>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_fragment_padding_top"
android:paddingLeft="@dimen/setup_fragment_padding_left"
android:paddingRight="@dimen/setup_fragment_padding_right" >
<fragment
class="com.android.email.activity.setup.AccountSetupOptionsFragment"
android:id="@+id/options_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include layout="@layout/account_setup_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -32,6 +32,7 @@ import com.android.emailcommon.provider.Account;
*
* Common code used by the activities and the fragments.
*/
@Deprecated
public final class ActivityHelper {
private ActivityHelper() {
}

View File

@ -0,0 +1,335 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.activity.setup;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import com.android.email.service.EmailServiceUtils;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.mail.preferences.AccountPreferences;
import com.android.mail.ui.MailAsyncTaskLoader;
import com.android.mail.utils.LogUtils;
import java.io.IOException;
/**
* This retained headless fragment acts as a container for the multi-step task of creating the
* AccountManager account and saving our account object to the database, as well as some misc
* related background tasks.
*/
public class AccountCreationFragment extends Fragment {
public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
private static final String ACCOUNT_TAG = "account";
private static final String SYNC_EMAIL_TAG = "email";
private static final String SYNC_CALENDAR_TAG = "calendar";
private static final String SYNC_CONTACTS_TAG = "contacts";
private static final String NOTIFICATIONS_TAG = "notifications";
private static final String SAVESTATE_STAGE = "AccountCreationFragment.stage";
private static final int STAGE_BEFORE_ACCOUNT_SECURITY = 0;
private static final int STAGE_REFRESHING_ACCOUNT = 1;
private static final int STAGE_WAITING_FOR_ACCOUNT_SECURITY = 2;
private static final int STAGE_AFTER_ACCOUNT_SECURITY = 3;
private int mStage = 0;
private Context mAppContext;
private final Handler mHandler;
AccountCreationFragment() {
mHandler = new Handler();
}
public static AccountCreationFragment newInstance(Account account, boolean syncEmail,
boolean syncCalendar, boolean syncContacts, boolean enableNotifications) {
final Bundle args = new Bundle(5);
args.putParcelable(AccountCreationFragment.ACCOUNT_TAG, account);
args.putBoolean(AccountCreationFragment.SYNC_EMAIL_TAG, syncEmail);
args.putBoolean(AccountCreationFragment.SYNC_CALENDAR_TAG, syncCalendar);
args.putBoolean(AccountCreationFragment.SYNC_CONTACTS_TAG, syncContacts);
args.putBoolean(AccountCreationFragment.NOTIFICATIONS_TAG, enableNotifications);
final AccountCreationFragment f = new AccountCreationFragment();
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mAppContext = getActivity().getApplicationContext();
if (savedInstanceState != null) {
mStage = savedInstanceState.getInt(SAVESTATE_STAGE);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVESTATE_STAGE, mStage);
}
@Override
public void onResume() {
super.onResume();
switch (mStage) {
case STAGE_BEFORE_ACCOUNT_SECURITY:
kickBeforeAccountSecurityLoader();
break;
case STAGE_REFRESHING_ACCOUNT:
kickRefreshingAccountLoader();
break;
case STAGE_WAITING_FOR_ACCOUNT_SECURITY:
// TODO: figure out when we might get here and what to do if we do
break;
case STAGE_AFTER_ACCOUNT_SECURITY:
kickAfterAccountSecurityLoader();
break;
}
}
private void kickBeforeAccountSecurityLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
loaderManager.initLoader(STAGE_BEFORE_ACCOUNT_SECURITY, getArguments(),
new BeforeAccountSecurityCallbacks());
}
private void kickRefreshingAccountLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
loaderManager.initLoader(STAGE_REFRESHING_ACCOUNT, getArguments(),
new RefreshAccountCallbacks());
}
private void kickAfterAccountSecurityLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
loaderManager.initLoader(STAGE_AFTER_ACCOUNT_SECURITY, getArguments(),
new AfterAccountSecurityCallbacks());
}
private class BeforeAccountSecurityCallbacks
implements LoaderManager.LoaderCallbacks<Boolean> {
public BeforeAccountSecurityCallbacks() {}
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
final boolean email = args.getBoolean(SYNC_EMAIL_TAG);
final boolean calendar = args.getBoolean(SYNC_CALENDAR_TAG);
final boolean contacts = args.getBoolean(SYNC_CONTACTS_TAG);
final boolean notificationsEnabled = args.getBoolean(NOTIFICATIONS_TAG);
/**
* Task loader returns true if we created the account, false if we bailed out.
*/
return new MailAsyncTaskLoader<Boolean>(mAppContext) {
@Override
protected void onDiscardResult(Boolean result) {}
@Override
public Boolean loadInBackground() {
// Set the incomplete flag here to avoid reconciliation issues
account.mFlags |= Account.FLAGS_INCOMPLETE;
AccountSettingsUtils.commitSettings(mAppContext, account);
final AccountManagerFuture<Bundle> future =
EmailServiceUtils.setupAccountManagerAccount(mAppContext, account,
email, calendar, contacts, null);
boolean createSuccess = false;
try {
future.getResult();
createSuccess = true;
} catch (OperationCanceledException e) {
LogUtils.d(LogUtils.TAG, "addAccount was canceled");
} catch (IOException e) {
LogUtils.d(LogUtils.TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
LogUtils.d(LogUtils.TAG, "addAccount failed: " + e);
}
if (!createSuccess) {
return false;
}
// We can move the notification setting to the inbox FolderPreferences
// later, once we know what the inbox is
new AccountPreferences(mAppContext, account.getEmailAddress())
.setDefaultInboxNotificationsEnabled(notificationsEnabled);
// Now that AccountManager account creation is complete, clear the
// INCOMPLETE flag
account.mFlags &= ~Account.FLAGS_INCOMPLETE;
AccountSettingsUtils.commitSettings(mAppContext, account);
return true;
}
};
}
@Override
public void onLoadFinished(Loader<Boolean> loader, Boolean success) {
if (success == null || !isResumed()) {
return;
}
if (success) {
mStage = STAGE_REFRESHING_ACCOUNT;
kickRefreshingAccountLoader();
} else {
final AccountSetupFinal activity = (AccountSetupFinal)getActivity();
mHandler.post(new Runnable() {
@Override
public void run() {
if (!isResumed()) {
return;
}
// Can't do this from within onLoadFinished
activity.destroyAccountCreationFragment();
activity.showCreateAccountErrorDialog();
}
});
}
}
@Override
public void onLoaderReset(Loader<Boolean> loader) {}
}
private class RefreshAccountCallbacks implements LoaderManager.LoaderCallbacks<Account> {
@Override
public Loader<Account> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
return new MailAsyncTaskLoader<Account>(mAppContext) {
@Override
protected void onDiscardResult(Account result) {}
@Override
public Account loadInBackground() {
account.refresh(mAppContext);
return account;
}
};
}
@Override
public void onLoadFinished(Loader<Account> loader, Account account) {
if (account == null || !isResumed()) {
return;
}
getArguments().putParcelable(ACCOUNT_TAG, account);
if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
final Intent intent = AccountSecurity
.actionUpdateSecurityIntent(getActivity(), account.mId, false);
startActivityForResult(intent, REQUEST_CODE_ACCEPT_POLICIES);
mStage = STAGE_WAITING_FOR_ACCOUNT_SECURITY;
} else {
mStage = STAGE_AFTER_ACCOUNT_SECURITY;
kickAfterAccountSecurityLoader();
}
}
@Override
public void onLoaderReset(Loader<Account> loader) {}
}
private class AfterAccountSecurityCallbacks
implements LoaderManager.LoaderCallbacks<Account> {
@Override
public Loader<Account> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
return new MailAsyncTaskLoader<Account>(mAppContext) {
@Override
protected void onDiscardResult(Account result) {}
@Override
public Account loadInBackground() {
// Clear the security hold flag now
account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
AccountSettingsUtils.commitSettings(mAppContext, account);
// Start up services based on new account(s)
MailActivityEmail.setServicesEnabledSync(mAppContext);
EmailServiceUtils
.startService(mAppContext, account.mHostAuthRecv.mProtocol);
return account;
}
};
}
@Override
public void onLoadFinished(final Loader<Account> loader, final Account account) {
// Need to do this from a runnable because this triggers fragment transactions
mHandler.post(new Runnable() {
@Override
public void run() {
if (account == null || !isResumed()) {
return;
}
// Move to final setup screen
AccountSetupFinal activity = (AccountSetupFinal) getActivity();
activity.getSetupData().setAccount(account);
activity.proceedFromAccountCreationFragment();
// Update the folder list (to get our starting folders, e.g. Inbox)
final EmailServiceProxy proxy = EmailServiceUtils.getServiceForAccount(activity,
account.mId);
try {
proxy.updateFolderList(account.mId);
} catch (RemoteException e) {
// It's all good
}
}
});
}
@Override
public void onLoaderReset(Loader<Account> loader) {}
}
/**
* This is called after the AccountSecurity activity completes.
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mStage = STAGE_AFTER_ACCOUNT_SECURITY;
// onResume() will be called immediately after this to kick the next loader
}
}

View File

@ -42,7 +42,6 @@ import android.widget.Button;
import android.widget.Toast;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@ -208,7 +207,6 @@ public class AccountSetupBasics extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityHelper.debugSetWindowFlags(this);
// Check for forced account creation first, as it comes from an externally-generated
// intent and won't have any SetupData prepared.
@ -718,7 +716,7 @@ public class AccountSetupBasics extends AccountSetupActivity
public void onCheckSettingsComplete(int result, SetupDataFragment setupData) {
mSetupData = setupData;
if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
AccountSetupOptions.actionOptions(this, mSetupData);
AccountSetupFinal.actionFinal(this, mSetupData);
mReportAccountAuthenticatorError = false;
finish();
}

View File

@ -0,0 +1,487 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.activity.setup;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.provider.AccountBackupRestore;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.mail.ui.MailAsyncTaskLoader;
import com.android.mail.utils.LogUtils;
public class AccountSetupFinal extends AccountSetupActivity implements View.OnClickListener {
private static final String SAVESTATE_IS_PROCESSING_KEY =
"com.android.email.AccountSetupFinal.is_processing";
private static final String SAVESTATE_STATE = "com.android.email.AccountSetupFinal.state";
private static final String ACCOUNT_CREATION_FRAGMENT_TAG = "AccountCreationFragment";
private static final String ACCOUNT_FINALIZE_FRAGMENT_TAG = "AccountFinalizeFragment";
private static final String CREATE_ACCOUNT_DIALOG_TAG = "CreateAccountDialog";
private static final String CONTENT_FRAGMENT_TAG = "AccountSetupContentFragment";
private static final int STATE_OPTIONS = 0;
private static final int STATE_NAMES = 1;
private int mState = STATE_OPTIONS;
private boolean mIsProcessing = false;
private Button mNextButton;
public static void actionFinal(Activity fromActivity, SetupDataFragment setupData) {
final Intent intent = new ForwardingIntent(fromActivity, AccountSetupFinal.class);
intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
fromActivity.startActivity(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.account_setup);
if (savedInstanceState != null) {
mIsProcessing = savedInstanceState.getBoolean(SAVESTATE_IS_PROCESSING_KEY, false);
mState = savedInstanceState.getInt(SAVESTATE_STATE, STATE_OPTIONS);
} else {
// If we're not restoring from a previous state, we want to configure the initial screen
mState = STATE_OPTIONS;
updateHeadline();
updateContentFragment();
}
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
mNextButton = UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
if (!mIsProcessing
&& mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
// If we are just visiting here to fill in details, exit immediately
getFragmentManager().executePendingTransactions();
initiateAccountCreation();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVESTATE_IS_PROCESSING_KEY, mIsProcessing);
}
/**
* Set the headline text according to mState.
*/
private void updateHeadline() {
TextView headlineView = UiUtilities.getView(this, R.id.headline);
switch (mState) {
case STATE_OPTIONS:
headlineView.setText(R.string.account_setup_options_headline);
break;
case STATE_NAMES:
headlineView.setText(R.string.account_setup_names_headline);
break;
}
}
/**
* Swap in the new fragment according to mState. This pushes the current fragment onto the back
* stack, so only call it once per transition.
*/
private void updateContentFragment() {
final Fragment f;
switch (mState) {
case STATE_OPTIONS:
f = new AccountSetupOptionsFragment();
break;
case STATE_NAMES:
f = new AccountSetupNamesFragment();
break;
default:
throw new IllegalStateException("Unknown state " + mState);
}
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.setup_fragment_container, f, CONTENT_FRAGMENT_TAG);
ft.addToBackStack(null);
ft.commit();
}
/**
* Retrieve the current content fragment
* @return The content fragment or null if it wasn't found for some reason
*/
private Fragment getContentFragment() {
return getFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
}
/**
* Main choreography function to handle moving forward through scenes. Moving back should be
* generally handled for us by the back stack
*/
protected void proceed() {
mIsProcessing = false;
setNextButtonEnabled(true);
switch (mState) {
case STATE_OPTIONS:
mState = STATE_NAMES;
updateHeadline();
updateContentFragment();
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
getFragmentManager().executePendingTransactions();
initiateAccountFinalize();
}
break;
case STATE_NAMES:
finishActivity();
break;
}
}
/**
* Block the back key if we are currently processing the "next" key"
*/
@Override
public void onBackPressed() {
if (mIsProcessing) {
return;
}
if (mState == STATE_NAMES) {
finishActivity();
} else {
super.onBackPressed();
}
}
private void finishActivity() {
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_NO_ACCOUNTS) {
AccountSetupBasics.actionAccountCreateFinishedWithResult(this);
} else if (mSetupData.getFlowMode() != SetupDataFragment.FLOW_MODE_NORMAL) {
AccountSetupBasics.actionAccountCreateFinishedAccountFlow(this);
} else {
final Account account = mSetupData.getAccount();
if (account != null) {
AccountSetupBasics.actionAccountCreateFinished(this, account);
}
}
finish();
}
/**
* Respond to clicks in the "Next" or "Previous" buttons
*/
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.next:
// Debounce touches
if (!mIsProcessing) {
switch (mState) {
case STATE_OPTIONS:
initiateAccountCreation();
break;
case STATE_NAMES:
initiateAccountFinalize();
break;
}
setNextButtonEnabled(false);
}
break;
case R.id.previous:
onBackPressed();
break;
}
}
public void setNextButtonEnabled(final boolean enabled) {
mNextButton.setEnabled(enabled);
}
/**
* Ths is called when the user clicks the "done" button.
* It collects the data from the UI, updates the setup account record, and launches a fragment
* which handles creating the account in the system and database.
*/
private void initiateAccountCreation() {
mIsProcessing = true;
final Account account = mSetupData.getAccount();
if (account.mHostAuthRecv == null) {
throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
}
final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
getContentFragment();
if (fragment == null) {
throw new IllegalStateException("Fragment missing!");
}
account.setDisplayName(account.getEmailAddress());
int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
final EmailServiceUtils.EmailServiceInfo serviceInfo =
EmailServiceUtils.getServiceInfo(getApplicationContext(),
account.mHostAuthRecv.mProtocol);
if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
}
account.setFlags(newFlags);
account.setSyncInterval(fragment.getCheckFrequencyValue());
final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
if (syncWindowValue != null) {
account.setSyncLookback(syncWindowValue);
}
// Finish setting up the account, and commit it to the database
if (mSetupData.getPolicy() != null) {
account.mFlags |= Account.FLAGS_SECURITY_HOLD;
account.mPolicy = mSetupData.getPolicy();
}
// Finally, write the completed account (for the first time) and then
// install it into the Account manager as well. These are done off-thread.
// The account manager will report back via the callback, which will take us to
// the next operations.
final boolean syncEmail = fragment.getSyncEmailValue();
final boolean syncCalendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
final boolean syncContacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
final boolean enableNotifications = fragment.getNotifyValue();
final Fragment f = AccountCreationFragment.newInstance(account, syncEmail, syncCalendar,
syncContacts, enableNotifications);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(f, ACCOUNT_CREATION_FRAGMENT_TAG);
ft.commit();
showCreateAccountDialog();
}
/**
* Called by the account creation fragment after it has completed.
* We do a small amount of work here before moving on to the next state.
*/
public void proceedFromAccountCreationFragment() {
destroyAccountCreationFragment();
// If the account manager initiated the creation, and success was not reported,
// then we assume that we're giving up (for any reason) - report failure.
final AccountAuthenticatorResponse authenticatorResponse =
mSetupData.getAccountAuthenticatorResponse();
if (authenticatorResponse != null) {
authenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
mSetupData.setAccountAuthenticatorResponse(null);
}
proceed();
}
public void destroyAccountCreationFragment() {
dismissCreateAccountDialog();
final Fragment f = getFragmentManager().findFragmentByTag(ACCOUNT_CREATION_FRAGMENT_TAG);
if (f == null) {
LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountCreationFragment to destroy");
}
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(f);
ft.commit();
}
public static class CreateAccountDialogFragment extends DialogFragment {
CreateAccountDialogFragment() {}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
/// Show "Creating account..." dialog
final ProgressDialog d = new ProgressDialog(getActivity());
d.setIndeterminate(true);
d.setMessage(getString(R.string.account_setup_creating_account_msg));
return d;
}
}
protected void showCreateAccountDialog() {
new CreateAccountDialogFragment().show(getFragmentManager(), CREATE_ACCOUNT_DIALOG_TAG);
}
protected void dismissCreateAccountDialog() {
final DialogFragment f = (DialogFragment)
getFragmentManager().findFragmentByTag(CREATE_ACCOUNT_DIALOG_TAG);
if (f != null) {
f.dismiss();
}
}
public static class CreateAccountErrorDialogFragment extends DialogFragment
implements DialogInterface.OnClickListener {
public CreateAccountErrorDialogFragment() {}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String message = getString(R.string.account_setup_failed_dlg_auth_message,
R.string.system_account_create_failed);
return new AlertDialog.Builder(getActivity())
.setIconAttribute(android.R.attr.alertDialogIcon)
.setTitle(getString(R.string.account_setup_failed_dlg_title))
.setMessage(message)
.setCancelable(true)
.setPositiveButton(
getString(R.string.account_setup_failed_dlg_edit_details_action), this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
getActivity().finish();
}
}
/**
* This is called if MailService.setupAccountManagerAccount() fails for some reason
*/
protected void showCreateAccountErrorDialog() {
new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
}
private void initiateAccountFinalize() {
mIsProcessing = true;
AccountSetupNamesFragment fragment = (AccountSetupNamesFragment) getContentFragment();
// Update account object from UI
final Account account = mSetupData.getAccount();
final String description = fragment.getDescription();
if (!TextUtils.isEmpty(description)) {
account.setDisplayName(description);
}
account.setSenderName(fragment.getSenderName());
final Fragment f = AccountFinalizeFragment.newInstance(account);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(f, ACCOUNT_FINALIZE_FRAGMENT_TAG);
ft.commit();
}
private static class AccountFinalizeFragment extends Fragment {
private static final String ACCOUNT_TAG = "account";
private static final int FINAL_ACCOUNT_TASK_LOADER_ID = 0;
private Context mAppContext;
public static AccountFinalizeFragment newInstance(Account account) {
final AccountFinalizeFragment f = new AccountFinalizeFragment();
final Bundle args = new Bundle(1);
args.putParcelable(ACCOUNT_TAG, account);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppContext = getActivity().getApplicationContext();
setRetainInstance(true);
}
@Override
public void onResume() {
super.onResume();
getLoaderManager().initLoader(FINAL_ACCOUNT_TASK_LOADER_ID, getArguments(),
new LoaderManager.LoaderCallbacks<Boolean>() {
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
final Account accountArg = args.getParcelable(ACCOUNT_TAG);
return new FinalSetupTaskLoader(mAppContext, accountArg);
}
@Override
public void onLoadFinished(Loader<Boolean> loader, Boolean success) {
if (success && isResumed()) {
AccountSetupFinal activity = (AccountSetupFinal) getActivity();
activity.finishActivity();
}
}
@Override
public void onLoaderReset(Loader<Boolean> loader) {
}
});
}
/**
* Final account setup work is handled in this Loader:
* Commit final values to provider
* Trigger account backup
*/
private static class FinalSetupTaskLoader extends MailAsyncTaskLoader<Boolean> {
private final Account mAccount;
public FinalSetupTaskLoader(Context context, Account account) {
super(context);
mAccount = account;
}
Account getAccount() {
return mAccount;
}
@Override
public Boolean loadInBackground() {
// Update the account in the database
final ContentValues cv = new ContentValues();
cv.put(EmailContent.AccountColumns.DISPLAY_NAME, mAccount.getDisplayName());
cv.put(EmailContent.AccountColumns.SENDER_NAME, mAccount.getSenderName());
mAccount.update(getContext(), cv);
// Update the backup (side copy) of the accounts
AccountBackupRestore.backup(getContext());
return true;
}
@Override
protected void onDiscardResult(Boolean result) {}
}
}
}

View File

@ -25,7 +25,6 @@ import android.view.View.OnClickListener;
import android.widget.Button;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@ -63,7 +62,6 @@ public class AccountSetupIncoming extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityHelper.debugSetWindowFlags(this);
final HostAuth hostAuth = mSetupData.getAccount().mHostAuthRecv;
mServiceInfo = EmailServiceUtils.getServiceInfo(this, hostAuth.mProtocol);
@ -196,7 +194,7 @@ public class AccountSetupIncoming extends AccountSetupActivity
if (mServiceInfo.usesSmtp) {
AccountSetupOutgoing.actionOutgoingSettings(this, mSetupData);
} else {
AccountSetupOptions.actionOptions(this, mSetupData);
AccountSetupFinal.actionFinal(this, mSetupData);
finish();
}
}

View File

@ -1,236 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.activity.setup;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.provider.AccountBackupRestore;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.mail.ui.MailAsyncTaskLoader;
/**
* Final screen of setup process. Collect account nickname and/or username.
*/
public class AccountSetupNames extends AccountSetupActivity {
private static final int REQUEST_SECURITY = 0;
private Button mNextButton;
private static final String SAVESTATE_ISCOMPLETING_TAG = "isCompleting";
private boolean mIsCompleting = false;
private static final int FINAL_ACCOUNT_TASK_LOADER_ID = 0;
private static final String ACCOUNT_TAG = "account";
private Bundle mFinalAccountTaskLoaderArgs;
private LoaderManager.LoaderCallbacks mFinalAccountTaskLoaderCallbacks;
public static void actionSetNames(Activity fromActivity, SetupDataFragment setupData) {
ForwardingIntent intent = new ForwardingIntent(fromActivity, AccountSetupNames.class);
intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
fromActivity.startActivity(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mIsCompleting = savedInstanceState.getBoolean(SAVESTATE_ISCOMPLETING_TAG);
}
ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_names);
mNextButton = UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onNext();
}
});
// Proceed immediately if in account creation mode
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
onNext();
}
if (mIsCompleting) {
startFinalSetupTaskLoader(getSetupData().getAccount());
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVESTATE_ISCOMPLETING_TAG, mIsCompleting);
}
/**
* Block the back key if we are currently processing the "next" key"
*/
@Override
public void onBackPressed() {
if (!mIsCompleting) {
finishActivity();
}
}
private void finishActivity() {
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_NO_ACCOUNTS) {
AccountSetupBasics.actionAccountCreateFinishedWithResult(this);
} else if (mSetupData.getFlowMode() != SetupDataFragment.FLOW_MODE_NORMAL) {
AccountSetupBasics.actionAccountCreateFinishedAccountFlow(this);
} else {
final Account account = mSetupData.getAccount();
if (account != null) {
AccountSetupBasics.actionAccountCreateFinished(this, account);
}
}
finish();
}
public void setNextButtonEnabled(boolean enabled) {
mNextButton.setEnabled(enabled);
}
/**
* After clicking the next button, we'll start an async task to commit the data
* and other steps to finish the creation of the account.
*/
private void onNext() {
mNextButton.setEnabled(false); // Protect against double-tap.
mIsCompleting = true;
AccountSetupNamesFragment fragment = (AccountSetupNamesFragment)
getFragmentManager().findFragmentById(R.id.names_fragment);
// Update account object from UI
final Account account = mSetupData.getAccount();
final String description = fragment.getDescription();
if (!TextUtils.isEmpty(description)) {
account.setDisplayName(description);
}
account.setSenderName(fragment.getSenderName());
startFinalSetupTaskLoader(account);
}
private void startFinalSetupTaskLoader(Account account) {
if (mFinalAccountTaskLoaderArgs == null) {
mFinalAccountTaskLoaderArgs = new Bundle(1);
mFinalAccountTaskLoaderArgs.putParcelable(ACCOUNT_TAG, account);
final Context appContext = getApplicationContext();
mFinalAccountTaskLoaderCallbacks = new LoaderManager.LoaderCallbacks<Boolean>() {
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
final Account accountArg = args.getParcelable(ACCOUNT_TAG);
return new FinalSetupTaskLoader(appContext, accountArg);
}
@Override
public void onLoadFinished(Loader<Boolean> loader, Boolean isSecurityHold) {
if (isSecurityHold) {
final FinalSetupTaskLoader finalSetupTaskLoader =
(FinalSetupTaskLoader)loader;
final Intent i = AccountSecurity.actionUpdateSecurityIntent(
appContext, finalSetupTaskLoader.getAccount().mId, false);
startActivityForResult(i, REQUEST_SECURITY);
} else {
finishActivity();
}
}
@Override
public void onLoaderReset(Loader<Boolean> loader) {}
};
}
getLoaderManager().initLoader(FINAL_ACCOUNT_TASK_LOADER_ID, mFinalAccountTaskLoaderArgs,
mFinalAccountTaskLoaderCallbacks);
}
/**
* Final account setup work is handled in this AsyncTask:
* Commit final values to provider
* Trigger account backup
* Check for security hold
*
* When this completes, we return to UI thread for the following steps:
* If security hold, dispatch to AccountSecurity activity
* Otherwise, return to AccountSetupBasics for conclusion.
*
* TODO: If there was *any* indication that security might be required, we could at least
* force the DeviceAdmin activation step, without waiting for the initial sync/handshake
* to fail.
* TODO: If the user doesn't update the security, don't go to the MessageList.
*/
private static class FinalSetupTaskLoader extends MailAsyncTaskLoader<Boolean> {
private final Account mAccount;
public FinalSetupTaskLoader(Context context, Account account) {
super(context);
mAccount = account;
}
Account getAccount() {
return mAccount;
}
@Override
public Boolean loadInBackground() {
// Update the account in the database
final ContentValues cv = new ContentValues();
cv.put(AccountColumns.DISPLAY_NAME, mAccount.getDisplayName());
cv.put(AccountColumns.SENDER_NAME, mAccount.getSenderName());
mAccount.update(getContext(), cv);
// Update the backup (side copy) of the accounts
AccountBackupRestore.backup(getContext());
return Account.isSecurityHold(getContext(), mAccount.mId);
}
@Override
protected void onDiscardResult(Boolean result) {}
}
/**
* Handle the eventual result from the security update activity
*
* TODO: If the user doesn't update the security, don't go to the MessageList.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_SECURITY:
finishActivity();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

View File

@ -158,7 +158,7 @@ public class AccountSetupNamesFragment extends Fragment {
mName.setError(null);
}
}
final AccountSetupNames activity = (AccountSetupNames) getActivity();
final AccountSetupFinal activity = (AccountSetupFinal) getActivity();
activity.setNextButtonEnabled(enableNextButton);
}

View File

@ -1,541 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.activity.setup;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.mail.preferences.AccountPreferences;
import com.android.mail.ui.MailAsyncTaskLoader;
import com.android.mail.utils.LogUtils;
import java.io.IOException;
public class AccountSetupOptions extends AccountSetupActivity implements OnClickListener {
private static final String EXTRA_IS_PROCESSING_KEY = "com.android.email.is_processing";
private static final String ACCOUNT_FINALIZE_FRAGMENT_TAG = "AccountFinalizeFragment";
private boolean mDonePressed = false;
private boolean mIsProcessing = false;
public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
public static void actionOptions(Activity fromActivity, SetupDataFragment setupData) {
final Intent intent = new ForwardingIntent(fromActivity, AccountSetupOptions.class);
intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
fromActivity.startActivity(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_options);
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
UiUtilities.getView(this, R.id.next).setOnClickListener(this);
mIsProcessing = savedInstanceState != null &&
savedInstanceState.getBoolean(EXTRA_IS_PROCESSING_KEY, false);
if (mIsProcessing) {
// We are already processing, so just show the dialog until we finish
showCreateAccountDialog();
} else if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
// If we are just visiting here to fill in details, exit immediately
onDone();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(EXTRA_IS_PROCESSING_KEY, mIsProcessing);
}
@Override
public void finish() {
// If the account manager initiated the creation, and success was not reported,
// then we assume that we're giving up (for any reason) - report failure.
final AccountAuthenticatorResponse authenticatorResponse =
mSetupData.getAccountAuthenticatorResponse();
if (authenticatorResponse != null) {
authenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
mSetupData.setAccountAuthenticatorResponse(null);
}
super.finish();
}
/**
* Respond to clicks in the "Next" or "Previous" buttons
*/
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.next:
// Don't allow this more than once (Exchange accounts call an async method
// before finish()'ing the Activity, which allows this code to potentially be
// executed multiple times
if (!mDonePressed) {
onDone();
mDonePressed = true;
}
break;
case R.id.previous:
onBackPressed();
break;
}
}
/**
* Ths is called when the user clicks the "done" button.
* It collects the data from the UI, updates the setup account record, and commits
* the account to the database (making it real for the first time.)
* Finally, we call setupAccountManagerAccount(), which will eventually complete via callback.
*/
private void onDone() {
final Account account = mSetupData.getAccount();
if (account.isSaved()) {
// Disrupting the normal flow could get us here, but if the account is already
// saved, we've done this work
return;
} else if (account.mHostAuthRecv == null) {
throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
}
final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
getFragmentManager().findFragmentById(R.id.options_fragment);
if (fragment == null) {
throw new IllegalStateException("Fragment missing!");
}
mIsProcessing = true;
account.setDisplayName(account.getEmailAddress());
int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
final EmailServiceUtils.EmailServiceInfo serviceInfo =
EmailServiceUtils.getServiceInfo(getApplicationContext(),
account.mHostAuthRecv.mProtocol);
if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
}
account.setFlags(newFlags);
account.setSyncInterval(fragment.getCheckFrequencyValue());
final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
if (syncWindowValue != null) {
account.setSyncLookback(syncWindowValue);
}
// Finish setting up the account, and commit it to the database
// Set the incomplete flag here to avoid reconciliation issues in ExchangeService
account.mFlags |= Account.FLAGS_INCOMPLETE;
if (mSetupData.getPolicy() != null) {
account.mFlags |= Account.FLAGS_SECURITY_HOLD;
account.mPolicy = mSetupData.getPolicy();
}
// Finally, write the completed account (for the first time) and then
// install it into the Account manager as well. These are done off-thread.
// The account manager will report back via the callback, which will take us to
// the next operations.
final Bundle args = new Bundle(5);
args.putParcelable(AccountFinalizeFragment.ACCOUNT_TAG, account);
args.putBoolean(AccountFinalizeFragment.SYNC_EMAIL_TAG, fragment.getSyncEmailValue());
final boolean calendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
args.putBoolean(AccountFinalizeFragment.SYNC_CALENDAR_TAG, calendar);
final boolean contacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
args.putBoolean(AccountFinalizeFragment.SYNC_CONTACTS_TAG, contacts);
args.putBoolean(AccountFinalizeFragment.NOTIFICATIONS_TAG, fragment.getNotifyValue());
final Fragment f = new AccountFinalizeFragment();
f.setArguments(args);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(f, ACCOUNT_FINALIZE_FRAGMENT_TAG);
ft.commit();
showCreateAccountDialog();
}
public void destroyAccountFinalizeFragment() {
final Fragment f = getFragmentManager().findFragmentByTag(ACCOUNT_FINALIZE_FRAGMENT_TAG);
if (f == null) {
LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountFinalizeFragment to destroy");
}
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(f);
ft.commit();
}
/**
* This retained headless fragment acts as a container for the multi-step task of creating the
* AccountManager account and saving our account object to the database, as well as some misc
* related background tasks.
*
* TODO: move this to a separate file, probably
*/
public static class AccountFinalizeFragment extends Fragment {
public static final String ACCOUNT_TAG = "account";
public static final String SYNC_EMAIL_TAG = "email";
public static final String SYNC_CALENDAR_TAG = "calendar";
public static final String SYNC_CONTACTS_TAG = "contacts";
public static final String NOTIFICATIONS_TAG = "notifications";
private static final String SAVESTATE_STAGE = "AccountFinalizeFragment.stage";
private static final int STAGE_BEFORE_ACCOUNT_SECURITY = 0;
private static final int STAGE_REFRESHING_ACCOUNT = 1;
private static final int STAGE_WAITING_FOR_ACCOUNT_SECURITY = 2;
private static final int STAGE_AFTER_ACCOUNT_SECURITY = 3;
private int mStage = 0;
private Context mAppContext;
private final Handler mHandler;
AccountFinalizeFragment() {
mHandler = new Handler();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mAppContext = getActivity().getApplicationContext();
if (savedInstanceState != null) {
mStage = savedInstanceState.getInt(SAVESTATE_STAGE);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVESTATE_STAGE, mStage);
}
@Override
public void onResume() {
super.onResume();
switch (mStage) {
case STAGE_BEFORE_ACCOUNT_SECURITY:
kickBeforeAccountSecurityLoader();
break;
case STAGE_REFRESHING_ACCOUNT:
kickRefreshingAccountLoader();
break;
case STAGE_WAITING_FOR_ACCOUNT_SECURITY:
// TODO: figure out when we might get here and what to do if we do
break;
case STAGE_AFTER_ACCOUNT_SECURITY:
kickAfterAccountSecurityLoader();
break;
}
}
private void kickBeforeAccountSecurityLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
loaderManager.initLoader(STAGE_BEFORE_ACCOUNT_SECURITY, getArguments(),
new BeforeAccountSecurityCallbacks());
}
private void kickRefreshingAccountLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
loaderManager.initLoader(STAGE_REFRESHING_ACCOUNT, getArguments(),
new RefreshAccountCallbacks());
}
private void kickAfterAccountSecurityLoader() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
loaderManager.initLoader(STAGE_AFTER_ACCOUNT_SECURITY, getArguments(),
new AfterAccountSecurityCallbacks());
}
private class BeforeAccountSecurityCallbacks
implements LoaderManager.LoaderCallbacks<Boolean> {
public BeforeAccountSecurityCallbacks() {}
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
final boolean email = args.getBoolean(SYNC_EMAIL_TAG);
final boolean calendar = args.getBoolean(SYNC_CALENDAR_TAG);
final boolean contacts = args.getBoolean(SYNC_CONTACTS_TAG);
final boolean notificationsEnabled = args.getBoolean(NOTIFICATIONS_TAG);
/**
* Task loader returns true if we created the account, false if we bailed out.
*/
return new MailAsyncTaskLoader<Boolean>(mAppContext) {
@Override
protected void onDiscardResult(Boolean result) {}
@Override
public Boolean loadInBackground() {
AccountSettingsUtils.commitSettings(mAppContext, account);
final AccountManagerFuture<Bundle> future =
EmailServiceUtils.setupAccountManagerAccount(mAppContext, account,
email, calendar, contacts, null);
boolean createSuccess = false;
try {
future.getResult();
createSuccess = true;
} catch (OperationCanceledException e) {
LogUtils.d(Logging.LOG_TAG, "addAccount was canceled");
} catch (IOException e) {
LogUtils.d(Logging.LOG_TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
LogUtils.d(Logging.LOG_TAG, "addAccount failed: " + e);
}
if (!createSuccess) {
return false;
}
// We can move the notification setting to the inbox FolderPreferences
// later, once we know what the inbox is
new AccountPreferences(mAppContext, account.getEmailAddress())
.setDefaultInboxNotificationsEnabled(notificationsEnabled);
// Now that AccountManager account creation is complete, clear the
// INCOMPLETE flag
account.mFlags &= ~Account.FLAGS_INCOMPLETE;
AccountSettingsUtils.commitSettings(mAppContext, account);
return true;
}
};
}
@Override
public void onLoadFinished(Loader<Boolean> loader, Boolean success) {
if (success == null || !isResumed()) {
return;
}
if (success) {
mStage = STAGE_REFRESHING_ACCOUNT;
kickRefreshingAccountLoader();
} else {
final AccountSetupOptions activity = (AccountSetupOptions)getActivity();
mHandler.post(new Runnable() {
@Override
public void run() {
if (!isResumed()) {
return;
}
// Can't do this from within onLoadFinished
activity.destroyAccountFinalizeFragment();
activity.showCreateAccountErrorDialog();
}
});
}
}
@Override
public void onLoaderReset(Loader<Boolean> loader) {}
}
private class RefreshAccountCallbacks implements LoaderManager.LoaderCallbacks<Account> {
@Override
public Loader<Account> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
return new MailAsyncTaskLoader<Account>(mAppContext) {
@Override
protected void onDiscardResult(Account result) {}
@Override
public Account loadInBackground() {
account.refresh(mAppContext);
return account;
}
};
}
@Override
public void onLoadFinished(Loader<Account> loader, Account account) {
if (account == null || !isResumed()) {
return;
}
getArguments().putParcelable(ACCOUNT_TAG, account);
if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
final Intent intent = AccountSecurity
.actionUpdateSecurityIntent(getActivity(), account.mId, false);
startActivityForResult(intent,
AccountSetupOptions.REQUEST_CODE_ACCEPT_POLICIES);
mStage = STAGE_WAITING_FOR_ACCOUNT_SECURITY;
} else {
mStage = STAGE_AFTER_ACCOUNT_SECURITY;
kickAfterAccountSecurityLoader();
}
}
@Override
public void onLoaderReset(Loader<Account> loader) {}
}
private class AfterAccountSecurityCallbacks
implements LoaderManager.LoaderCallbacks<Account> {
@Override
public Loader<Account> onCreateLoader(int id, Bundle args) {
final Account account = args.getParcelable(ACCOUNT_TAG);
return new MailAsyncTaskLoader<Account>(mAppContext) {
@Override
protected void onDiscardResult(Account result) {}
@Override
public Account loadInBackground() {
// Clear the security hold flag now
account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
AccountSettingsUtils.commitSettings(mAppContext, account);
// Start up services based on new account(s)
MailActivityEmail.setServicesEnabledSync(mAppContext);
EmailServiceUtils
.startService(mAppContext, account.mHostAuthRecv.mProtocol);
return account;
}
};
}
@Override
public void onLoadFinished(Loader<Account> loader, Account account) {
if (account == null || !isResumed()) {
return;
}
// Move to final setup screen
AccountSetupOptions activity = (AccountSetupOptions) getActivity();
activity.getSetupData().setAccount(account);
activity.proceed();
// Update the folder list (to get our starting folders, e.g. Inbox)
final EmailServiceProxy proxy = EmailServiceUtils.getServiceForAccount(activity,
account.mId);
try {
proxy.updateFolderList(account.mId);
} catch (RemoteException e) {
// It's all good
}
}
@Override
public void onLoaderReset(Loader<Account> loader) {}
}
/**
* This is called after the AccountSecurity activity completes.
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mStage = STAGE_AFTER_ACCOUNT_SECURITY;
// onResume() will be called immediately after this to kick the next loader
}
}
public static class CreateAccountDialogFragment extends DialogFragment {
CreateAccountDialogFragment() {}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
/// Show "Creating account..." dialog
final ProgressDialog d = new ProgressDialog(getActivity());
d.setIndeterminate(true);
d.setMessage(getString(R.string.account_setup_creating_account_msg));
return d;
}
}
private void showCreateAccountDialog() {
new CreateAccountDialogFragment().show(getFragmentManager(), null);
}
public static class CreateAccountErrorDialogFragment extends DialogFragment
implements DialogInterface.OnClickListener {
public CreateAccountErrorDialogFragment() {}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String message = getString(R.string.account_setup_failed_dlg_auth_message,
R.string.system_account_create_failed);
return new AlertDialog.Builder(getActivity())
.setIconAttribute(android.R.attr.alertDialogIcon)
.setTitle(getString(R.string.account_setup_failed_dlg_title))
.setMessage(message)
.setCancelable(true)
.setPositiveButton(
getString(R.string.account_setup_failed_dlg_edit_details_action), this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
getActivity().finish();
}
}
/**
* This is called if MailService.setupAccountManagerAccount() fails for some reason
*/
private void showCreateAccountErrorDialog() {
new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
}
/**
* Background account creation has completed, so proceed to the next screen.
*/
private void proceed() {
AccountSetupNames.actionSetNames(this, mSetupData);
finish();
}
}

View File

@ -17,9 +17,7 @@
package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.Account;
import android.app.Activity;
import android.app.FragmentTransaction;
@ -51,7 +49,6 @@ public class AccountSetupOutgoing extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_outgoing);
mFragment = (AccountSetupOutgoingFragment)
@ -113,7 +110,7 @@ public class AccountSetupOutgoing extends AccountSetupActivity
public void onCheckSettingsComplete(int result, SetupDataFragment setupData) {
mSetupData = setupData;
if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
AccountSetupOptions.actionOptions(this, mSetupData);
AccountSetupFinal.actionFinal(this, mSetupData);
finish();
}
}

View File

@ -27,9 +27,6 @@ import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import com.android.email.R;
import com.android.email.activity.setup.AccountSetupOptions;
import com.android.email.activity.setup.SetupDataFragment;
import com.android.email.activity.setup.SpinnerOption;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
@ -38,19 +35,19 @@ import java.net.URISyntaxException;
/**
* Tests of basic UI logic in the AccountSetupOptions screen.
* You can run this entire test case with:
* runtest -c com.android.email.activity.setup.AccountSetupOptionsTests email
* runtest -c com.android.email.activity.setup.AccountSetupFinalTests email
*/
@Suppress
@MediumTest
public class AccountSetupOptionsTests
extends ActivityInstrumentationTestCase2<AccountSetupOptions> {
public class AccountSetupFinalTests
extends ActivityInstrumentationTestCase2<AccountSetupFinal> {
private AccountSetupOptions mActivity;
private AccountSetupFinal mActivity;
private Spinner mCheckFrequencyView;
private CheckBox mBackgroundAttachmentsView;
public AccountSetupOptionsTests() {
super(AccountSetupOptions.class);
public AccountSetupFinalTests() {
super(AccountSetupFinal.class);
}
/**
@ -157,7 +154,7 @@ public class AccountSetupOptionsTests
for (int i = 0; i < sa.getCount(); ++i) {
SpinnerOption so = (SpinnerOption) sa.getItem(i);
if (so != null && ((Integer)so.value).intValue() == value) {
if (so != null && ((Integer)so.value) == value) {
return true;
}
}