Remove exchange-specific layouts (merge into incoming)

* Configure everything via services.xml, removing lots of
  duplicated layouts and code
* Check that this works on phone and tablet
* More to do:  get rid of abstract class with only one
  subclass (AccountServerBaseFragment), remove as many
  references in Email2 to specific protocols (a lot has
  already been done)

Change-Id: I071e0aba029e2ccb9631d13b2b6d41ab74b1341b
This commit is contained in:
Marc Blank 2012-06-18 17:20:49 -07:00
parent d214f6d19f
commit 48e8026b34
21 changed files with 282 additions and 1095 deletions

View File

@ -269,19 +269,7 @@ public final class HostAuth extends EmailContent implements HostAuthColumns, Par
mPort = port;
if (mPort == PORT_UNKNOWN) {
boolean useSSL = ((mFlags & FLAG_SSL) != 0);
// infer port# from protocol + security
// SSL implies a different port - TLS runs in the "regular" port
// NOTE: Although the port should be setup in the various setup screens, this
// block cannot easily be moved because we get process URIs from other sources
// (e.g. for tests, provider templates and account restore) that may or may not
// have a port specified.
if (SCHEME_POP3.equals(mProtocol)) {
mPort = useSSL ? 995 : 110;
} else if (SCHEME_IMAP.equals(mProtocol)) {
mPort = useSSL ? 993 : 143;
} else if (SCHEME_EAS.equals(mProtocol)) {
mPort = useSSL ? 443 : 80;
} else if (SCHEME_SMTP.equals(mProtocol)) {
if (SCHEME_SMTP.equals(mProtocol)) {
mPort = useSSL ? 465 : 587;
}
}

View File

@ -1,84 +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.
-->
<!-- Exchange Setup - 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_exchange_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" />
<!-- Fragment on the left containing the setup info -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dip"
android:paddingRight="64dip"
>
<fragment
android:id="@+id/setup_fragment"
class="com.android.email.activity.setup.AccountSetupExchangeFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</FrameLayout>
</RelativeLayout>
</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.
-->
<!-- Exchange Setup - 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="wrap_content"
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_exchange_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" />
<!-- Fragment on the top containing the setup info -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dip"
android:paddingRight="96dip"
>
<fragment
android:id="@+id/setup_fragment"
class="com.android.email.activity.setup.AccountSetupExchangeFragment"
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

@ -38,13 +38,13 @@
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_height="1dp"
android:background="@color/account_setup_divider_color" />
<!-- Layout on the left containing the setup info -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_content"
android:id="@+id/accountTypes"
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_marginRight="64dip"
@ -60,30 +60,6 @@
android:layout_marginLeft="16dip"
android:text="@string/account_setup_account_type_instructions"
android:textAppearance="@style/accountSetupInfoText" />
<Button
android:id="@+id/pop"
android:layout_below="@+id/instructions"
android:layout_alignParentLeft="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginLeft="48dip"
style="@style/accountSetupButton"
android:text="@string/account_setup_account_type_pop_action" />
<Button
android:id="@+id/imap"
android:layout_below="@+id/pop"
android:layout_alignParentLeft="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginLeft="48dip"
style="@style/accountSetupButton"
android:text="@string/account_setup_account_type_imap_action" />
<Button
android:id="@+id/exchange"
android:layout_below="@+id/imap"
android:layout_alignParentLeft="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginLeft="48dip"
style="@style/accountSetupButton"
android:text="@string/account_setup_account_type_exchange_action" />
</RelativeLayout>
<!-- Previous button (can be below or to the right) -->

View File

@ -1,134 +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.
-->
<!-- Exchange server settings - tablet - see layout/ for phone UX variant -->
<!-- This is used directly by the account setup activity, but during settings it is
wrapped in an outer layout (account_settings_exchange_fragment) -->
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1" >
<TableRow
android:paddingTop="16dip" >
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="16dip"
android:text="@string/account_setup_exchange_username_label" />
<EditText
android:id="@+id/account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/account_setup_exchange_username_label"
android:inputType="textEmailAddress"
android:imeOptions="actionDone" />
</TableRow>
<TableRow
android:paddingTop="16dip" >
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="16dip"
android:text="@string/account_setup_incoming_password_label" />
<EditText
android:id="@+id/account_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/account_setup_incoming_password_label"
android:inputType="textPassword"
android:imeOptions="actionDone" />
</TableRow>
<TableRow
android:paddingTop="16dip" >
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="16dip"
android:text="@string/account_setup_exchange_server_label" />
<!-- Note: we use inputType=textUri as the closest approximation to a server name -->
<EditText
android:id="@+id/account_server"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/account_setup_exchange_server_label"
android:inputType="textUri"
android:imeOptions="actionDone" />
</TableRow>
<!-- Note, this row is not a TableRow, and it will span the entire table - no columns -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dip"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<CheckBox
android:id="@+id/account_ssl"
android:layout_marginTop="16dip"
android:layout_marginBottom="16dip"
android:layout_marginLeft="32dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_exchange_ssl_label" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<CheckBox
android:id="@+id/account_trust_certificates"
android:layout_marginTop="16dip"
android:layout_marginBottom="16dip"
android:layout_marginLeft="32dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/account_setup_exchange_trust_certificates_label"
android:visibility="gone" />
<View
android:id="@+id/account_trust_certificates_divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color"
android:visibility="gone" />
<include
android:id="@+id/client_certificate_selector"
layout="@layout/client_certificate_selector"
android:visibility="gone" />
<View
android:id="@+id/client_certificate_divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color"
android:visibility="gone" />
</LinearLayout>
<TableRow
android:paddingTop="32dip" >
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="16dip"
android:text="@string/account_setup_exchange_device_id_label" />
<!-- TODO - when adding back in styles, this should be slightly different (was "medium") -->
<TextView
android:id="@+id/device_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffbebebe" />
</TableRow>
</TableLayout>

View File

@ -98,6 +98,10 @@
android:inputType="number"
android:imeOptions="actionDone" />
</TableRow>
<include
android:id="@+id/client_certificate_selector"
layout="@layout/client_certificate_selector"
android:visibility="gone" />
<TableRow
android:paddingTop="16dip" >
<TextView
@ -129,5 +133,21 @@
android:inputType="text"
android:imeOptions="actionDone" />
</TableRow>
<TableRow
android:id="@+id/device_id_section"
android:paddingTop="32dip"
android:visibility="gone" >
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginRight="16dip"
android:text="@string/account_setup_exchange_device_id_label" />
<!-- TODO - when adding back in styles, this should be slightly different (was "medium") -->
<TextView
android:id="@+id/device_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffbebebe" />
</TableRow>
</TableLayout>

View File

@ -0,0 +1,23 @@
<?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.
-->
<!-- small -->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_alignParentLeft="true"
android:layout_marginTop="@dimen/setup_buttons_vertical_spacing"
android:layout_marginLeft="48dip"
style="@style/accountSetupButton" />

View File

@ -1,52 +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.
-->
<!-- Exchange server settings. This is a wrapper around the "exchange setup" fragment
that adds scrollview & buttons and makes it more compatible with a 2-pane PreferenceActivity
such as AccountSettingsXL. -->
<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/settings_fragment_padding_top"
android:paddingLeft="@dimen/settings_fragment_padding_left"
android:paddingRight="@dimen/settings_fragment_padding_right"
>
<!-- Fields entry -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<include
layout="@layout/account_setup_exchange_fragment"
/>
</FrameLayout>
<!-- This spacer fills the viewport and moves the buttons to the bottom -->
<View
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<include layout="@layout/account_settings_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 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
android:id="@+id/setup_fragment"
class="com.android.email.activity.setup.AccountSetupExchangeFragment"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>
<include layout="@layout/account_setup_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -1,89 +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.
-->
<!-- Exchange server settings - default - see layout-xlarge/ for XL variant -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:text="@string/account_setup_exchange_username_label"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary" />
<EditText
android:id="@+id/account_username"
android:inputType="textEmailAddress"
android:imeOptions="actionNext"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:contentDescription="@string/account_setup_exchange_username_label" />
<TextView
android:text="@string/account_setup_incoming_password_label"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary" />
<EditText
android:id="@+id/account_password"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
<!-- This text may be changed in code if the server is IMAP, etc. -->
<TextView
android:text="@string/account_setup_exchange_server_label"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary" />
<!-- Note: we use inputType=textUri as the closest approximation to a server name -->
<EditText
android:id="@+id/account_server"
android:inputType="textUri"
android:imeOptions="actionDone"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:contentDescription="@string/account_setup_exchange_server_label" />
<CheckBox
android:id="@+id/account_ssl"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/account_setup_exchange_ssl_label" />
<CheckBox
android:id="@+id/account_trust_certificates"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/account_setup_exchange_trust_certificates_label" />
<include
android:id="@+id/client_certificate_selector"
layout="@layout/client_certificate_selector"
android:visibility="gone" />
<TextView
android:text="@string/account_setup_exchange_device_id_label"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/device_id"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffbebebe" />
</LinearLayout>

View File

@ -87,6 +87,10 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:contentDescription="@string/account_setup_incoming_security_label" />
<include
android:id="@+id/client_certificate_selector"
layout="@layout/client_certificate_selector"
android:visibility="gone" />
<TextView
android:id="@+id/account_delete_policy_label"
android:text="@string/account_setup_incoming_delete_policy_label"
@ -119,4 +123,22 @@
android:inputType="text"
android:imeOptions="actionDone" />
</LinearLayout>
<LinearLayout
android:id="@+id/device_id_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:text="@string/account_setup_exchange_device_id_label"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/device_id"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffbebebe" />
</LinearLayout>
</LinearLayout>

View File

@ -29,14 +29,18 @@
<attr name="intent" format="string"/>
<attr name="port" format="integer"/>
<attr name="portSsl" format="integer"/>
<attr name="preferSsl" format="boolean"/>
<attr name="defaultSsl" format="boolean"/>
<attr name="offerTls" format="boolean"/>
<attr name="offerCerts" format="boolean"/>
<attr name="offerLocalDeletes" format="boolean"/>
<attr name="offerPrefix" format="boolean"/>
<attr name="usesSmtp" format="boolean"/>
<attr name="push" format="boolean"/>
<attr name="contacts" format="boolean"/>
<attr name="calendar" format="boolean"/>
<attr name="autodiscover" format="boolean"/>
<attr name="lookback" format="boolean"/>
<attr name="attachmentPreload" format="boolean"/>
<attr name="offerPush" format="boolean"/>
<attr name="syncContacts" format="boolean"/>
<attr name="syncCalendar" format="boolean"/>
<attr name="usesAutodiscover" format="boolean"/>
<attr name="offerLookback" format="boolean"/>
<attr name="offerAttachmentPreload" format="boolean"/>
<attr name="syncIntervalStrings" format="reference"/>
<attr name="syncIntervals" format="reference"/>
</declare-styleable>

View File

@ -22,7 +22,9 @@
email:serviceClass="com.android.email.service.ImapService"
email:port="110"
email:portSsl="995"
email:offerTls="true"
email:usesSmtp="true"
email:offerLocalDeletes="true"
email:syncIntervalStrings="@array/account_settings_check_frequency_entries"
email:syncIntervals="@array/account_settings_check_frequency_values" />
<emailservice
@ -30,10 +32,12 @@
email:name="IMAP"
email:accountType="com.android.email"
email:serviceClass="com.android.email.service.Pop3Service"
email:attachmentPreload="true"
email:offerAttachmentPreload="true"
email:port="143"
email:portSsl="995"
email:offerTls="true"
email:usesSmtp="true"
email:offerPrefix="true"
email:syncIntervalStrings="@array/account_settings_check_frequency_entries"
email:syncIntervals="@array/account_settings_check_frequency_values" />
<emailservice
@ -43,13 +47,14 @@
email:intent="com.android.email.EXCHANGE_INTENT"
email:port="80"
email:portSsl="443"
email:preferSsl="true"
email:defaultSsl="true"
email:offerCerts="true"
email:syncIntervalStrings="@array/account_settings_check_frequency_entries_push"
email:syncIntervals="@array/account_settings_check_frequency_values_push"
email:autodiscover="true"
email:attachmentPreload="true"
email:push="true"
email:lookback="true"
email:contacts="true"
email:calendar="true" />
email:usesAutodiscover="true"
email:offerAttachmentPreload="true"
email:offerPush="true"
email:offerLookback="true"
email:syncContacts="true"
email:syncCalendar="true" />
</emailservices>

View File

@ -56,7 +56,7 @@ import java.util.List;
*
* This activity uses the following fragments:
* AccountSettingsFragment
* Account{Incoming/Outgoing/Exchange}Fragment
* Account{Incoming/Outgoing}Fragment
* AccountCheckSettingsFragment
* GeneralPreferences
* DebugFragment

View File

@ -506,7 +506,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
(PreferenceCategory) findPreference(PREFERENCE_CATEGORY_DATA_USAGE);
mSyncWindow = null;
if (info.lookback) {
if (info.offerLookback) {
mSyncWindow = new ListPreference(mContext);
mSyncWindow.setTitle(R.string.account_setup_options_mail_window_label);
mSyncWindow.setValue(String.valueOf(mAccount.getSyncLookback()));
@ -531,7 +531,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
mAccountBackgroundAttachments = (CheckBoxPreference)
findPreference(PREFERENCE_BACKGROUND_ATTACHMENTS);
if (!info.attachmentPreload) {
if (!info.offerAttachmentPreload) {
dataUsageCategory.removePreference(mAccountBackgroundAttachments);
} else {
mAccountBackgroundAttachments.setChecked(
@ -653,10 +653,10 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
mSyncContacts = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CONTACTS);
mSyncCalendar = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CALENDAR);
mSyncEmail = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_EMAIL);
if (info.contacts || info.calendar) {
if (info.syncContacts || info.syncCalendar) {
android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
info.accountType);
if (info.contacts) {
if (info.syncContacts) {
mSyncContacts.setChecked(ContentResolver
.getSyncAutomatically(acct, ContactsContract.AUTHORITY));
mSyncContacts.setOnPreferenceChangeListener(this);
@ -664,7 +664,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
mSyncContacts.setChecked(false);
mSyncContacts.setEnabled(false);
}
if (info.calendar) {
if (info.syncCalendar) {
mSyncCalendar.setChecked(ContentResolver
.getSyncAutomatically(acct, CalendarContract.AUTHORITY));
mSyncCalendar.setOnPreferenceChangeListener(this);
@ -725,7 +725,7 @@ public class AccountSettingsFragment extends EmailPreferenceFragment
EmailServiceInfo info =
EmailServiceUtils.getServiceInfo(mContext, mAccount.getProtocol(mContext));
if (info.contacts || info.calendar) {
if (info.syncContacts || info.syncCalendar) {
android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
AccountManagerTypes.TYPE_EXCHANGE);
ContentResolver.setSyncAutomatically(acct, ContactsContract.AUTHORITY,

View File

@ -1,457 +0,0 @@
/*
* 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.
*/
package com.android.email.activity.setup;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
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.email.view.CertificateSelector;
import com.android.email.view.CertificateSelector.HostCallback;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Device;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.CertificateRequestor;
import com.android.emailcommon.utility.Utility;
import java.io.IOException;
/**
* Provides generic setup for Exchange accounts.
*
* This fragment is used by AccountSetupExchange (for creating accounts) and by AccountSettingsXL
* (for editing existing accounts).
*/
public class AccountSetupExchangeFragment extends AccountServerBaseFragment
implements OnCheckedChangeListener, HostCallback {
private static final int CERTIFICATE_REQUEST = 0;
private final static String STATE_KEY_CREDENTIAL = "AccountSetupExchangeFragment.credential";
private final static String STATE_KEY_LOADED = "AccountSetupExchangeFragment.loaded";
private EditText mUsernameView;
private EditText mPasswordView;
private EditText mServerView;
private CheckBox mSslSecurityView;
private CheckBox mTrustCertificatesView;
private CertificateSelector mClientCertificateSelector;
// Support for lifecycle
private boolean mStarted;
/* package */ boolean mLoaded;
private String mCacheLoginCredential;
/**
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onCreate");
}
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCacheLoginCredential = savedInstanceState.getString(STATE_KEY_CREDENTIAL);
mLoaded = savedInstanceState.getBoolean(STATE_KEY_LOADED, false);
}
mBaseScheme = HostAuth.SCHEME_EAS;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onCreateView");
}
int layoutId = mSettingsMode
? R.layout.account_settings_exchange_fragment
: R.layout.account_setup_exchange_fragment;
View view = inflater.inflate(layoutId, container, false);
final Context context = getActivity();
mUsernameView = UiUtilities.getView(view, R.id.account_username);
mPasswordView = UiUtilities.getView(view, R.id.account_password);
mServerView = UiUtilities.getView(view, R.id.account_server);
mSslSecurityView = UiUtilities.getView(view, R.id.account_ssl);
mSslSecurityView.setOnCheckedChangeListener(this);
mTrustCertificatesView = UiUtilities.getView(view, R.id.account_trust_certificates);
mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector);
// Calls validateFields() which enables or disables the Next button
// based on the fields' validity.
TextWatcher validationTextWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
validateFields();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
};
// We're editing an existing account; don't allow modification of the user name
if (mSettingsMode) {
makeTextViewUneditable(mUsernameView,
getString(R.string.account_setup_username_uneditable_error));
}
mUsernameView.addTextChangedListener(validationTextWatcher);
mPasswordView.addTextChangedListener(validationTextWatcher);
mServerView.addTextChangedListener(validationTextWatcher);
EditText lastView = mServerView;
lastView.setOnEditorActionListener(mDismissImeOnDoneListener);
String deviceId = "";
try {
deviceId = Device.getDeviceId(context);
} catch (IOException e) {
// Not required
}
((TextView) UiUtilities.getView(view, R.id.device_id)).setText(deviceId);
// Additional setup only used while in "settings" mode
onCreateViewSettingsMode(view);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onActivityCreated");
}
super.onActivityCreated(savedInstanceState);
mClientCertificateSelector.setHostActivity(this);
}
/**
* Called when the Fragment is visible to the user.
*/
@Override
public void onStart() {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onStart");
}
super.onStart();
mStarted = true;
loadSettings(SetupData.getAccount());
}
/**
* Called when the fragment is visible to the user and actively running.
*/
@Override
public void onResume() {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onResume");
}
super.onResume();
validateFields();
}
@Override
public void onPause() {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onPause");
}
super.onPause();
}
/**
* Called when the Fragment is no longer started.
*/
@Override
public void onStop() {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onStop");
}
super.onStop();
mStarted = false;
}
/**
* Called when the fragment is no longer in use.
*/
@Override
public void onDestroy() {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onDestroy");
}
super.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (Logging.DEBUG_LIFECYCLE && MailActivityEmail.DEBUG) {
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onSaveInstanceState");
}
super.onSaveInstanceState(outState);
outState.putString(STATE_KEY_CREDENTIAL, mCacheLoginCredential);
outState.putBoolean(STATE_KEY_LOADED, mLoaded);
}
/**
* Activity provides callbacks here. This also triggers loading and setting up the UX
*/
@Override
public void setCallback(Callback callback) {
super.setCallback(callback);
if (mStarted) {
loadSettings(SetupData.getAccount());
}
}
/**
* Force the given account settings to be loaded using {@link #loadSettings(Account)}.
*
* @return true if the loaded values pass validation
*/
private boolean forceLoadSettings(Account account) {
mLoaded = false;
return loadSettings(account);
}
/**
* Load the given account settings into the UI and then ensure the settings are valid.
* As an optimization, if the settings have already been loaded, the UI will not be
* updated, but, the account fields will still be validated.
*
* @return true if the loaded values pass validation
*/
/*package*/ boolean loadSettings(Account account) {
if (mLoaded) return validateFields();
HostAuth hostAuth = account.mHostAuthRecv;
String userName = hostAuth.mLogin;
if (userName != null) {
// Add a backslash to the start of the username, but only if the username has no
// backslash in it.
if (userName.indexOf('\\') < 0) {
userName = "\\" + userName;
}
mUsernameView.setText(userName);
}
if (hostAuth.mPassword != null) {
mPasswordView.setText(hostAuth.mPassword);
// Since username is uneditable, focus on the next editable field
if (mSettingsMode) {
mPasswordView.requestFocus();
}
}
String protocol = hostAuth.mProtocol;
if (protocol == null || !protocol.startsWith("eas")) {
throw new Error("Unknown account type: " + protocol);
}
if (hostAuth.mAddress != null) {
mServerView.setText(hostAuth.mAddress);
}
boolean ssl = 0 != (hostAuth.mFlags & HostAuth.FLAG_SSL);
boolean trustCertificates = 0 != (hostAuth.mFlags & HostAuth.FLAG_TRUST_ALL);
mSslSecurityView.setChecked(ssl);
mTrustCertificatesView.setChecked(trustCertificates);
if (hostAuth.mClientCertAlias != null) {
mClientCertificateSelector.setCertificate(hostAuth.mClientCertAlias);
}
onUseSslChanged(ssl);
mLoadedRecvAuth = hostAuth;
mLoaded = true;
return validateFields();
}
private boolean usernameFieldValid(EditText usernameView) {
return Utility.isTextViewNotEmpty(usernameView) &&
!usernameView.getText().toString().equals("\\");
}
/**
* Check the values in the fields and decide if it makes sense to enable the "next" button
* @return true if all fields are valid, false if any fields are incomplete
*/
private boolean validateFields() {
if (!mLoaded) return false;
boolean enabled = usernameFieldValid(mUsernameView)
&& Utility.isTextViewNotEmpty(mPasswordView)
&& Utility.isServerNameValid(mServerView);
enableNextButton(enabled);
// Warn (but don't prevent) if password has leading/trailing spaces
AccountSettingsUtils.checkPasswordSpaces(mContext, mPasswordView);
return enabled;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.getId() == R.id.account_ssl) {
onUseSslChanged(isChecked);
}
}
public void onUseSslChanged(boolean useSsl) {
int mode = useSsl ? View.VISIBLE : View.GONE;
mTrustCertificatesView.setVisibility(mode);
UiUtilities.setVisibilitySafe(getView(), R.id.account_trust_certificates_divider, mode);
mClientCertificateSelector.setVisibility(mode);
UiUtilities.setVisibilitySafe(getView(), R.id.client_certificate_divider, mode);
}
@Override
public void onCheckSettingsComplete(final int result) {
if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_CLIENT_CERTIFICATE_NEEDED) {
mSslSecurityView.setChecked(true);
onCertificateRequested();
return;
}
super.onCheckSettingsComplete(result);
}
/**
* Entry point from Activity after editing settings and verifying them. Must be FLOW_MODE_EDIT.
* Blocking - do not call from UI Thread.
*/
@Override
public void saveSettingsAfterEdit() {
Account account = SetupData.getAccount();
account.mHostAuthRecv.update(mContext, account.mHostAuthRecv.toContentValues());
account.mHostAuthSend.update(mContext, account.mHostAuthSend.toContentValues());
// For EAS, notify ExchangeService that the password has changed
try {
EmailServiceUtils.getService(mContext, null, "eas").hostChanged(account.mId);
} catch (RemoteException e) {
// Nothing to be done if this fails
}
// Update the backup (side copy) of the accounts
AccountBackupRestore.backup(mContext);
}
/**
* Entry point from Activity after entering new settings and verifying them. For setup mode.
*/
@Override
public void saveSettingsAfterSetup() {
}
/**
* Entry point from Activity after entering new settings and verifying them. For setup mode.
*/
public boolean setHostAuthFromAutodiscover(HostAuth newHostAuth) {
Account account = SetupData.getAccount();
account.mHostAuthSend = newHostAuth;
account.mHostAuthRecv = newHostAuth;
// Auto discovery may have changed the auth settings; force load them
return forceLoadSettings(account);
}
/**
* Implements AccountCheckSettingsFragment.Callbacks
*/
@Override
public void onAutoDiscoverComplete(int result, HostAuth hostAuth) {
AccountSetupIncoming activity = (AccountSetupIncoming) getActivity();
activity.onAutoDiscoverComplete(result, hostAuth);
}
/**
* Entry point from Activity, when "next" button is clicked
*/
@Override
public void onNext() {
Account account = SetupData.getAccount();
String userName = mUsernameView.getText().toString().trim();
if (userName.startsWith("\\")) {
userName = userName.substring(1);
}
mCacheLoginCredential = userName;
String userPassword = mPasswordView.getText().toString();
int flags = 0;
if (mSslSecurityView.isChecked()) {
flags |= HostAuth.FLAG_SSL;
}
if (mTrustCertificatesView.isChecked()) {
flags |= HostAuth.FLAG_TRUST_ALL;
}
String certAlias = mClientCertificateSelector.getCertificate();
String serverAddress = mServerView.getText().toString().trim();
int port = mSslSecurityView.isChecked() ? 443 : 80;
HostAuth sendAuth = account.getOrCreateHostAuthSend(mContext);
sendAuth.setLogin(userName, userPassword);
sendAuth.setConnection(mBaseScheme, serverAddress, port, flags, certAlias);
sendAuth.mDomain = null;
HostAuth recvAuth = account.getOrCreateHostAuthRecv(mContext);
recvAuth.setLogin(userName, userPassword);
recvAuth.setConnection(mBaseScheme, serverAddress, port, flags, certAlias);
recvAuth.mDomain = null;
// Check for a duplicate account (requires async DB work) and if OK, proceed with check
startDuplicateTaskCheck(account.mId, serverAddress, mCacheLoginCredential,
SetupData.CHECK_INCOMING);
}
@Override
public void onCertificateRequested() {
Intent intent = new Intent(CertificateRequestor.ACTION_REQUEST_CERT);
intent.setData(Uri.parse("eas://com.android.emailcommon/certrequest"));
startActivityForResult(intent, CERTIFICATE_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) {
String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
if (certAlias != null) {
mClientCertificateSelector.setCertificate(certAlias);
}
}
}
}

View File

@ -65,9 +65,7 @@ public class AccountSetupIncoming extends AccountSetupActivity
HostAuth hostAuth = SetupData.getAccount().mHostAuthRecv;
mServiceInfo = EmailServiceUtils.getServiceInfo(this, hostAuth.mProtocol);
setContentView(hostAuth.mProtocol.equals("eas") ? R.layout.account_setup_exchange :
R.layout.account_setup_incoming);
setContentView(R.layout.account_setup_incoming);
mFragment = (AccountServerBaseFragment)
getFragmentManager().findFragmentById(R.id.setup_fragment);
@ -79,7 +77,7 @@ public class AccountSetupIncoming extends AccountSetupActivity
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
// One-shot to launch autodiscovery at the entry to this activity (but not if it restarts)
if (mServiceInfo.autodiscover) {
if (mServiceInfo.usesAutodiscover) {
mStartedAutoDiscovery = false;
if (savedInstanceState != null) {
mStartedAutoDiscovery = savedInstanceState.getBoolean(STATE_STARTED_AUTODISCOVERY);

View File

@ -18,6 +18,8 @@ package com.android.email.activity.setup;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
@ -39,20 +41,29 @@ import com.android.email.activity.UiUtilities;
import com.android.email.provider.AccountBackupRestore;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
import com.android.email.view.CertificateSelector;
import com.android.email.view.CertificateSelector.HostCallback;
import com.android.email2.ui.MailActivityEmail;
import com.android.emailcommon.Device;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.utility.CertificateRequestor;
import com.android.emailcommon.utility.Utility;
import java.io.IOException;
import java.util.ArrayList;
/**
* Provides UI for IMAP/POP account settings.
*
* This fragment is used by AccountSetupIncoming (for creating accounts) and by AccountSettingsXL
* (for editing existing accounts).
*/
public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
public class AccountSetupIncomingFragment extends AccountServerBaseFragment
implements HostCallback {
private static final int CERTIFICATE_REQUEST = 0;
private final static String STATE_KEY_CREDENTIAL = "AccountSetupIncomingFragment.credential";
private final static String STATE_KEY_LOADED = "AccountSetupIncomingFragment.loaded";
@ -65,7 +76,9 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
private TextView mDeletePolicyLabelView;
private Spinner mDeletePolicyView;
private View mImapPathPrefixSectionView;
private View mDeviceIdSectionView;
private EditText mImapPathPrefixView;
private CertificateSelector mClientCertificateSelector;
// Delete policy as loaded from the device
private int mLoadedDeletePolicy;
@ -74,6 +87,8 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
private boolean mConfigured;
private boolean mLoaded;
private String mCacheLoginCredential;
private HostAuth mRecvAuth;
private EmailServiceInfo mServiceInfo;
/**
* Called to do initial creation of a fragment. This is called after
@ -105,6 +120,9 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
View view = inflater.inflate(layoutId, container, false);
Context context = getActivity();
mRecvAuth = SetupData.getAccount().mHostAuthRecv;
mServiceInfo = EmailServiceUtils.getServiceInfo(mContext, mRecvAuth.mProtocol);
mUsernameView = (EditText) UiUtilities.getView(view, R.id.account_username);
mPasswordView = (EditText) UiUtilities.getView(view, R.id.account_password);
mServerLabelView = (TextView) UiUtilities.getView(view, R.id.account_server_label);
@ -115,39 +133,51 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
R.id.account_delete_policy_label);
mDeletePolicyView = (Spinner) UiUtilities.getView(view, R.id.account_delete_policy);
mImapPathPrefixSectionView = UiUtilities.getView(view, R.id.imap_path_prefix_section);
mDeviceIdSectionView = UiUtilities.getView(view, R.id.device_id_section);
mImapPathPrefixView = (EditText) UiUtilities.getView(view, R.id.imap_path_prefix);
mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector);
// Set up spinners
SpinnerOption securityTypes[] = {
new SpinnerOption(HostAuth.FLAG_NONE, context.getString(
R.string.account_setup_incoming_security_none_label)),
new SpinnerOption(HostAuth.FLAG_SSL, context.getString(
R.string.account_setup_incoming_security_ssl_label)),
new SpinnerOption(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, context.getString(
R.string.account_setup_incoming_security_ssl_trust_certificates_label)),
new SpinnerOption(HostAuth.FLAG_TLS, context.getString(
R.string.account_setup_incoming_security_tls_label)),
new SpinnerOption(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL, context.getString(
R.string.account_setup_incoming_security_tls_trust_certificates_label)),
};
SpinnerOption deletePolicies[] = {
new SpinnerOption(Account.DELETE_POLICY_NEVER,
context.getString(R.string.account_setup_incoming_delete_policy_never_label)),
new SpinnerOption(Account.DELETE_POLICY_ON_DELETE,
context.getString(R.string.account_setup_incoming_delete_policy_delete_label)),
};
ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>(context,
android.R.layout.simple_spinner_item, securityTypes);
// Set up security type spinner
ArrayList<SpinnerOption> securityTypes = new ArrayList<SpinnerOption>();
securityTypes.add(
new SpinnerOption(HostAuth.FLAG_NONE, context.getString(
R.string.account_setup_incoming_security_none_label)));
securityTypes.add(
new SpinnerOption(HostAuth.FLAG_SSL, context.getString(
R.string.account_setup_incoming_security_ssl_label)));
securityTypes.add(
new SpinnerOption(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, context.getString(
R.string.account_setup_incoming_security_ssl_trust_certificates_label)));
if (mServiceInfo.offerTls) {
securityTypes.add(
new SpinnerOption(HostAuth.FLAG_TLS, context.getString(
R.string.account_setup_incoming_security_tls_label)));
securityTypes.add(
new SpinnerOption(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL,
context.getString(
R.string.account_setup_incoming_security_tls_trust_certificates_label)));
}
ArrayAdapter<SpinnerOption> securityTypesAdapter = new ArrayAdapter<SpinnerOption>(
context, android.R.layout.simple_spinner_item, securityTypes);
securityTypesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSecurityTypeView.setAdapter(securityTypesAdapter);
ArrayAdapter<SpinnerOption> deletePoliciesAdapter = new ArrayAdapter<SpinnerOption>(context,
android.R.layout.simple_spinner_item, deletePolicies);
deletePoliciesAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
mDeletePolicyView.setAdapter(deletePoliciesAdapter);
if (mServiceInfo.offerLocalDeletes) {
SpinnerOption deletePolicies[] = {
new SpinnerOption(Account.DELETE_POLICY_NEVER,
context.getString(
R.string.account_setup_incoming_delete_policy_never_label)),
new SpinnerOption(Account.DELETE_POLICY_ON_DELETE,
context.getString(
R.string.account_setup_incoming_delete_policy_delete_label)),
};
ArrayAdapter<SpinnerOption> deletePoliciesAdapter =
new ArrayAdapter<SpinnerOption>(context,
android.R.layout.simple_spinner_item, deletePolicies);
deletePoliciesAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
mDeletePolicyView.setAdapter(deletePoliciesAdapter);
}
// Updates the port when the user changes the security type. This allows
// us to show a reasonable default which the user can change.
@ -193,6 +223,7 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
Log.d(Logging.LOG_TAG, "AccountSetupIncomingFragment onActivityCreated");
}
super.onActivityCreated(savedInstanceState);
mClientCertificateSelector.setHostActivity(this);
}
/**
@ -289,15 +320,14 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
mServerLabelView.setText(R.string.account_setup_incoming_server_label);
mServerView.setContentDescription(getResources().getText(
R.string.account_setup_incoming_server_label));
if (HostAuth.SCHEME_POP3.equals(mBaseScheme)) {
if (!mServiceInfo.offerPrefix) {
mImapPathPrefixSectionView.setVisibility(View.GONE);
lastView = mPortView;
} else if (HostAuth.SCHEME_IMAP.equals(mBaseScheme)) {
}
if (!mServiceInfo.offerLocalDeletes) {
mDeletePolicyLabelView.setVisibility(View.GONE);
mDeletePolicyView.setVisibility(View.GONE);
mPortView.setImeOptions(EditorInfo.IME_ACTION_NEXT);
} else {
throw new Error("Unknown account type: " + account);
}
lastView.setOnEditorActionListener(mDismissImeOnDoneListener);
mConfigured = true;
@ -314,6 +344,12 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
String username = recvAuth.mLogin;
if (username != null) {
//*** For eas?
// Add a backslash to the start of the username, but only if the username has no
// backslash in it.
//if (userName.indexOf('\\') < 0) {
// userName = "\\" + userName;
//}
mUsernameView.setText(username);
}
String password = recvAuth.mPassword;
@ -325,14 +361,11 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
}
}
if (HostAuth.SCHEME_IMAP.equals(recvAuth.mProtocol)) {
if (mServiceInfo.offerPrefix) {
String prefix = recvAuth.mDomain;
if (prefix != null && prefix.length() > 0) {
mImapPathPrefixView.setText(prefix.substring(1));
}
} else if (!HostAuth.SCHEME_POP3.equals(recvAuth.mProtocol)) {
// Account must either be IMAP or POP3
throw new Error("Unknown account type: " + recvAuth.mProtocol);
}
// The delete policy is set for all legacy accounts. For POP3 accounts, the user sets
@ -343,6 +376,9 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
int flags = recvAuth.mFlags;
flags &= ~HostAuth.FLAG_AUTHENTICATE;
if (mServiceInfo.defaultSsl) {
flags |= HostAuth.FLAG_SSL;
}
SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, flags);
String hostname = recvAuth.mAddress;
@ -380,18 +416,39 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
AccountSettingsUtils.checkPasswordSpaces(mContext, mPasswordView);
}
private int getPortFromSecurityType() {
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
boolean useSsl = ((securityType & HostAuth.FLAG_SSL) != 0);
private int getPortFromSecurityType(boolean useSsl) {
EmailServiceInfo info = EmailServiceUtils.getServiceInfo(mContext,
SetupData.getAccount().mHostAuthRecv.mProtocol);
int port = useSsl ? info.portSsl : info.port;
return port;
return useSsl ? info.portSsl : info.port;
}
private boolean getSslSelected() {
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
return ((securityType & HostAuth.FLAG_SSL) != 0);
}
public void onUseSslChanged(boolean useSsl) {
if (mServiceInfo.offerCerts) {
int mode = useSsl ? View.VISIBLE : View.GONE;
mClientCertificateSelector.setVisibility(mode);
String deviceId = "";
try {
deviceId = Device.getDeviceId(mContext);
} catch (IOException e) {
// Not required
}
((TextView) UiUtilities.getView(getView(), R.id.device_id)).setText(deviceId);
mDeviceIdSectionView.setVisibility(mode);
//UiUtilities.setVisibilitySafe(getView(), R.id.client_certificate_divider, mode);
}
}
private void updatePortFromSecurityType() {
int port = getPortFromSecurityType();
boolean sslSelected = getSslSelected();
int port = getPortFromSecurityType(sslSelected);
mPortView.setText(Integer.toString(port));
onUseSslChanged(sslSelected);
}
/**
@ -450,12 +507,12 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
try {
serverPort = Integer.parseInt(mPortView.getText().toString().trim());
} catch (NumberFormatException e) {
serverPort = getPortFromSecurityType();
serverPort = getPortFromSecurityType(getSslSelected());
Log.d(Logging.LOG_TAG, "Non-integer server port; using '" + serverPort + "'");
}
int securityType = (Integer) ((SpinnerOption) mSecurityTypeView.getSelectedItem()).value;
recvAuth.setConnection(mBaseScheme, serverAddress, serverPort, securityType);
if (HostAuth.SCHEME_IMAP.equals(recvAuth.mProtocol)) {
if (mServiceInfo.offerPrefix) {
String prefix = mImapPathPrefixView.getText().toString().trim();
recvAuth.mDomain = TextUtils.isEmpty(prefix) ? null : ("/" + prefix);
} else {
@ -481,4 +538,30 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
return deletePolicyChanged || super.haveSettingsChanged();
}
/**
* Implements AccountCheckSettingsFragment.Callbacks
*/
@Override
public void onAutoDiscoverComplete(int result, HostAuth hostAuth) {
AccountSetupIncoming activity = (AccountSetupIncoming) getActivity();
activity.onAutoDiscoverComplete(result, hostAuth);
}
@Override
public void onCertificateRequested() {
Intent intent = new Intent(CertificateRequestor.ACTION_REQUEST_CERT);
intent.setData(Uri.parse("eas://com.android.emailcommon/certrequest"));
startActivityForResult(intent, CERTIFICATE_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) {
String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
if (certAlias != null) {
mClientCertificateSelector.setCertificate(certAlias);
}
}
}
}

View File

@ -111,7 +111,7 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
if (info.lookback) {
if (info.offerLookback) {
enableLookbackSpinner();
}
@ -124,18 +124,18 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
(account.getFlags() & Account.FLAGS_NOTIFY_NEW_MAIL) != 0);
SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, account.getSyncInterval());
if (info.contacts) {
if (info.syncContacts) {
mSyncContactsView.setVisibility(View.VISIBLE);
mSyncContactsView.setChecked(true);
UiUtilities.setVisibilitySafe(this, R.id.account_sync_contacts_divider, View.VISIBLE);
}
if (info.calendar) {
if (info.syncCalendar) {
mSyncCalendarView.setVisibility(View.VISIBLE);
mSyncCalendarView.setChecked(true);
UiUtilities.setVisibilitySafe(this, R.id.account_sync_calendar_divider, View.VISIBLE);
}
if (info.attachmentPreload) {
if (!info.offerAttachmentPreload) {
mBackgroundAttachmentsView.setVisibility(View.GONE);
UiUtilities.setVisibilitySafe(this, R.id.account_background_attachments_divider,
View.GONE);

View File

@ -24,7 +24,8 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
@ -60,16 +61,23 @@ public class AccountSetupType extends AccountSetupActivity implements OnClickLis
// Otherwise proceed into this screen
setContentView(R.layout.account_setup_account_type);
ViewGroup parent = UiUtilities.getView(this, R.id.accountTypes);
boolean parentRelative = parent instanceof RelativeLayout;
View lastView = parent.getChildAt(0);
int i = 1;
for (EmailServiceInfo info: EmailServiceUtils.getServiceInfoList(this)) {
if (EmailServiceUtils.isServiceAvailable(this, info.protocol)) {
ViewGroup parent = UiUtilities.getView(this, R.id.accountTypes);
LinearLayout view = (LinearLayout)LayoutInflater.from(this)
.inflate(R.layout.account_type, parent);
Button button = (Button)view.getChildAt(i);
LayoutInflater.from(this).inflate(R.layout.account_type, parent);
Button button = (Button)parent.getChildAt(i);
if (parentRelative) {
LayoutParams params = (LayoutParams)button.getLayoutParams();
params.addRule(RelativeLayout.BELOW, lastView.getId());
}
button.setId(i);
button.setTag(info.protocol);
button.setText(info.name);
button.setOnClickListener(this);
lastView = button;
i++;
// TODO: Remember vendor overlay for exchange name
}
@ -87,7 +95,7 @@ public class AccountSetupType extends AccountSetupActivity implements OnClickLis
HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
recvAuth.setConnection(protocol, recvAuth.mAddress, recvAuth.mPort, recvAuth.mFlags);
EmailServiceInfo info = EmailServiceUtils.getServiceInfo(this, protocol);
if (info.autodiscover) {
if (info.usesAutodiscover) {
SetupData.setCheckSettingsMode(SetupData.CHECK_AUTODISCOVER);
} else {
SetupData.setCheckSettingsMode(
@ -96,17 +104,19 @@ public class AccountSetupType extends AccountSetupActivity implements OnClickLis
recvAuth.mLogin = recvAuth.mLogin + "@" + recvAuth.mAddress;
AccountSetupBasics.setFlagsForProtocol(account, protocol);
AccountSetupIncoming.actionIncomingSettings(this, SetupData.getFlowMode(), account);
// Back from the incoming screen returns to AccountSetupBasics
finish();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
onSelect((String)v.getTag());
break;
case R.id.previous:
finish();
break;
default:
onSelect((String)v.getTag());
break;
}
}
}

View File

@ -84,14 +84,18 @@ public class EmailServiceUtils {
String intentAction;
public int port;
public int portSsl;
public boolean preferSsl = false;
public boolean usesSmtp = true;
public boolean autodiscover = false;
public boolean push = false;
public boolean lookback = false;
public boolean contacts = false;
public boolean calendar = false;
public boolean attachmentPreload = true;
public boolean defaultSsl = false;
public boolean offerTls = false;
public boolean offerCerts = false;
public boolean usesSmtp = false;
public boolean offerLocalDeletes = false;
public boolean offerPrefix = false;
public boolean usesAutodiscover = false;
public boolean offerPush = false;
public boolean offerLookback = false;
public boolean syncContacts = false;
public boolean syncCalendar = false;
public boolean offerAttachmentPreload = false;
public int serverLabel;
public CharSequence[] syncIntervalStrings;
public CharSequence[] syncIntervals;
@ -146,18 +150,27 @@ public class EmailServiceUtils {
String klass = ta.getString(R.styleable.EmailServiceInfo_serviceClass);
info.intentAction = ta.getString(R.styleable.EmailServiceInfo_intent);
info.accountType = ta.getString(R.styleable.EmailServiceInfo_accountType);
info.preferSsl = ta.getBoolean(R.styleable.EmailServiceInfo_preferSsl, false);
info.defaultSsl = ta.getBoolean(R.styleable.EmailServiceInfo_defaultSsl, false);
info.port = ta.getInteger(R.styleable.EmailServiceInfo_port, 0);
info.portSsl = ta.getInteger(R.styleable.EmailServiceInfo_portSsl, 0);
info.offerTls = ta.getBoolean(R.styleable.EmailServiceInfo_offerTls, false);
info.offerCerts = ta.getBoolean(R.styleable.EmailServiceInfo_offerCerts, false);
info.offerLocalDeletes =
ta.getBoolean(R.styleable.EmailServiceInfo_offerLocalDeletes, false);
info.offerPrefix =
ta.getBoolean(R.styleable.EmailServiceInfo_offerPrefix, false);
info.usesSmtp = ta.getBoolean(R.styleable.EmailServiceInfo_usesSmtp, false);
info.autodiscover =
ta.getBoolean(R.styleable.EmailServiceInfo_autodiscover, false);
info.push = ta.getBoolean(R.styleable.EmailServiceInfo_push, false);
info.lookback = ta.getBoolean(R.styleable.EmailServiceInfo_lookback, false);
info.contacts = ta.getBoolean(R.styleable.EmailServiceInfo_contacts, false);
info.calendar = ta.getBoolean(R.styleable.EmailServiceInfo_calendar, false);
info.attachmentPreload =
ta.getBoolean(R.styleable.EmailServiceInfo_attachmentPreload, false);
info.usesAutodiscover =
ta.getBoolean(R.styleable.EmailServiceInfo_usesAutodiscover, false);
info.offerPush = ta.getBoolean(R.styleable.EmailServiceInfo_offerPush, false);
info.offerLookback =
ta.getBoolean(R.styleable.EmailServiceInfo_offerLookback, false);
info.syncContacts =
ta.getBoolean(R.styleable.EmailServiceInfo_syncContacts, false);
info.syncCalendar =
ta.getBoolean(R.styleable.EmailServiceInfo_syncCalendar, false);
info.offerAttachmentPreload =
ta.getBoolean(R.styleable.EmailServiceInfo_offerAttachmentPreload, false);
info.syncIntervalStrings =
ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervalStrings);
info.syncIntervals =