diff options
author | Jessica Wagantall <jessicag@codeaurora.org> | 2014-12-19 19:23:18 -0800 |
---|---|---|
committer | Jessica Wagantall <jessicag@codeaurora.org> | 2014-12-19 19:24:38 -0800 |
commit | 56973a3d4071dbc0ee6f859093470778b8eb9824 (patch) | |
tree | f2e107ee0aa02be8e390c40e665fb2c1ee316bbe | |
parent | 647b3807c4bf1ad3c9f7676889afd3787184a03a (diff) | |
parent | 14e94b2a064f6447f3905de1a7858a2c08d8ecc8 (diff) | |
download | packages_apps_Contacts-56973a3d4071dbc0ee6f859093470778b8eb9824.tar.gz packages_apps_Contacts-56973a3d4071dbc0ee6f859093470778b8eb9824.tar.bz2 packages_apps_Contacts-56973a3d4071dbc0ee6f859093470778b8eb9824.zip |
Merge commit '14e94b2a064f6447f3905de1a7858a2c08d8ecc8' into HEAD
Change-Id: Id804dfef6576350bccb687d605b118cd6c21abf9
33 files changed, 907 insertions, 944 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 989cd02a4..61c6ae535 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -21,6 +21,7 @@ <original-package android:name="com.android.contacts" /> <uses-permission android:name="android.permission.CALL_PHONE" /> + <uses-permission android:name="android.permission.CALL_PRIVILEGED" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> @@ -438,10 +439,10 @@ android:theme="@style/BackgroundOnlyTheme" /> <activity - android:name=".editor.MultiPickContactActivity" + android:name=".activities.MultiPickContactActivity" android:windowSoftInputMode="stateHidden|adjustResize" android:screenOrientation="nosensor" - android:theme="@android:style/Theme.Holo.Light" + android:theme="@style/ContactPickerTheme" android:configChanges="orientation|keyboardHidden|layoutDirection"> <intent-filter> <action android:name="com.android.contacts.action.MULTI_PICK" /> diff --git a/res/drawable-hdpi/ic_call_incoming_holo_dark.png b/res/drawable-hdpi/ic_call_incoming_holo_dark.png Binary files differnew file mode 100644 index 000000000..8351f4805 --- /dev/null +++ b/res/drawable-hdpi/ic_call_incoming_holo_dark.png diff --git a/res/drawable-hdpi/ic_call_log_list_incoming_call.png b/res/drawable-hdpi/ic_call_log_list_incoming_call.png Binary files differdeleted file mode 100755 index 15b5e4436..000000000 --- a/res/drawable-hdpi/ic_call_log_list_incoming_call.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_call_log_list_missed_call.png b/res/drawable-hdpi/ic_call_log_list_missed_call.png Binary files differdeleted file mode 100755 index 8dcb2796c..000000000 --- a/res/drawable-hdpi/ic_call_log_list_missed_call.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_call_log_list_outgoing_call.png b/res/drawable-hdpi/ic_call_log_list_outgoing_call.png Binary files differdeleted file mode 100755 index 160c70736..000000000 --- a/res/drawable-hdpi/ic_call_log_list_outgoing_call.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_call_missed_holo_dark.png b/res/drawable-hdpi/ic_call_missed_holo_dark.png Binary files differnew file mode 100644 index 000000000..7c17c3010 --- /dev/null +++ b/res/drawable-hdpi/ic_call_missed_holo_dark.png diff --git a/res/drawable-hdpi/ic_call_outgoing_holo_dark.png b/res/drawable-hdpi/ic_call_outgoing_holo_dark.png Binary files differnew file mode 100644 index 000000000..3b9e0f8a9 --- /dev/null +++ b/res/drawable-hdpi/ic_call_outgoing_holo_dark.png diff --git a/res/drawable-mdpi/ic_call_incoming_holo_dark.png b/res/drawable-mdpi/ic_call_incoming_holo_dark.png Binary files differnew file mode 100644 index 000000000..8dcb350bc --- /dev/null +++ b/res/drawable-mdpi/ic_call_incoming_holo_dark.png diff --git a/res/drawable-mdpi/ic_call_missed_holo_dark.png b/res/drawable-mdpi/ic_call_missed_holo_dark.png Binary files differnew file mode 100644 index 000000000..af030cf13 --- /dev/null +++ b/res/drawable-mdpi/ic_call_missed_holo_dark.png diff --git a/res/drawable-mdpi/ic_call_outgoing_holo_dark.png b/res/drawable-mdpi/ic_call_outgoing_holo_dark.png Binary files differnew file mode 100644 index 000000000..38a01b7a6 --- /dev/null +++ b/res/drawable-mdpi/ic_call_outgoing_holo_dark.png diff --git a/res/drawable-xhdpi/ic_call_incoming_holo_dark.png b/res/drawable-xhdpi/ic_call_incoming_holo_dark.png Binary files differnew file mode 100644 index 000000000..8eb5f3d8b --- /dev/null +++ b/res/drawable-xhdpi/ic_call_incoming_holo_dark.png diff --git a/res/drawable-xhdpi/ic_call_missed_holo_dark.png b/res/drawable-xhdpi/ic_call_missed_holo_dark.png Binary files differnew file mode 100644 index 000000000..6d09a4e95 --- /dev/null +++ b/res/drawable-xhdpi/ic_call_missed_holo_dark.png diff --git a/res/drawable-xhdpi/ic_call_outgoing_holo_dark.png b/res/drawable-xhdpi/ic_call_outgoing_holo_dark.png Binary files differnew file mode 100644 index 000000000..636050403 --- /dev/null +++ b/res/drawable-xhdpi/ic_call_outgoing_holo_dark.png diff --git a/res/drawable-xxhdpi/ic_call_incoming_holo_dark.png b/res/drawable-xxhdpi/ic_call_incoming_holo_dark.png Binary files differnew file mode 100644 index 000000000..12769173b --- /dev/null +++ b/res/drawable-xxhdpi/ic_call_incoming_holo_dark.png diff --git a/res/drawable-xxhdpi/ic_call_missed_holo_dark.png b/res/drawable-xxhdpi/ic_call_missed_holo_dark.png Binary files differnew file mode 100644 index 000000000..8919fd3c9 --- /dev/null +++ b/res/drawable-xxhdpi/ic_call_missed_holo_dark.png diff --git a/res/drawable-xxhdpi/ic_call_outgoing_holo_dark.png b/res/drawable-xxhdpi/ic_call_outgoing_holo_dark.png Binary files differnew file mode 100644 index 000000000..192bbf6a3 --- /dev/null +++ b/res/drawable-xxhdpi/ic_call_outgoing_holo_dark.png diff --git a/res/layout/group_account_header_horizontal.xml b/res/layout/group_account_header_horizontal.xml index b074206bf..f70633e35 100644 --- a/res/layout/group_account_header_horizontal.xml +++ b/res/layout/group_account_header_horizontal.xml @@ -18,6 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@drawable/list_section_divider_holo_custom" android:orientation="horizontal"> <TextView diff --git a/res/layout/group_account_header_vertical.xml b/res/layout/group_account_header_vertical.xml index c5b9d76b7..1309dd052 100644 --- a/res/layout/group_account_header_vertical.xml +++ b/res/layout/group_account_header_vertical.xml @@ -18,10 +18,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginLeft="?attr/list_item_padding_left" - android:layout_marginRight="?attr/list_item_padding_right" - android:layout_marginStart="?attr/list_item_padding_left" - android:layout_marginEnd="?attr/list_item_padding_right" android:paddingBottom="6dip" android:background="@drawable/list_section_divider_holo_custom" android:gravity="center_vertical" diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml index fc0fcd34d..94c72d06d 100755 --- a/res/layout/group_browse_list_item.xml +++ b/res/layout/group_browse_list_item.xml @@ -36,6 +36,12 @@ android:paddingEnd="@dimen/group_list_padding" android:minHeight="@dimen/detail_min_line_item_height" > + <View + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="@color/secondary_header_separator_color" /> + <include android:id="@+id/group_list_header" layout="@layout/group_browse_list_account_header" diff --git a/res/layout/pick_calls_item.xml b/res/layout/pick_calls_item.xml index 53f98c1d6..e3d120f3a 100644 --- a/res/layout/pick_calls_item.xml +++ b/res/layout/pick_calls_item.xml @@ -28,117 +28,93 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:minHeight="?android:attr/listPreferredItemHeight" - android:paddingTop="3dip" - android:paddingBottom="3dip" - > - <LinearLayout - android:layout_width="60dip" - android:layout_weight="0" - android:layout_height="match_parent" - android:orientation="vertical" - android:gravity="center_horizontal"> - - <ImageView android:id="@+id/call_type_icon" - android:layout_width="wrap_content" - android:layout_weight="1" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:layout_marginStart="4dip"/> + android:minHeight="72dp" + android:descendantFocusability="blocksDescendants"> - <TextView android:id="@+id/label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textStyle="bold"/> - </LinearLayout> + <CheckBox + android:id="@+id/pick_contact_check" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dip" + android:layout_marginEnd="8dip" + android:layout_gravity="center_vertical" + android:clickable="false" /> <LinearLayout - android:layout_width="wrap_content" + android:layout_width="0dp" + android:layout_height="wrap_content" android:layout_weight="1" - android:layout_height="match_parent" + android:layout_gravity="center_vertical" android:orientation="vertical"> + <TextView + android:id="@+id/name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@android:style/TextAppearance.Material.Subhead" + android:singleLine="true" /> + <LinearLayout - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" android:orientation="horizontal"> - <TextView android:id="@+id/number" + <TextView + android:id="@+id/subscription" android:layout_width="wrap_content" - android:layout_weight="1" android:layout_height="wrap_content" + android:layout_marginEnd="4dip" + android:textAppearance="@android:style/TextAppearance.Material.Caption" + android:textSize="12sp" android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - /> + android:ellipsize="marquee" /> - <TextView android:id="@+id/line1" + <TextView + android:id="@+id/label" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceSmall" + android:textAppearance="@android:style/TextAppearance.Material.Caption" android:singleLine="true" - /> + android:ellipsize="marquee" /> - <TextView android:id="@+id/subscription" - android:layout_width="wrap_content" - android:layout_weight="0" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:singleLine="true" - /> </LinearLayout> + <LinearLayout - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" android:orientation="horizontal"> - <TextView android:id="@+id/duration" + <ImageView + android:id="@+id/call_type_icon" android:layout_width="wrap_content" - android:layout_weight="1" android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:singleLine="true" - /> + android:layout_marginEnd="4dip" + android:layout_gravity="center_vertical" /> - <TextView android:id="@+id/date" - android:layout_weight="0" + + <TextView + android:id="@+id/call_date" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:singleLine="true" - /> + android:layout_gravity="center_vertical" + android:textAppearance="@android:style/TextAppearance.Material.Caption" + android:singleLine="true" /> </LinearLayout> + </LinearLayout> - <View android:id="@+id/divider" - android:layout_weight="0" - android:layout_width="1px" - android:layout_height="match_parent" - android:layout_marginTop="5dip" - android:layout_marginBottom="5dip" - android:layout_marginStart="11dip" - /> + <TextView android:id="@+id/duration" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginStart="4dip" + android:layout_marginEnd="8dip" + android:textAppearance="@android:style/TextAppearance.Material.Body1" + android:singleLine="true" /> - <CheckBox - android:layout_weight="0" - android:id="@+id/pick_contact_check" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="10dip" - android:layout_centerVertical="true" - android:focusable="false" - android:clickable="false"> - </CheckBox> </LinearLayout> diff --git a/res/layout/pick_contact.xml b/res/layout/pick_contact.xml deleted file mode 100644 index 6da5f29a8..000000000 --- a/res/layout/pick_contact.xml +++ /dev/null @@ -1,100 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - <LinearLayout - android:id="@+id/search_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - style="@android:style/ButtonBar"> - - <EditText - android:id="@+id/search_field" - android:layout_height="wrap_content" - android:layout_width="0dip" - android:layout_weight="1.0" - android:layout_marginStart="5dip" - android:layout_marginEnd="5dip" - android:singleLine="true" - android:ellipsize="end" - android:inputType="textNoSuggestions" - android:imeOptions="actionDone" - android:hint="@string/search_bar_hint" - android:drawableStart="@drawable/ic_ab_search" - android:freezesText="true" - /> - <TextView android:id="@+id/select_all_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerVertical="true" - android:layout_marginEnd="5dip" - android:textAppearance="?android:attr/textAppearanceLarge" - android:singleLine="true" - android:text="@string/select_all" - /> - <CheckBox - android:id="@+id/select_all_check" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginEnd="5dip" - /> - </LinearLayout> - - <ListView android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="1.0" - android:fastScrollEnabled="true" - android:id="@android:id/list"> - </ListView> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - style="@android:style/ButtonBar"> - - <Button android:id="@+id/btn_ok" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:text="@string/btn_ok" - /> - - <Button android:id="@+id/btn_cancel" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:text="@string/btn_cancel" - /> - </LinearLayout> -</LinearLayout> diff --git a/res/layout/pick_contact_item.xml b/res/layout/pick_contact_item.xml index 6d9142b32..57569e6f5 100644 --- a/res/layout/pick_contact_item.xml +++ b/res/layout/pick_contact_item.xml @@ -27,49 +27,18 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeight" - android:paddingTop="3dip" - android:paddingBottom="3dip" - > - <ImageView android:layout_width="@dimen/contact_browser_list_item_photo_size" - android:layout_height="@dimen/contact_browser_list_item_photo_size" - android:layout_marginStart="10dip" - android:layout_marginEnd="5dip" - android:layout_marginTop="5dip" - android:visibility="gone" - android:id="@+id/pick_contact_photo"/> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toEndOf="@id/pick_contact_photo" - android:layout_marginStart="10dip" - android:layout_marginEnd="50dip" - android:layout_marginTop="5dip" - android:textAppearance="?android:attr/textAppearanceLarge" - android:id="@+id/pick_contact_name"> - </TextView> - <TextView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_below="@id/pick_contact_name" - android:layout_marginStart="10dip" - android:layout_marginBottom="5dip" - android:textAppearance="?android:attr/textAppearanceSmall" - android:id="@+id/pick_contact_number" - android:singleLine="true"> - </TextView> - <CheckBox - android:id="@+id/pick_contact_check" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="10dip" - android:layout_centerVertical="true" - android:layout_alignParentEnd="true" - android:focusable="false" - android:clickable="false"> - </CheckBox> -</RelativeLayout> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:minHeight="?android:attr/listPreferredItemHeight" + android:descendantFocusability="blocksDescendants"> + + <com.android.contacts.common.list.ContactListItemView + android:id="@+id/contact" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginEnd="8dip" + android:layout_gravity="center_vertical" /> + +</FrameLayout> diff --git a/res/menu/multi_contact_picker_options.xml b/res/menu/multi_contact_picker_options.xml new file mode 100644 index 000000000..e7fe7148b --- /dev/null +++ b/res/menu/multi_contact_picker_options.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The CyanogenMod 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. +--> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/done" + android:icon="@drawable/ic_done_wht_24dp" + android:title="@string/menu_done" + android:showAsAction="always" /> + <item android:id="@+id/select_all_check" + android:title="@string/select_all" + android:showAsAction="never" + android:checkable="true" /> +</menu> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 17c01e14b..9a0dc8a53 100755 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -241,8 +241,6 @@ <string name="add_account" msgid="8201790677994503186">"添加帐户"</string> <string name="add_new_account" msgid="5748627740680940264">"添加新帐户"</string> <string name="select_all">"全选"</string> - <string name="btn_ok">"确定"</string> - <string name="btn_cancel">"取消"</string> <string name="search_bar_hint">"搜索联系人"</string> <string name="menu_sendViaSMS">通过短信发送联系人</string> <string name="deleteConfirmation_title">"要删除联系人吗?"</string> @@ -255,7 +253,6 @@ <string name="import_sim_contacts_message">"正在导入..."</string> <!-- Import from sim card --> <string name="import_finish">"导入完成"</string> - <string name="import_stop">"导入停止"</string> <string name="too_many_contacts_add_to_group">联系人过多,应该少于<xliff:g id="count">%d</xliff:g>个</string> <!-- add for MemoryStatusActivity --> <string name="menu_memory_status">"存储器状态"</string> diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index f66be16c7..f6db43b67 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -225,8 +225,6 @@ <string name="add_account" msgid="8201790677994503186">"新增帳戶"</string> <string name="add_new_account" msgid="5748627740680940264">"新增帳戶"</string> <string name="select_all">"全選"</string> - <string name="btn_ok">"確定"</string> - <string name="btn_cancel">"取消"</string> <string name="menu_sendViaSMS">通過簡訊發送聯絡人</string> <string name="deleteConfirmation_title">"要刪除聯絡人嗎?"</string> <string name="importConfirmation_title">"要導入聯絡人嗎?"</string> @@ -239,7 +237,6 @@ <string name="import_sim_contacts_message">"正在導入..."</string> <!-- Import from sim card --> <string name="import_finish">導入完成</string> - <string name="import_stop">導入停止</string> <string name="menu_export_database" msgid="2659719297530170820">"匯出資料庫檔案"</string> <string name="action_menu_add_new_contact_button" msgid="3180222523336380017">"新增聯絡人"</string> <string name="expanding_entry_card_view_see_more" msgid="3779194067124758079">"顯示更多"</string> diff --git a/res/values/config.xml b/res/values/config.xml new file mode 100755 index 000000000..64e091d75 --- /dev/null +++ b/res/values/config.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <!-- CMCC feature --> + <bool name="config_show_quick_call_button">true</bool> + <bool name="config_show_sms_import_dialog">true</bool> +</resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index ec81912a5..3ba576e3a 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -671,23 +671,32 @@ <!-- Button label to prompt the user to add another account (when there are already existing accounts on the device) [CHAR LIMIT=30] --> <string name="add_new_account">Add new account</string> <string name="select_all">All</string> - <string name="btn_ok">Ok</string> - <string name="btn_cancel">Cancel</string> <string name="menu_sendViaSMS">Send contact via SMS</string> - <!-- Gray hint displayed in the search field in Contacts when empty --> - <string name="search_bar_hint">Search contacts</string> <!-- Confirmation dialog title after users selects to delete a contact. [CHAR LIMIT=25]--> <string name="deleteConfirmation_title">Delete contact?</string> <string name="import_sim_contacts_title">Import sim contacts</string> - <string name="import_sim_contacts_message">Importing sim contacts ...</string> - <string name="ContactMultiImportConfirmation">These contacts will be imported.</string> + <string name="import_sim_contacts_message">Importing sim contacts\u2026</string> + <plurals name="ContactMultiImportConfirmation"> + <item quantity="one">%d contact will be imported.</item> + <item quantity="other">%d contacts will be imported.</item> + </plurals> <string name="import_finish">"Import finished"</string> - <string name="import_stop">"Import stopped"</string> + <plurals name="import_progress"> + <item quantity="one">%d contact imported</item> + <item quantity="other">%d contacts imported</item> + </plurals> + <plurals name="contacts_selected"> + <item quantity="one">%d contact selected</item> + <item quantity="other">%d contacts selected</item> + </plurals> <string name="too_many_contacts_add_to_group">Too many contacts, that should be less than <xliff:g id="count">%d</xliff:g></string> <!-- Multi Delete Contacts related strings --> - <string name="ContactMultiDeleteConfirmation">These contacts will be deleted.</string> + <plurals name="ContactMultiDeleteConfirmation"> + <item quantity="one">%d contact will be deleted.</item> + <item quantity="other">%d contacts will be deleted.</item> + </plurals> <string name="delete_contacts_title">Delete Contacts</string> - <string name="delete_contacts_message">Deleting Contacts ...</string> + <string name="delete_contacts_message">Deleting Contacts\u2026</string> <string name="delete_termination">"Delete is termination"</string> <!-- Menu item shown only when the special debug mode is enabled, which is used to send all contacts database files via email. [CHAR LIMI=NONE] --> <string name="menu_export_database">Export database files</string> diff --git a/res/values/styles.xml b/res/values/styles.xml index 987f42a9f..3b0089ef1 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -101,6 +101,7 @@ <item name="list_item_presence_icon_margin">4dip</item> <item name="list_item_presence_icon_size">16dip</item> <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item> + <item name="list_item_quick_call_size">48dip</item> <item name="list_item_profile_photo_size">70dip</item> <item name="list_item_prefix_highlight_color">@color/people_app_theme_color</item> <item name="list_item_background_color">@color/list_item_pinned_header_color</item> diff --git a/src/com/android/contacts/editor/MultiPickContactActivity.java b/src/com/android/contacts/activities/MultiPickContactActivity.java index 4a65bc28a..64081a56e 100755 --- a/src/com/android/contacts/editor/MultiPickContactActivity.java +++ b/src/com/android/contacts/activities/MultiPickContactActivity.java @@ -27,8 +27,9 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.android.contacts.editor; +package com.android.contacts.activities; +import android.app.ActionBar; import android.app.AlertDialog; import android.app.Dialog; import android.app.ListActivity; @@ -38,47 +39,44 @@ import android.accounts.AccountManager; import android.content.AsyncQueryHandler; import android.content.BroadcastReceiver; import android.content.ContentResolver; +import android.content.ContentProviderOperation; import android.content.ContentValues; import android.content.Context; -import android.content.ContentProviderOperation; import android.content.DialogInterface; -import android.content.IntentFilter; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.content.IntentFilter; import android.content.OperationApplicationException; import android.database.Cursor; -import android.graphics.drawable.Drawable; import android.net.Uri; -import android.net.Uri.Builder; import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.provider.CallLog; -import android.provider.ContactsContract; import android.provider.CallLog.Calls; +import android.provider.ContactsContract; +import android.provider.ContactsContract.InternalContactCounts; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.telephony.SubscriptionManager; import android.text.Editable; import android.text.format.DateUtils; import android.text.TextUtils; -import android.text.TextWatcher; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; @@ -88,10 +86,11 @@ import android.widget.CursorAdapter; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; +import android.widget.SearchView; +import android.widget.SectionIndexer; import android.widget.TextView; import android.widget.Toast; -import com.android.contacts.activities.PeopleActivity; import com.android.contacts.R; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; @@ -99,18 +98,22 @@ import com.android.contacts.common.SimContactsConstants; import com.android.contacts.common.SimContactsOperation; import com.android.contacts.common.list.AccountFilterActivity; import com.android.contacts.common.list.ContactListFilter; +import com.android.contacts.common.list.ContactListItemView; +import com.android.contacts.common.list.ContactsSectionIndexer; +import com.android.contacts.common.list.DefaultContactListAdapter; import com.android.contacts.common.MoreContactUtils; import com.android.contacts.common.model.account.SimAccountType; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; public class MultiPickContactActivity extends ListActivity implements - View.OnClickListener, TextView.OnEditorActionListener, - OnTouchListener, TextWatcher { + TextView.OnEditorActionListener, View.OnTouchListener, + SearchView.OnQueryTextListener, SearchView.OnCloseListener, + View.OnFocusChangeListener, DialogInterface.OnClickListener, + DialogInterface.OnKeyListener { private final static String TAG = "MultiPickContactActivity"; private final static boolean DEBUG = true; @@ -119,13 +122,32 @@ public class MultiPickContactActivity extends ListActivity implements static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, // 0 Contacts.DISPLAY_NAME_PRIMARY, // 1 - Contacts.DISPLAY_NAME_ALTERNATIVE, // 2 - Contacts.PHOTO_ID, // 3 - Contacts.LOOKUP_KEY, // 4 - RawContacts.ACCOUNT_TYPE, // 5 - RawContacts.ACCOUNT_NAME, // 6 - Contacts.NAME_RAW_CONTACT_ID, - Contacts.PHOTO_THUMBNAIL_URI + Contacts.PHOTO_ID, // 2 + Contacts.LOOKUP_KEY, // 3 + RawContacts.ACCOUNT_TYPE, // 4 + RawContacts.ACCOUNT_NAME, // 5 + Contacts.NAME_RAW_CONTACT_ID, // 6 + Contacts.PHOTO_THUMBNAIL_URI // 7 + }; + + static final String[] PHONES_PROJECTION = new String[] { + Data.CONTACT_ID, // 0 + Data.DISPLAY_NAME, // 1 + Data.PHOTO_ID, // 2 + Data.LOOKUP_KEY, // 3 + Phone._ID, // 4 + Phone.TYPE, // 5 + Phone.LABEL, // 6 + Phone.NUMBER, // 7 + }; + + static final String[] EMAILS_PROJECTION = new String[] { + Data.CONTACT_ID, // 0 + Data.DISPLAY_NAME, // 1 + Data.PHOTO_ID, // 2 + Data.LOOKUP_KEY, // 3 + Email._ID, // 4 + Email.ADDRESS // 5 }; static final String[] CALL_LOG_PROJECTION = new String[] { @@ -136,61 +158,47 @@ public class MultiPickContactActivity extends ListActivity implements Calls.TYPE, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE, - Calls.CACHED_NUMBER_LABEL, Calls.PHONE_ACCOUNT_ID + Calls.CACHED_NUMBER_LABEL, + Calls.PHONE_ACCOUNT_ID, + Calls.GEOCODED_LOCATION, }; static final String CONTACTS_SELECTION = Contacts.IN_VISIBLE_GROUP + "=1"; - static final String[] PHONES_PROJECTION = new String[] { - Phone._ID, // 0 - Phone.TYPE, // 1 - Phone.LABEL, // 2 - Phone.NUMBER, // 3 - Phone.DISPLAY_NAME, // 4 - Phone.CONTACT_ID // 5 - }; - static final String PHONES_SELECTION = RawContacts.ACCOUNT_TYPE + "<>?"; static final String[] PHONES_SELECTION_ARGS = { SimContactsConstants.ACCOUNT_TYPE_SIM }; - static final String[] EMAILS_PROJECTION = new String[] { - Email._ID, - Phone.DISPLAY_NAME, - Email.ADDRESS, - }; - - private static final int SUMMARY_ID_COLUMN_INDEX = 0; - private static final int SUMMARY_DISPLAY_NAME_PRIMARY_COLUMN_INDEX = 1; - private static final int SUMMARY_DISPLAY_NAME_ALTERNATIVE_COLUMN_INDEX = 2; - private static final int SUMMARY_PHOTO_ID_COLUMN_INDEX = 3; - private static final int SUMMARY_LOOKUP_KEY_COLUMN_INDEX = 4; - private static final int SUMMARY_ACCOUNT_TYPE = 5; - private static final int SUMMARY_ACCOUNT_NAME = 6; - - //call log column - private static final int ID_COLUMN_INDEX = 0; - private static final int NUMBER_COLUMN_INDEX = 1; - private static final int DATE_COLUMN_INDEX = 2; - private static final int DURATION_COLUMN_INDEX = 3; - private static final int CALL_TYPE_COLUMN_INDEX = 4; - private static final int CALLER_NAME_COLUMN_INDEX = 5; - private static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 6; - private static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 7; - private static final int PHONE_SUBSCRIPTION_COLUMN_INDEX = 8; - - private static final int PHONE_COLUMN_ID = 0; - private static final int PHONE_COLUMN_TYPE = 1; - private static final int PHONE_COLUMN_LABEL = 2; - private static final int PHONE_COLUMN_NUMBER = 3; - private static final int PHONE_COLUMN_DISPLAY_NAME = 4; - private static final int PHONE_COLUMN_CONTACT_ID = 5; - - private static final int EMAIL_COLUMN_ID = 0; - private static final int EMAIL_COLUMN_DISPLAY_NAME = 1; - private static final int EMAIL_COLUMN_ADDRESS = 2; + public static final int CONTACT_COLUMN_ID = 0; + public static final int CONTACT_COLUMN_DISPLAY_NAME = 1; + public static final int CONTACT_COLUMN_PHOTO_ID = 2; + public static final int CONTACT_COLUMN_LOOKUP_KEY = 3; + // contacts query specific columns + public static final int CONTACT_COLUMN_ACCOUNT_TYPE = 4; + public static final int CONTACT_COLUMN_ACCOUNT_NAME = 5; + public static final int CONTACT_COLUMN_RAW_CONTACT_ID = 6; + public static final int CONTACT_COLUMN_PHOTO_URI = 7; + // phone query specific columns + public static final int PHONE_COLUMN_ID = 4; + public static final int PHONE_COLUMN_TYPE = 5; + public static final int PHONE_COLUMN_LABEL = 6; + public static final int PHONE_COLUMN_NUMBER = 7; + // email query specific columns + public static final int EMAIL_COLUMN_ID = 4; + public static final int EMAIL_COLUMN_ADDRESS = 5; + + public static final int CALLLOG_COLUMN_ID = 0; + public static final int CALLLOG_COLUMN_NUMBER = 1; + public static final int CALLLOG_COLUMN_DATE = 2; + public static final int CALLLOG_COLUMN_DURATION = 3; + public static final int CALLLOG_COLUMN_CALL_TYPE = 4; + public static final int CALLLOG_COLUMN_CALLER_NAME = 5; + public static final int CALLLOG_COLUMN_CALLER_NUMBERTYPE = 6; + public static final int CALLLOG_COLUMN_CALLER_NUMBERLABEL = 7; + public static final int CALLLOG_COLUMN_PHONE_ACCOUNT = 8; + public static final int CALLLOG_COLUMN_CALLER_LOCATION = 9; private static final int QUERY_TOKEN = 42; private static final int MODE_MASK_SEARCH = 0x80000000; @@ -206,37 +214,45 @@ public class MultiPickContactActivity extends ListActivity implements private static final int MODE_SEARCH_CALL = MODE_DEFAULT_CALL | MODE_MASK_SEARCH; private static final int MODE_SEARCH_SIM = MODE_DEFAULT_SIM | MODE_MASK_SEARCH; private static final int DIALOG_DEL_CALL = 1; - public static final int ACTION_ADD_GROUP_MEMBER = 0; - public static final int ACTION_MOVE_GROUP_MEMBER = 1; - public static final int ACTION_DEFAULT_VALUE = -1; - public static final String ADD_GROUP_MEMBERS= "add_group_members"; + public static final String ADD_GROUP_MEMBERS = "add_group_members"; + + public static final String ACTION_MULTI_PICK = "com.android.contacts.action.MULTI_PICK"; + static final String ACTION_MULTI_PICK_EMAIL = "com.android.contacts.action.MULTI_PICK_EMAIL"; + static final String ACTION_MULTI_PICK_CALL = "com.android.contacts.action.MULTI_PICK_CALL"; + static final String ACTION_MULTI_PICK_SIM = "com.android.contacts.action.MULTI_PICK_SIM"; + + public static final String EXTRA_IS_SELECT_ALL_DISALLOWED = "is_select_all_disallowed"; + public static final String EXTRA_SELECT_CALLLOG = "selectcalllog"; + public static final String EXTRA_NOT_SHOW_SIM_FLAG = "not_sim_show"; + public static final String EXTRA_GROUP_ID = "group_id"; + public static final String EXTRA_GROUP_ACTION = "group_action"; - public static final String ADD_MOVE_GROUP_MEMBER_KEY = "add_move_group_member"; - public static final String KEY_GROUP_ID = "group_id"; + public static final int GROUP_ACTION_ADD_MEMBER = 0; + public static final int GROUP_ACTION_MOVE_MEMBER = 1; + public static final int GROUP_ACTION_NONE = -1; private ContactItemListAdapter mAdapter; private QueryHandler mQueryHandler; private Bundle mChoiceSet; - private Bundle mBackupChoiceSet; - private EditText mSearchEditor; - private Button mOKButton; - private Button mCancelButton; - private TextView mSelectAllLabel; - private CheckBox mSelectAllCheckBox; + + private ActionBar mActionBar; + private SearchView mSearchView; + private ViewGroup mSearchViewContainer; + private int mMode; private boolean mSelectCallLog; - public static final String KEY_SELECT_CALLLOG = "selectcalllog"; + private boolean mSearchUiVisible = false; - private ArrayList<Long> mGroupIds= new ArrayList<Long>(); + private ArrayList<Long> mGroupIds = new ArrayList<Long>(); private ProgressDialog mProgressDialog; private SimContactsOperation mSimContactsOperation; - private Context mContext; - private Intent mIntent; private AccountManager accountManager; + private CharSequence[] mLabelArray; + private AccountManager mAccountManager; - private static final String[] COLUMN_NAMES = new String[] { + private static final String[] SIM_COLUMN_NAMES = new String[] { "name", "number", "emails", @@ -250,10 +266,6 @@ public class MultiPickContactActivity extends ListActivity implements private static final int SIM_COLUMN_ANRS = 3; private static final int SIM_COLUMN_ID = 4; - private Drawable mDrawableIncoming; - private Drawable mDrawableOutgoing; - private Drawable mDrawableMissed; - /** * control of whether show the contacts in SIM card, if intent has this * flag,not show. @@ -266,46 +278,35 @@ public class MultiPickContactActivity extends ListActivity implements private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // TODO Auto-generated method stub if (intent.getAction().equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { updateContent(); // If now is airplane mode, should cancel import sim contacts - if (isPickSim() && MoreContactUtils.isAPMOnAndSIMPowerDown(mContext)) { + if (isPickSim() && MoreContactUtils.isAPMOnAndSIMPowerDown(context)) { cancelSimContactsImporting(); } } } }; - /** Called when the activity is first created. */ + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); String action = intent.getAction(); - boolean isContact = intent.getBooleanExtra( - SimContactsConstants.IS_CONTACT, false); + boolean isContact = intent.getBooleanExtra(SimContactsConstants.IS_CONTACT, false); + if (Intent.ACTION_DELETE.equals(action)) { mMode = MODE_DEFAULT_CONTACT; setTitle(R.string.menu_deleteContact); } else if (SimContactsConstants.ACTION_MULTI_PICK.equals(action)) { - if (!isContact) { - mMode = MODE_DEFAULT_PHONE; - } else { - mMode = MODE_DEFAULT_CONTACT; - } + mMode = isContact ? MODE_DEFAULT_CONTACT : MODE_DEFAULT_PHONE; } else if (SimContactsConstants.ACTION_MULTI_PICK_EMAIL.equals(action)) { mMode = MODE_DEFAULT_EMAIL; } else if (SimContactsConstants.ACTION_MULTI_PICK_CALL.equals(action)) { mMode = MODE_DEFAULT_CALL; setTitle(R.string.delete_call_title); - mDrawableIncoming = getResources().getDrawable( - R.drawable.ic_call_log_list_incoming_call); - mDrawableOutgoing = getResources().getDrawable( - R.drawable.ic_call_log_list_outgoing_call); - mDrawableMissed = getResources().getDrawable( - R.drawable.ic_call_log_list_missed_call); - if (intent.getBooleanExtra(KEY_SELECT_CALLLOG, false)) { + if (intent.getBooleanExtra(EXTRA_SELECT_CALLLOG, false)) { mSelectCallLog = true; setTitle(R.string.select_call_title); } @@ -313,15 +314,19 @@ public class MultiPickContactActivity extends ListActivity implements mMode = MODE_DEFAULT_SIM; } - setContentView(R.layout.pick_contact); mChoiceSet = new Bundle(); mAdapter = new ContactItemListAdapter(this); getListView().setAdapter(mAdapter); mQueryHandler = new QueryHandler(this); mSimContactsOperation = new SimContactsOperation(this); - mContext = getApplicationContext(); - accountManager = AccountManager.get(mContext); - initResource(); + mAccountManager = AccountManager.get(this); + + mActionBar = getActionBar(); + mActionBar.setHomeButtonEnabled(true); + mActionBar.setDisplayHomeAsUpEnabled(true); + mActionBar.setDisplayShowTitleEnabled(true); + inflateSearchView(); + startQuery(); //register receiver. IntentFilter filter = new IntentFilter(); @@ -329,92 +334,227 @@ public class MultiPickContactActivity extends ListActivity implements registerReceiver(mBroadcastReceiver, filter); } + private void inflateSearchView() { + LayoutInflater inflater = LayoutInflater.from(mActionBar.getThemedContext()); + mSearchViewContainer = (ViewGroup) inflater.inflate(R.layout.custom_action_bar, null); + mSearchView = (SearchView) mSearchViewContainer.findViewById(R.id.search_view); + + if (isPickCall() || isPickSim()) { + mSearchView.setVisibility(View.GONE); + return; + } + + // In order to make the SearchView look like "shown via search menu", we need to + // manually setup its state. See also DialtactsActivity.java and ActionBarAdapter.java. + mSearchView.setIconifiedByDefault(true); + mSearchView.setQueryHint(getString(R.string.hint_findContacts)); + mSearchView.setIconified(false); + mSearchView.setFocusable(true); + + mSearchView.setOnQueryTextListener(this); + mSearchView.setOnCloseListener(this); + mSearchView.setOnQueryTextFocusChangeListener(this); + + mActionBar.setCustomView(mSearchViewContainer, new ActionBar.LayoutParams( + ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.WRAP_CONTENT)); + mActionBar.setDisplayShowCustomEnabled(true); + + configureSearchMode(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { - // Let the system ignore the menu key when the activity is foreground. + MenuInflater inflater = getMenuInflater(); + + inflater.inflate(R.menu.search_menu, menu); + inflater.inflate(R.menu.multi_contact_picker_options, menu); + + final MenuItem selectAllItem = menu.findItem(R.id.select_all_check); + selectAllItem.setVisible(!mSearchUiVisible); + selectAllItem.setChecked(mChoiceSet.size() == mAdapter.getCount()); + + final MenuItem doneItem = menu.findItem(R.id.done); + doneItem.setVisible(!mChoiceSet.isEmpty()); + + final MenuItem searchItem = menu.findItem(R.id.menu_search); + searchItem.setVisible(!mSearchUiVisible && !isPickCall() && !isPickSim()); + + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_search: + mSearchUiVisible = !mSearchUiVisible; + if (!mSearchUiVisible) { + exitSearchMode(); + } else { + configureSearchMode(); + } + return true; + case R.id.select_all_check: + selectAll(!item.isChecked()); + return true; + case R.id.done: + if (isSearchMode()) { + exitSearchMode(); + } + if (mMode == MODE_DEFAULT_CONTACT) { + if (SimContactsConstants.ACTION_MULTI_PICK.equals(getIntent().getAction())) { + if (mChoiceSet.size() > MAX_CONTACTS_NUM_TO_SELECT_ONCE) { + String text = getString(R.string.too_many_contacts_add_to_group, + MAX_CONTACTS_NUM_TO_SELECT_ONCE); + Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); + } else { + int memberAction = getIntent().getIntExtra(EXTRA_GROUP_ACTION, + GROUP_ACTION_NONE); + switch (memberAction) { + case GROUP_ACTION_ADD_MEMBER: + setResult(RESULT_OK, new Intent().putExtras(mChoiceSet)); + finish(); + break; + case GROUP_ACTION_MOVE_MEMBER: + String account = getIntent().getStringExtra( + SimContactsConstants.ACCOUNT_TYPE); + long groupId = getIntent().getLongExtra(EXTRA_GROUP_ID, -1); + showGroupSelectionList(account, groupId); + break; + default: + setResultAndFinish(); + break; + } + } + } else if (mChoiceSet.size() > 0) { + showDialog(R.id.dialog_delete_contact_confirmation); + } + } else if (mMode == MODE_DEFAULT_PHONE) { + setResultAndFinish(); + } else if (mMode == MODE_DEFAULT_SIM) { + if (mChoiceSet.size() > 0) { + showDialog(R.id.dialog_import_sim_contact_confirmation); + } + } else if (mMode == MODE_DEFAULT_EMAIL) { + setResultAndFinish(); + } else if (mMode == MODE_DEFAULT_CALL) { + if (mChoiceSet.size() > 0) { + if (mSelectCallLog) { + setResultAndFinish(); + } else { + showDialog(DIALOG_DEL_CALL); + } + } + } + return true; + case android.R.id.home: + finish(); + return true; + } return false; } - private boolean isSearchMode() { - return (mMode & MODE_MASK_SEARCH) == MODE_MASK_SEARCH; + @Override + public void onBackPressed() { + if (mSearchUiVisible) { + exitSearchMode(); + } else { + super.onBackPressed(); + } } - private boolean initSearchText(){ - String s = getIntent().getStringExtra(PeopleActivity.EDITABLE_KEY); - if (s != null && s.trim().length() > 0) { - mSearchEditor.setText(s.trim()); - enterSearchMode(); - doFilter(mSearchEditor.getText()); - return true; + @Override + public boolean onQueryTextSubmit(String query) { + updateState(query); + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + updateState(newText); + return true; + } + + @Override + public boolean onClose() { + if (!TextUtils.isEmpty(mSearchView.getQuery())) { + mSearchView.setQuery(null, true); } - return false; + return true; } - private void initResource() { - mOKButton = (Button) findViewById(R.id.btn_ok); - mOKButton.setOnClickListener(this); - mOKButton.setText(getOKString()); - mCancelButton = (Button) findViewById(R.id.btn_cancel); - mCancelButton.setOnClickListener(this); - mSearchEditor = ((EditText) findViewById(R.id.search_field)); - mSearchEditor.addTextChangedListener(this); - mSearchEditor.setOnClickListener(this); - mSearchEditor.setOnTouchListener(this); - mSearchEditor.setOnEditorActionListener(this); - if (isPickCall() || isPickSim()) { - mSearchEditor.setVisibility(View.INVISIBLE); + @Override + public void onFocusChange(View view, boolean hasFocus) { + switch (view.getId()) { + case R.id.search_view: { + if (hasFocus) { + final InputMethodManager imm = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mSearchView.findFocus(), 0); + } + } } - mSelectAllCheckBox = (CheckBox) findViewById(R.id.select_all_check); - mSelectAllCheckBox.setOnClickListener(this); - mSelectAllLabel = (TextView) findViewById(R.id.select_all_label); + } + + private void updateState(String query) { + if (!TextUtils.isEmpty(query)) { + if (!isSearchMode()) { + enterSearchMode(); + } + } else if (isSearchMode()) { + exitSearchMode(); + } + doFilter(query); + } + + private void setResultAndFinish() { + Intent intent = new Intent(); + Bundle bundle = new Bundle(); + bundle.putBundle(SimContactsConstants.RESULT_KEY, mChoiceSet); + intent.putExtras(bundle); + setResult(RESULT_OK, intent); + finish(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { hideSoftKeyboard(); - CheckBox checkBox = (CheckBox) v.findViewById(R.id.pick_contact_check); - boolean isChecked = !checkBox.isChecked(); - checkBox.setChecked(isChecked); - if (isChecked) { + + ContactItemCache cache = (ContactItemCache) v.getTag(); + String key = String.valueOf(cache.id); + + if (!mChoiceSet.containsKey(key)) { String[] value = null; - ContactItemCache cache = (ContactItemCache) v.getTag(); if (isPickContact()) { value = new String[] { - cache.lookupKey, String.valueOf(cache.id), - String.valueOf(cache.nameRawContactId), - cache.photoUri, cache.name + cache.lookupKey, String.valueOf(cache.id), + String.valueOf(cache.nameRawContactId), + cache.photoUri, cache.name }; } else if (isPickPhone()) { value = new String[] { - cache.name, cache.number, cache.type, - cache.label, cache.contact_id + cache.name, cache.number, cache.type, + cache.label, cache.contact_id }; } else if (isPickEmail()) { value = new String[] { - cache.name, cache.email + cache.name, cache.email }; } else if (isPickSim()) { value = new String[] { - cache.name, cache.number, cache.email, cache.anrs + cache.name, cache.number, cache.email, cache.anrs + }; + } else if (isPickCall() && mSelectCallLog) { + value = new String[] { + cache.name, cache.number }; - } else if (isPickCall()) { - if (mSelectCallLog) { - value = new String[] { - cache.name, cache.number - }; - } - } - mChoiceSet.putStringArray(String.valueOf(id), value); - if (!isSearchMode()) { - if (mChoiceSet.size() == mAdapter.getCount()) { - mSelectAllCheckBox.setChecked(true); - } } + mChoiceSet.putStringArray(key, value); } else { - mChoiceSet.remove(String.valueOf(id)); - mSelectAllCheckBox.setChecked(false); + mChoiceSet.remove(key); } - mOKButton.setText(getOKString()); + + updateActionBar(); + mAdapter.notifyDataSetChanged(); } @Override @@ -422,7 +562,7 @@ public class MultiPickContactActivity extends ListActivity implements switch (keyCode) { case KeyEvent.KEYCODE_BACK: { if (isSearchMode()) { - exitSearchMode(false); + exitSearchMode(); return true; } } @@ -430,83 +570,82 @@ public class MultiPickContactActivity extends ListActivity implements return super.onKeyDown(keyCode, event); } - private String getOKString() { - if (0 == mChoiceSet.size()) { - mOKButton.setEnabled(false); - } else { - mOKButton.setEnabled(true); + private void updateActionBar() { + String countTitle = null; + if (!mChoiceSet.isEmpty()) { + countTitle = getResources().getQuantityString(R.plurals.contacts_selected, + mChoiceSet.size(), mChoiceSet.size()); } - - return getString(R.string.btn_ok) + "(" + mChoiceSet.size() + ")"; + mActionBar.setSubtitle(countTitle); + invalidateOptionsMenu(); } - private void backupChoiceSet() { - mBackupChoiceSet = (Bundle) mChoiceSet.clone(); - } - - private void restoreChoiceSet() { - mChoiceSet = mBackupChoiceSet; + private boolean isSearchMode() { + return (mMode & MODE_MASK_SEARCH) == MODE_MASK_SEARCH; } private void enterSearchMode() { mMode |= MODE_MASK_SEARCH; - mSelectAllLabel.setVisibility(View.GONE); - mSelectAllCheckBox.setVisibility(View.GONE); - backupChoiceSet(); + configureSearchMode(); } - private void exitSearchMode(boolean isConfirmed) { + private void exitSearchMode() { + mSearchUiVisible = false; mMode &= ~MODE_MASK_SEARCH; - hideSoftKeyboard(); - mSelectAllLabel.setVisibility(View.VISIBLE); - mSelectAllCheckBox.setVisibility(View.VISIBLE); - if (!isConfirmed) { - restoreChoiceSet(); + configureSearchMode(); + } + + private void configureSearchMode() { + if (mSearchUiVisible) { + mSearchViewContainer.setVisibility(View.VISIBLE); + mSearchView.requestFocus(); + } else { + mSearchViewContainer.setVisibility(View.GONE); + mSearchView.setQuery(null, true); } - mSearchEditor.setText(""); - mOKButton.setText(getOKString()); + mActionBar.setDisplayShowTitleEnabled(!mSearchUiVisible); + updateActionBar(); } + @Override protected Dialog onCreateDialog(int id, Bundle bundle) { switch (id) { - case R.id.dialog_delete_contact_confirmation: { + case R.id.dialog_delete_contact_confirmation: return new AlertDialog.Builder(this) .setTitle(R.string.deleteConfirmation_title) - .setIconAttribute(android.R.attr.alertDialogIcon) - .setMessage(R.string.ContactMultiDeleteConfirmation) + .setMessage(getResources().getQuantityString( + R.plurals.ContactMultiDeleteConfirmation, + mChoiceSet.size(), mChoiceSet.size())) .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, - new DeleteClickListener()).create(); - } - case DIALOG_DEL_CALL: { - return new AlertDialog.Builder(this).setTitle(R.string.title_del_call) - .setIcon(android.R.drawable.ic_dialog_alert).setMessage( - R.string.delete_call_alert).setNegativeButton( - android.R.string.cancel, null).setPositiveButton( - android.R.string.ok, new DeleteClickListener()).create(); - } - case R.id.dialog_import_sim_contact_confirmation: { + .setPositiveButton(android.R.string.ok, this) + .create(); + case DIALOG_DEL_CALL: + return new AlertDialog.Builder(this) + .setTitle(R.string.title_del_call) + .setMessage(R.string.delete_call_alert) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, this) + .create(); + case R.id.dialog_import_sim_contact_confirmation: return new AlertDialog.Builder(this) .setTitle(R.string.importConfirmation_title) - .setIcon(android.R.drawable.ic_dialog_alert) - .setMessage(R.string.ContactMultiImportConfirmation) + .setMessage(getResources().getQuantityString( + R.plurals.ContactMultiImportConfirmation, + mChoiceSet.size(), mChoiceSet.size())) .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, - new DeleteClickListener()).create(); - } - + .setPositiveButton(android.R.string.ok, this) + .create(); } return super.onCreateDialog(id, bundle); } - private class DeleteContactsThread extends Thread - implements OnCancelListener, DialogInterface.OnClickListener { - + private class DeleteContactsThread extends Thread implements + DialogInterface.OnCancelListener, DialogInterface.OnClickListener { boolean mCanceled = false; private String name = null; private String number = null; - final String[] PROJECTION = new String[] { + private final String[] PROJECTION = new String[] { Phone.CONTACT_ID, Phone.NUMBER, Phone.DISPLAY_NAME @@ -515,7 +654,6 @@ public class MultiPickContactActivity extends ListActivity implements private final int COLUMN_NAME = 2; private ArrayList<ContentProviderOperation> mOpsCalls = null; - private ArrayList<ContentProviderOperation> mOpsContacts = null; public DeleteContactsThread() { @@ -523,6 +661,7 @@ public class MultiPickContactActivity extends ListActivity implements @Override public void run() { + final Context context = MultiPickContactActivity.this; final ContentResolver resolver = getContentResolver(); // The mChoiceSet object will change when activity restart, but @@ -532,8 +671,7 @@ public class MultiPickContactActivity extends ListActivity implements Set<String> keySet = choiceSet.keySet(); Iterator<String> it = keySet.iterator(); - android.content.ContentProviderOperation.Builder builder = null; - + ContentProviderOperation.Builder builder = null; ContentProviderOperation cpo = null; // Current contact count we can delete. @@ -556,19 +694,17 @@ public class MultiPickContactActivity extends ListActivity implements } else { uri = Uri.withAppendedPath(Contacts.CONTENT_URI, id); long longId = Long.parseLong(id); - int subscription = - mSimContactsOperation.getSimSubscription(longId); + int subscription = mSimContactsOperation.getSimSubscription(longId); if (subscription == SimContactsConstants.SUB_1 || subscription == SimContactsConstants.SUB_2) { - if (MoreContactUtils.isAPMOnAndSIMPowerDown(mContext)) { + if (MoreContactUtils.isAPMOnAndSIMPowerDown(context)) { break; } ContentValues values = mSimContactsOperation.getSimAccountValues(longId); log("values is : " + values + "; sub is " + subscription); - int result = mSimContactsOperation.delete(values, subscription); - if (result == 0) { + if (mSimContactsOperation.delete(values, subscription) == 0) { mProgressDialog.incrementProgressBy(1); continue; } @@ -584,7 +720,7 @@ public class MultiPickContactActivity extends ListActivity implements if (count % BATCH_DELETE_CONTACT_NUMBER == 0) { batchDelete(); } - count ++; + count++; } batchDelete(); @@ -600,8 +736,8 @@ public class MultiPickContactActivity extends ListActivity implements */ private void batchDelete() { try { - mContext.getContentResolver().applyBatch(CallLog.AUTHORITY, mOpsCalls); - mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, mOpsContacts); + getContentResolver().applyBatch(CallLog.AUTHORITY, mOpsCalls); + getContentResolver().applyBatch(ContactsContract.AUTHORITY, mOpsContacts); mOpsCalls.clear(); mOpsContacts.clear(); } catch (RemoteException e) { @@ -611,168 +747,68 @@ public class MultiPickContactActivity extends ListActivity implements } } + @Override public void onCancel(DialogInterface dialog) { mCanceled = true; Log.d(TAG, "DeleteContactsThread onCancel, progress:" + mProgressDialog.getProgress()); // Give a toast show to tell user delete termination } + @Override public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_NEGATIVE) { mCanceled = true; mProgressDialog.dismiss(); } } - } - private class DeleteClickListener implements DialogInterface.OnClickListener { - public void onClick(DialogInterface dialog, int which) { - CharSequence title = null; - CharSequence message = null; - - if (isPickCall()) { - title = getString(R.string.delete_call_title); - message = getString(R.string.delete_call_message); - } else if (isPickSim()) { - title = getString(R.string.import_sim_contacts_title); - message = getString(R.string.import_sim_contacts_message); - } else { - title = getString(R.string.delete_contacts_title); - message = getString(R.string.delete_contacts_message); - } + @Override + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_SEARCH: + case KeyEvent.KEYCODE_CALL: + return true; + default: + return false; + } + } - Thread thread; - if (isPickSim()) { - thread = new ImportAllSimContactsThread(); - } else { - thread = new DeleteContactsThread(); - } + @Override + public void onClick(DialogInterface dialog, int which) { + CharSequence title = null; + CharSequence message = null; + + if (isPickCall()) { + title = getString(R.string.delete_call_title); + message = getString(R.string.delete_call_message); + } else if (isPickSim()) { + title = getString(R.string.import_sim_contacts_title); + message = getString(R.string.import_sim_contacts_message); + } else { + title = getString(R.string.delete_contacts_title); + message = getString(R.string.delete_contacts_message); + } - DialogInterface.OnKeyListener keyListener = new DialogInterface.OnKeyListener() { - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_SEARCH: - case KeyEvent.KEYCODE_CALL: - return true; - default: - return false; - } - } - }; + Thread thread = isPickSim() + ? new ImportAllSimContactsThread() : new DeleteContactsThread(); - mProgressDialog = new ProgressDialog(MultiPickContactActivity.this); - mProgressDialog.setTitle(title); - mProgressDialog.setMessage(message); - mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, - getString(R.string.btn_cancel), (OnClickListener) thread); - mProgressDialog.setOnCancelListener((OnCancelListener) thread); - mProgressDialog.setOnKeyListener(keyListener); - mProgressDialog.setProgress(0); - mProgressDialog.setMax(mChoiceSet.size()); + mProgressDialog = new ProgressDialog(MultiPickContactActivity.this); + mProgressDialog.setTitle(title); + mProgressDialog.setMessage(message); + mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, + getString(android.R.string.cancel), (DialogInterface.OnClickListener) thread); + mProgressDialog.setOnCancelListener((DialogInterface.OnCancelListener) thread); + mProgressDialog.setOnKeyListener(this); + mProgressDialog.setProgress(0); + mProgressDialog.setMax(mChoiceSet.size()); - // set dialog can not be canceled by touching outside area of - // dialog. - mProgressDialog.setCanceledOnTouchOutside(false); - mProgressDialog.show(); + // set dialog can not be canceled by touching outside area of dialog + mProgressDialog.setCanceledOnTouchOutside(false); + mProgressDialog.show(); - thread.start(); - } - } - - public void onClick(View v) { - int id = v.getId(); - switch (id) { - case R.id.btn_ok: - if (isSearchMode()) { - exitSearchMode(true); - } - if (mMode == MODE_DEFAULT_CONTACT) { - if (SimContactsConstants.ACTION_MULTI_PICK.equals(getIntent().getAction())) { - if (mChoiceSet.size() > MAX_CONTACTS_NUM_TO_SELECT_ONCE) { - Toast.makeText( - mContext, - mContext.getString(R.string.too_many_contacts_add_to_group, - MAX_CONTACTS_NUM_TO_SELECT_ONCE), Toast.LENGTH_SHORT) - .show(); - } else { - switch (getIntent().getIntExtra(ADD_MOVE_GROUP_MEMBER_KEY, - ACTION_DEFAULT_VALUE)) { - case ACTION_ADD_GROUP_MEMBER: - this.setResult(RESULT_OK, new Intent().putExtras(mChoiceSet)); - finish(); - break; - case ACTION_MOVE_GROUP_MEMBER: - showGroupSelectionList( - getIntent().getStringExtra( - SimContactsConstants.ACCOUNT_TYPE), - getIntent().getLongExtra(KEY_GROUP_ID, -1)); - break; - default: - Intent intent = new Intent(); - Bundle bundle = new Bundle(); - bundle.putBundle(SimContactsConstants.RESULT_KEY, mChoiceSet); - intent.putExtras(bundle); - this.setResult(RESULT_OK, intent); - finish(); - } - } - } else if (mChoiceSet.size() > 0) { - showDialog(R.id.dialog_delete_contact_confirmation); - } - } else if (mMode == MODE_DEFAULT_PHONE) { - Intent intent = new Intent(); - Bundle bundle = new Bundle(); - bundle.putBundle(SimContactsConstants.RESULT_KEY, mChoiceSet); - intent.putExtras(bundle); - this.setResult(RESULT_OK, intent); - finish(); - } else if (mMode == MODE_DEFAULT_SIM) { - if (mChoiceSet.size() > 0) { - showDialog(R.id.dialog_import_sim_contact_confirmation); - } - } else if (mMode == MODE_DEFAULT_EMAIL) { - Intent intent = new Intent(); - Bundle bundle = new Bundle(); - bundle.putBundle(SimContactsConstants.RESULT_KEY, mChoiceSet); - intent.putExtras(bundle); - this.setResult(RESULT_OK, intent); - finish(); - } else if (mMode == MODE_DEFAULT_CALL) { - if (mChoiceSet.size() > 0) { - if (mSelectCallLog) { - Intent intent = new Intent(); - Bundle bundle = new Bundle(); - bundle.putBundle(SimContactsConstants.RESULT_KEY, mChoiceSet); - intent.putExtras(bundle); - this.setResult(RESULT_OK, intent); - finish(); - } else { - showDialog(DIALOG_DEL_CALL); - } - } - } - break; - case R.id.btn_cancel: - if (!isSearchMode()) { - this.setResult(this.RESULT_CANCELED); - finish(); - } else { - exitSearchMode(false); - } - break; - case R.id.select_all_check: - if (mSelectAllCheckBox.isChecked()) { - selectAll(true); - } else { - selectAll(false); - } - break; - case R.id.search_field: - enterSearchMode(); - break; - } + thread.start(); } @Override @@ -786,7 +822,7 @@ public class MultiPickContactActivity extends ListActivity implements mProgressDialog.cancel(); } - //unregister receiver. + // unregister receiver. if (mBroadcastReceiver != null) { unregisterReceiver(mBroadcastReceiver); } @@ -794,20 +830,69 @@ public class MultiPickContactActivity extends ListActivity implements super.onDestroy(); } + /** + * Just get the uri we need to query contacts. + * + * @return uri with account info parameter if explicit request contacts fit + * current account, else just search contacts fit specified keyword. + */ + private Uri getContactsFilterUri() { + Uri filterUri = Contacts.CONTENT_FILTER_URI; + + // To confirm if the search rule must contain account limitation. + Intent intent = getIntent(); + ContactListFilter filter = (ContactListFilter) intent.getParcelableExtra( + AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER); + int operation = getIntent().getIntExtra(EXTRA_GROUP_ACTION, GROUP_ACTION_NONE); + long groupId = getIntent().getLongExtra(EXTRA_GROUP_ID, -1); + String accountName = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_NAME); + String accountType = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_TYPE); + switch (operation) { + case GROUP_ACTION_ADD_MEMBER: + case GROUP_ACTION_MOVE_MEMBER: + Uri.Builder builder = Contacts.CONTENT_FILTER_URI.buildUpon(); + builder.appendQueryParameter(ADD_GROUP_MEMBERS, + operation == GROUP_ACTION_ADD_MEMBER ? "true" : "false"); + builder.appendQueryParameter(Groups._ID, String.valueOf(groupId)); + builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); + builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); + return builder.build(); + } + if (filter != null && + filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { + // Need consider account info limitation, construct the uri with + // account info query parameter. + Uri.Builder builder = filterUri.buildUpon(); + filter.addAccountQueryParameterToUrl(builder); + return builder.build(); + } + + if (!isShowSIM()) { + filterUri = filterUri.buildUpon() + .appendQueryParameter(RawContacts.ACCOUNT_TYPE, SimAccountType.ACCOUNT_TYPE) + .appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, "true") + .build(); + } + // No need to consider account info limitation, just return a uri + // with "filter" path. + return filterUri; + } + private Uri getUriToQuery() { Uri uri; switch (mMode) { - case MODE_DEFAULT_CONTACT: - int operation = getIntent().getIntExtra(ADD_MOVE_GROUP_MEMBER_KEY, -1); - long groupId = getIntent().getLongExtra(KEY_GROUP_ID, -1); - String accountName = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_NAME); - String accountType = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_TYPE); + case MODE_DEFAULT_CONTACT: { + Intent intent = getIntent(); + int operation = intent.getIntExtra(EXTRA_GROUP_ACTION, GROUP_ACTION_NONE); + long groupId = intent.getLongExtra(EXTRA_GROUP_ID, -1); + String accountName = intent.getStringExtra(SimContactsConstants.ACCOUNT_NAME); + String accountType = intent.getStringExtra(SimContactsConstants.ACCOUNT_TYPE); switch (operation) { - case ACTION_ADD_GROUP_MEMBER: - case ACTION_MOVE_GROUP_MEMBER: - Builder builder = Contacts.CONTENT_GROUP_URI.buildUpon(); - builder.appendQueryParameter(ADD_GROUP_MEMBERS, String.valueOf( - operation == ACTION_ADD_GROUP_MEMBER)); + case GROUP_ACTION_ADD_MEMBER: + case GROUP_ACTION_MOVE_MEMBER: + Uri.Builder builder = Contacts.CONTENT_GROUP_URI.buildUpon(); + builder.appendQueryParameter(ADD_GROUP_MEMBERS, + operation == GROUP_ACTION_ADD_MEMBER ? "true" : "false"); builder.appendQueryParameter(Groups._ID, String.valueOf(groupId)); builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); @@ -818,6 +903,7 @@ public class MultiPickContactActivity extends ListActivity implements break; } break; + } case MODE_SEARCH_CONTACT: uri = Contacts.CONTENT_URI; break; @@ -835,8 +921,7 @@ public class MultiPickContactActivity extends ListActivity implements break; case MODE_DEFAULT_SIM: case MODE_SEARCH_SIM: { - mIntent = getIntent(); - int subscription = mIntent.getIntExtra(SimContactsConstants.SUB, 0); + int subscription = getIntent().getIntExtra(SimContactsConstants.SUB, 0); uri = querySimContacts(subscription); break; } @@ -844,59 +929,10 @@ public class MultiPickContactActivity extends ListActivity implements throw new IllegalArgumentException("getUriToQuery: Incorrect mode: " + mMode); } return uri.buildUpon() - .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, - "true") + .appendQueryParameter(InternalContactCounts.EXTRA_ADDRESS_BOOK_INDEX, "true") .build(); } - /** - * Just get the uri we need to query contacts. - * - * @return uri with account info parameter if explicit request contacts fit - * current account, else just search contacts fit specified keyword. - */ - private Uri getContactsFilterUri() { - Uri filterUri = Contacts.CONTENT_FILTER_URI; - - // To confirm if the search rule must contain account limitation. - Intent intent = getIntent(); - ContactListFilter filter = (ContactListFilter) intent.getParcelableExtra( - AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER); - int operation = getIntent().getIntExtra(ADD_MOVE_GROUP_MEMBER_KEY, -1); - long groupId = getIntent().getLongExtra(KEY_GROUP_ID, -1); - String accountName = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_NAME); - String accountType = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_TYPE); - switch (operation) { - case ACTION_ADD_GROUP_MEMBER: - case ACTION_MOVE_GROUP_MEMBER: - Builder builder = Contacts.CONTENT_FILTER_URI.buildUpon(); - builder.appendQueryParameter(ADD_GROUP_MEMBERS, String.valueOf( - operation == ACTION_ADD_GROUP_MEMBER)); - builder.appendQueryParameter(Groups._ID, String.valueOf(groupId)); - builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName); - builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType); - return builder.build(); - } - if (filter != null && - filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { - - // Need consider account info limitation, construct the uri with - // account info query parameter. - Builder builder = filterUri.buildUpon(); - filter.addAccountQueryParameterToUrl(builder); - return builder.build(); - } - - if (!isShowSIM()) { - filterUri = filterUri.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_TYPE, - SimAccountType.ACCOUNT_TYPE) - .appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, - "true").build(); - } - // No need to consider account info limitation, just return a uri - // with "filter" path. - return filterUri; - } private Uri getFilterUri() { switch (mMode) { case MODE_SEARCH_CONTACT: @@ -927,7 +963,7 @@ public class MultiPickContactActivity extends ListActivity implements return CALL_LOG_PROJECTION; case MODE_DEFAULT_SIM: case MODE_SEARCH_SIM: - return COLUMN_NAMES; + return SIM_COLUMN_NAMES; default: log("getProjectionForQuery: Incorrect mode: " + mMode); } @@ -951,9 +987,8 @@ public class MultiPickContactActivity extends ListActivity implements case MODE_SEARCH_PHONE: if (isShowSIM()) { return null; - } else { - return PHONES_SELECTION; } + return PHONES_SELECTION; case MODE_DEFAULT_CONTACT: return getSelectionForAccount(); case MODE_DEFAULT_SIM: @@ -1003,9 +1038,8 @@ public class MultiPickContactActivity extends ListActivity implements case MODE_SEARCH_PHONE: if (isShowSIM()) { return null; - } else { - return PHONES_SELECTION_ARGS; } + return PHONES_SELECTION_ARGS; case MODE_DEFAULT_SIM: case MODE_SEARCH_SIM: return null; @@ -1016,8 +1050,8 @@ public class MultiPickContactActivity extends ListActivity implements private boolean isShowSIM() { // if airplane mode on, do not show SIM. - return !getIntent().hasExtra(EXT_NOT_SHOW_SIM_FLAG) - && !MoreContactUtils.isAPMOnAndSIMPowerDown(mContext); + return !getIntent().hasExtra(EXTRA_NOT_SHOW_SIM_FLAG) + && !MoreContactUtils.isAPMOnAndSIMPowerDown(this); } public void startQuery() { @@ -1027,49 +1061,29 @@ public class MultiPickContactActivity extends ListActivity implements if (filter != null) { if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { // We should exclude the invisiable contacts. - uri = uri.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, - filter.accountName).appendQueryParameter(RawContacts.ACCOUNT_TYPE, - filter.accountType) + uri = uri.buildUpon() + .appendQueryParameter(RawContacts.ACCOUNT_NAME, filter.accountName) + .appendQueryParameter(RawContacts.ACCOUNT_TYPE, filter.accountType) .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, - ContactsContract.Directory.DEFAULT+"").build(); + String.valueOf(ContactsContract.Directory.DEFAULT)) + .build(); } else if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) { // Do not query sim contacts in airplane mode. if (!isShowSIM()) { - uri = uri.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_TYPE, - SimAccountType.ACCOUNT_TYPE) - .appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, - "true").build(); + uri = uri.buildUpon() + .appendQueryParameter(RawContacts.ACCOUNT_TYPE, + SimAccountType.ACCOUNT_TYPE) + .appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, "true") + .build(); } } } String[] projection = getProjectionForQuery(); - String selection = getSelectionForQuery(); - String[] selectionArgs = getSelectionArgsForQuery(); - mQueryHandler.startQuery(QUERY_TOKEN, null, uri, projection, selection, - selectionArgs, getSortOrder(projection)); - } - - @Override - public void afterTextChanged(Editable s) { - if (!TextUtils.isEmpty(s)) { - if (!isSearchMode()) { - enterSearchMode(); - } - } else if (isSearchMode()) { - exitSearchMode(true); - } - doFilter(s); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + mQueryHandler.startQuery(QUERY_TOKEN, null, uri, projection, + getSelectionForQuery(), getSelectionArgsForQuery(), getSortOrder(projection)); } - public void doFilter(Editable s) { + public void doFilter(CharSequence s) { if (TextUtils.isEmpty(s)) { startQuery(); return; @@ -1077,15 +1091,13 @@ public class MultiPickContactActivity extends ListActivity implements Uri uri = Uri.withAppendedPath(getFilterUri(), Uri.encode(s.toString())); String[] projection = getProjectionForQuery(); - String selection = getSelectionForQuery(); - String[] selectionArgs = getSelectionArgsForQuery(); - mQueryHandler.startQuery(QUERY_TOKEN, null, uri, projection, selection, - selectionArgs, getSortOrder(projection)); + mQueryHandler.startQuery(QUERY_TOKEN, null, uri, projection, + getSelectionForQuery(), getSelectionArgsForQuery(), getSortOrder(projection)); } public void updateContent() { if (isSearchMode()) { - doFilter(mSearchEditor.getText()); + doFilter(mSearchView.getQuery().toString()); } else { startQuery(); } @@ -1135,52 +1147,48 @@ public class MultiPickContactActivity extends ListActivity implements String id = null; String[] value = null; if (isPickContact()) { - id = String.valueOf(cursor.getLong(SUMMARY_ID_COLUMN_INDEX)); + id = String.valueOf(cursor.getLong(CONTACT_COLUMN_ID)); value = new String[] { - cursor.getString(SUMMARY_LOOKUP_KEY_COLUMN_INDEX), id, - cursor.getString(cursor.getColumnIndex(Contacts.NAME_RAW_CONTACT_ID)), - cursor.getString(cursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI)), - cursor.getString(SUMMARY_DISPLAY_NAME_PRIMARY_COLUMN_INDEX) + cursor.getString(CONTACT_COLUMN_LOOKUP_KEY), id, + cursor.getString(CONTACT_COLUMN_RAW_CONTACT_ID), + cursor.getString(CONTACT_COLUMN_PHOTO_URI), + cursor.getString(CONTACT_COLUMN_DISPLAY_NAME) }; } else if (isPickPhone()) { id = String.valueOf(cursor.getLong(PHONE_COLUMN_ID)); - String name = cursor.getString(PHONE_COLUMN_DISPLAY_NAME); - String number = cursor.getString(PHONE_COLUMN_NUMBER); - String type = String.valueOf(cursor.getInt(PHONE_COLUMN_TYPE)); - String label = cursor.getString(PHONE_COLUMN_LABEL); - String contact_id = String.valueOf(cursor.getLong(PHONE_COLUMN_CONTACT_ID)); value = new String[] { - name, number, type, label, contact_id + cursor.getString(CONTACT_COLUMN_DISPLAY_NAME), + cursor.getString(PHONE_COLUMN_NUMBER), + String.valueOf(cursor.getInt(PHONE_COLUMN_TYPE)), + cursor.getString(PHONE_COLUMN_LABEL), + String.valueOf(cursor.getLong(CONTACT_COLUMN_ID)) }; } else if (isPickEmail()) { id = String.valueOf(cursor.getLong(EMAIL_COLUMN_ID)); - String name = cursor.getString(EMAIL_COLUMN_DISPLAY_NAME); - String email = cursor.getString(EMAIL_COLUMN_ADDRESS); value = new String[] { - name, email, id + cursor.getString(CONTACT_COLUMN_DISPLAY_NAME), + cursor.getString(EMAIL_COLUMN_ADDRESS), + id }; } else if (isPickCall()) { + id = String.valueOf(cursor.getLong(CALLLOG_COLUMN_ID)); if (mSelectCallLog) { - id = String.valueOf(cursor.getLong(ID_COLUMN_INDEX)); - String number = cursor.getString(NUMBER_COLUMN_INDEX); - String name = cursor.getString(CALLER_NAME_COLUMN_INDEX); value = new String[] { - name, number + cursor.getString(CALLLOG_COLUMN_NUMBER), + cursor.getString(CALLLOG_COLUMN_CALLER_NAME) }; } else { - id = String.valueOf(cursor.getLong(ID_COLUMN_INDEX)); value = new String[] { - id + id }; } } else if (isPickSim()) { id = String.valueOf(cursor.getLong(SIM_COLUMN_ID)); - String name = cursor.getString(SIM_COLUMN_DISPLAY_NAME); - String number = cursor.getString(SIM_COLUMN_NUMBER); - String email = cursor.getString(SIM_COLUMN_EMAILS); - String anrs = cursor.getString(SIM_COLUMN_ANRS); value = new String[] { - name, number, email, anrs + cursor.getString(SIM_COLUMN_DISPLAY_NAME), + cursor.getString(SIM_COLUMN_NUMBER), + cursor.getString(SIM_COLUMN_EMAILS), + cursor.getString(SIM_COLUMN_ANRS) }; } if (isSelected) { @@ -1190,39 +1198,21 @@ public class MultiPickContactActivity extends ListActivity implements } } - // update UI items. - mOKButton.setText(getOKString()); - - int count = mList.getChildCount(); - for (int i = 0; i < count; i++) { - View v = mList.getChildAt(i); - CheckBox checkBox = (CheckBox) v.findViewById(R.id.pick_contact_check); - checkBox.setChecked(isSelected); - } + updateActionBar(); + mAdapter.notifyDataSetChanged(); } private class QueryHandler extends AsyncQueryHandler { - protected WeakReference<MultiPickContactActivity> mActivity; - public QueryHandler(Context context) { super(context.getContentResolver()); - mActivity = new WeakReference<MultiPickContactActivity>( - (MultiPickContactActivity) context); } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { - // In the case of low memory, the WeakReference object may be - // recycled. - if (mActivity == null || mActivity.get() == null) { - mActivity = new WeakReference<MultiPickContactActivity>( - MultiPickContactActivity.this); - } - final MultiPickContactActivity activity = mActivity.get(); - activity.mAdapter.changeCursor(cursor); + mAdapter.changeCursor(cursor); if (cursor == null || cursor.getCount() == 0) { - Toast.makeText(mContext, R.string.listFoundAllContactsZero, - Toast.LENGTH_SHORT).show(); + Toast.makeText(MultiPickContactActivity.this, + R.string.listFoundAllContactsZero, Toast.LENGTH_SHORT).show(); } } } @@ -1241,102 +1231,112 @@ public class MultiPickContactActivity extends ListActivity implements String photoUri; } - private final class ContactItemListAdapter extends CursorAdapter { + private final class ContactItemListAdapter extends CursorAdapter implements SectionIndexer { Context mContext; protected LayoutInflater mInflater; + private ContactsSectionIndexer mIndexer; private ContactPhotoManager mContactPhotoManager; public ContactItemListAdapter(Context context) { super(context, null, false); mContext = context; - mInflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mContactPhotoManager = ContactPhotoManager.getInstance(mContext); } + private void assignContactAndFillCache(ContactListItemView cliv, Cursor cursor, + Account account, ContactItemCache cache) { + String newLookupKey = cursor.getString(CONTACT_COLUMN_LOOKUP_KEY); + boolean rebound = !TextUtils.equals(cache.lookupKey, newLookupKey); + + cache.lookupKey = newLookupKey; + cache.name = cursor.getString(CONTACT_COLUMN_DISPLAY_NAME); + + long photoId = cursor.getLong(CONTACT_COLUMN_PHOTO_ID); + mContactPhotoManager.loadThumbnail(cliv.getPhotoView(), photoId, account, false, true, + new DefaultImageRequest(cache.name, cache.lookupKey, true)); + + CharSequence query = mSearchView != null ? mSearchView.getQuery() : null; + cliv.setHighlightedPrefix(query != null ? query.toString().toUpperCase() : null); + cliv.setDisplayName(cache.name); + cliv.setChecked(mChoiceSet.containsKey(String.valueOf(cache.id)), !rebound); + } + @Override public void bindView(View view, Context context, Cursor cursor) { ContactItemCache cache = (ContactItemCache) view.getTag(); + ContactListItemView cliv = (ContactListItemView) view.findViewById(R.id.contact); + if (isPickContact()) { - cache.id = cursor.getLong(SUMMARY_ID_COLUMN_INDEX); - cache.lookupKey = cursor.getString(SUMMARY_LOOKUP_KEY_COLUMN_INDEX); - cache.name = cursor.getString(SUMMARY_DISPLAY_NAME_PRIMARY_COLUMN_INDEX); - cache.nameRawContactId = cursor.getLong(cursor - .getColumnIndex(Contacts.NAME_RAW_CONTACT_ID)); - cache.photoUri = cursor.getString(cursor - .getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI)); - ((TextView) view.findViewById(R.id.pick_contact_name)) - .setText(cache.name == null ? "" : cache.name); - view.findViewById(R.id.pick_contact_number).setVisibility(View.GONE); - - long photoId = 0; - if (!cursor.isNull(SUMMARY_PHOTO_ID_COLUMN_INDEX)) { - photoId = cursor.getLong(SUMMARY_PHOTO_ID_COLUMN_INDEX); - } + cache.id = cursor.getLong(CONTACT_COLUMN_ID); + cache.nameRawContactId = cursor.getLong(CONTACT_COLUMN_RAW_CONTACT_ID); + cache.photoUri = cursor.getString(CONTACT_COLUMN_PHOTO_URI); + Account account = null; - if (!cursor.isNull(SUMMARY_ACCOUNT_TYPE) && !cursor.isNull(SUMMARY_ACCOUNT_NAME)) { - final String accountType = cursor.getString(SUMMARY_ACCOUNT_TYPE); - final String accountName = cursor.getString(SUMMARY_ACCOUNT_NAME); + if (!cursor.isNull(CONTACT_COLUMN_ACCOUNT_TYPE) + && !cursor.isNull(CONTACT_COLUMN_ACCOUNT_NAME)) { + final String accountType = cursor.getString(CONTACT_COLUMN_ACCOUNT_TYPE); + final String accountName = cursor.getString(CONTACT_COLUMN_ACCOUNT_NAME); account = new Account(accountName, accountType); } - ImageView photo = ((ImageView) view.findViewById(R.id.pick_contact_photo)); - photo.setVisibility(View.VISIBLE); - DefaultImageRequest request = null; - if (photoId == 0) { - request = new DefaultImageRequest(cache.name, cache.lookupKey, true); - } - mContactPhotoManager.loadThumbnail(photo, photoId, account, false, true, request); + + assignContactAndFillCache(cliv, cursor, account, cache); + cliv.setPhoneNumber(null, null); } else if (isPickPhone()) { cache.id = cursor.getLong(PHONE_COLUMN_ID); - cache.name = cursor.getString(PHONE_COLUMN_DISPLAY_NAME); cache.number = cursor.getString(PHONE_COLUMN_NUMBER); cache.label = cursor.getString(PHONE_COLUMN_LABEL); cache.type = String.valueOf(cursor.getInt(PHONE_COLUMN_TYPE)); - ((TextView) view.findViewById(R.id.pick_contact_name)).setText(cache.name); - ((TextView) view.findViewById(R.id.pick_contact_number)).setText(cache.number); + + assignContactAndFillCache(cliv, cursor, null, cache); + cliv.setPhoneNumber(cache.number, null); } else if (isPickSim()) { cache.id = cursor.getLong(SIM_COLUMN_ID); cache.name = cursor.getString(SIM_COLUMN_DISPLAY_NAME); cache.number = cursor.getString(SIM_COLUMN_NUMBER); cache.email = cursor.getString(SIM_COLUMN_EMAILS); cache.anrs = cursor.getString(SIM_COLUMN_ANRS); - ((TextView) view.findViewById(R.id.pick_contact_name)).setText(cache.name); + + cliv.setDisplayName(cache.name); + cliv.removePhotoView(); if (!TextUtils.isEmpty(cache.number)) { - ((TextView) view.findViewById(R.id.pick_contact_number)).setText(cache.number); + cliv.setPhoneNumber(cache.number, null); } else if (!TextUtils.isEmpty(cache.email)) { String[] emailArray = (cache.email).split(","); - ((TextView) view.findViewById(R.id.pick_contact_number)).setText(emailArray[0]); + cliv.setPhoneNumber(emailArray[0], null); + } else { + cliv.setPhoneNumber(null, null); } } else if (isPickEmail()) { cache.id = cursor.getLong(EMAIL_COLUMN_ID); - cache.name = cursor.getString(EMAIL_COLUMN_DISPLAY_NAME); cache.email = cursor.getString(EMAIL_COLUMN_ADDRESS); - ((TextView) view.findViewById(R.id.pick_contact_name)).setText(cache.name); - ((TextView) view.findViewById(R.id.pick_contact_number)).setText(cache.email); - } else if (isPickCall()) { - cache.id = cursor.getLong(ID_COLUMN_INDEX); - cache.name = cursor.getString(CALLER_NAME_COLUMN_INDEX); - cache.number = cursor.getString(NUMBER_COLUMN_INDEX); - String number = cursor.getString(NUMBER_COLUMN_INDEX); - String callerName = cursor.getString(CALLER_NAME_COLUMN_INDEX); - int callerNumberType = cursor.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX); - String callerNumberLabel = cursor.getString(CALLER_NUMBERLABEL_COLUMN_INDEX); - String subscriptionId = cursor.getString(PHONE_SUBSCRIPTION_COLUMN_INDEX); - long date = cursor.getLong(DATE_COLUMN_INDEX); - long duration = cursor.getLong(DURATION_COLUMN_INDEX); - int type = cursor.getInt(CALL_TYPE_COLUMN_INDEX); + + assignContactAndFillCache(cliv, cursor, null, cache); + cliv.setPhoneNumber(cache.email, null); + } else if (isPickCall()) { + cache.id = cursor.getLong(CALLLOG_COLUMN_ID); + cache.name = cursor.getString(CALLLOG_COLUMN_CALLER_NAME); + cache.number = cursor.getString(CALLLOG_COLUMN_NUMBER); + + String callerName = cursor.getString(CALLLOG_COLUMN_CALLER_NAME); + int callerNumberType = cursor.getInt(CALLLOG_COLUMN_CALLER_NUMBERTYPE); + String callerNumberLabel = cursor.getString(CALLLOG_COLUMN_CALLER_NUMBERLABEL); + String geocodedLocation = cursor.getString(CALLLOG_COLUMN_CALLER_LOCATION); + String accountId = cursor.getString(CALLLOG_COLUMN_PHONE_ACCOUNT); + long date = cursor.getLong(CALLLOG_COLUMN_DATE); + long duration = cursor.getLong(CALLLOG_COLUMN_DURATION); + int type = cursor.getInt(CALLLOG_COLUMN_CALL_TYPE); ImageView callType = (ImageView) view.findViewById(R.id.call_type_icon); - TextView dateText = (TextView) view.findViewById(R.id.date); + TextView dateText = (TextView) view.findViewById(R.id.call_date); TextView durationText = (TextView) view.findViewById(R.id.duration); TextView subSlotText = (TextView) view.findViewById(R.id.subscription); - TextView numberLableText = (TextView) view.findViewById(R.id.label); - TextView numberText = (TextView) view.findViewById(R.id.number); - TextView callerNameText = (TextView) view.findViewById(R.id.line1); + TextView numberLabelText = (TextView) view.findViewById(R.id.label); + TextView nameText = (TextView) view.findViewById(R.id.name); // only for monkey test, callType can not be null in normal behaviour - if(callType == null){ + if (callType == null) { return; } @@ -1344,13 +1344,13 @@ public class MultiPickContactActivity extends ListActivity implements // Set the icon switch (type) { case Calls.INCOMING_TYPE: - callType.setImageDrawable(mDrawableIncoming); + callType.setImageResource(R.drawable.ic_call_incoming_holo_dark); break; case Calls.OUTGOING_TYPE: - callType.setImageDrawable(mDrawableOutgoing); + callType.setImageResource(R.drawable.ic_call_outgoing_holo_dark); break; case Calls.MISSED_TYPE: - callType.setImageDrawable(mDrawableMissed); + callType.setImageResource(R.drawable.ic_call_missed_holo_dark); break; default: callType.setVisibility(View.INVISIBLE); @@ -1359,30 +1359,21 @@ public class MultiPickContactActivity extends ListActivity implements // set the number if (!TextUtils.isEmpty(callerName)) { - callerNameText.setText(callerName); - callerNameText.setVisibility(View.VISIBLE); - numberText.setVisibility(View.GONE); - numberText.setText(null); + nameText.setText(callerName); } else { - callerNameText.setVisibility(View.GONE); - callerNameText.setText(null); - numberText.setVisibility(View.VISIBLE); - numberText.setTextDirection(View.TEXT_DIRECTION_LTR); - numberText.setText(getDisplayNumber(number)); + nameText.setText(getDisplayNumber(cache.number)); } CharSequence numberLabel = null; - if (!PhoneNumberUtils.isUriNumber(number)) { - numberLabel = Phone.getTypeLabel(context.getResources(), - callerNumberType, callerNumberLabel); - } - if (!TextUtils.isEmpty(numberLabel)) { - numberLableText.setText(numberLabel); - numberLableText.setVisibility(View.VISIBLE); + if (callerNumberType != 0 && !PhoneNumberUtils.isUriNumber(cache.number)) { + numberLabel = Phone.getDisplayLabel(context, callerNumberType, + callerNumberLabel); } else { - numberLableText.setText(null); - numberLableText.setVisibility(View.INVISIBLE); + numberLabel = geocodedLocation; } + numberLabelText.setText(numberLabel); + numberLabelText.setVisibility(TextUtils.isEmpty(numberLabel) + ? View.GONE : View.VISIBLE); // set date dateText.setText(DateUtils.getRelativeTimeSpanString(date, @@ -1393,74 +1384,108 @@ public class MultiPickContactActivity extends ListActivity implements durationText.setText(DateUtils.formatElapsedTime(duration)); // set slot - int slotId = SimContactsConstants.SUB_INVALID; - if (subscriptionId != null && !subscriptionId.equals("E")) { - slotId = SubscriptionManager.getSlotId(Long.valueOf(subscriptionId)); + if (isMultiSimEnabled()) { + int slotId = SimContactsConstants.SUB_INVALID; + if (accountId != null) { + try { + slotId = SubscriptionManager.getSlotId(Long.valueOf(accountId)); + } catch (NumberFormatException e) { + // ignore and keep the default 'invalid' + } + } + subSlotText.setText(MoreContactUtils.getMultiSimAliasesName( + MultiPickContactActivity.this, slotId)); + } else { + subSlotText.setVisibility(View.GONE); } - subSlotText.setText(MoreContactUtils.getMultiSimAliasesName( - MultiPickContactActivity.this, slotId)); - } - CheckBox checkBox = (CheckBox) view.findViewById(R.id.pick_contact_check); - if (mChoiceSet.containsKey(String.valueOf(cache.id))) { - checkBox.setChecked(true); - } else { - checkBox.setChecked(false); + CheckBox checkBox = (CheckBox) view.findViewById(R.id.pick_contact_check); + checkBox.setChecked(mChoiceSet.containsKey(String.valueOf(cache.id))); } } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - View v = null; - if (isPickCall()) { - v = mInflater.inflate(R.layout.pick_calls_item, parent, false); - } else { - v = mInflater - .inflate(R.layout.pick_contact_item, parent, false); + int layoutResId = isPickCall() ? R.layout.pick_calls_item : R.layout.pick_contact_item; + View v = mInflater.inflate(layoutResId, parent, false); + ContactListItemView cliv = (ContactListItemView) v.findViewById(R.id.contact); + if (cliv != null) { + cliv.setUnknownNameText(getString(R.string.missing_name)); } ContactItemCache cache = new ContactItemCache(); v.setTag(cache); return v; } - public View getView(int position, View convertView, ViewGroup parent) { - View v; + @Override + protected void onContentChanged() { + updateContent(); + } - if (!mCursor.moveToPosition(position)) { - throw new IllegalStateException( - "couldn't move cursor to position " + position); - } - if (convertView != null && convertView.getTag() != null) { - v = convertView; + @Override + public void changeCursor(Cursor cursor) { + super.changeCursor(cursor); + String[] sections = null; + int[] counts = null; + Bundle extras = cursor != null ? cursor.getExtras() : null; + if (extras != null && + extras.containsKey(InternalContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES)) { + sections = extras.getStringArray( + InternalContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES); + counts = extras.getIntArray(InternalContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS); } else { - v = newView(mContext, mCursor, parent); + sections = new String[0]; + counts = new int[0]; } - bindView(v, mContext, mCursor); - return v; + mIndexer = new ContactsSectionIndexer(sections, counts); + updateActionBar(); } @Override - protected void onContentChanged() { - updateContent(); + public Object[] getSections() { + if (mIndexer != null) { + return mIndexer.getSections(); + } + return null; } @Override - public void changeCursor(Cursor cursor) { - super.changeCursor(cursor); - if (!isSearchMode()) { - if (cursor == null || cursor.getCount() == 0) { - mSelectAllCheckBox.setChecked(false); - mSelectAllLabel.setEnabled(false); - mSelectAllCheckBox.setClickable(false); - } else { - mSelectAllLabel.setEnabled(true); - mSelectAllCheckBox.setClickable(true); - if (cursor.getCount() > mChoiceSet.size()) { - mSelectAllCheckBox.setChecked(false); - } else { - mSelectAllCheckBox.setChecked(true); - } - } + public int getPositionForSection(int section) { + Cursor cursor = getCursor(); + if (cursor == null) { + return 0; + } + if (mIndexer != null) { + return mIndexer.getPositionForSection(section); + } + return 0; + } + + @Override + public int getSectionForPosition(int position) { + if (mIndexer != null) { + return mIndexer.getSectionForPosition(position); + } + return -1; + } + + public int getSortIndex() { + switch (mMode) { + case MODE_DEFAULT_CONTACT: + case MODE_SEARCH_CONTACT: + case MODE_DEFAULT_PHONE: + case MODE_SEARCH_PHONE: + case MODE_DEFAULT_EMAIL: + case MODE_SEARCH_EMAIL: + return CONTACT_COLUMN_DISPLAY_NAME; + case MODE_DEFAULT_CALL: + case MODE_SEARCH_CALL: + return CALLLOG_COLUMN_CALLER_NAME; + case MODE_DEFAULT_SIM: + case MODE_SEARCH_SIM: + return SIM_COLUMN_DISPLAY_NAME; + default: + throw new IllegalArgumentException("Incorrect mode for multi pick"); } } } @@ -1485,21 +1510,13 @@ public class MultiPickContactActivity extends ListActivity implements private void hideSoftKeyboard() { // Hide soft keyboard, if visible - InputMethodManager inputMethodManager = (InputMethodManager) - getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.hideSoftInputFromWindow(mSearchEditor.getWindowToken(), 0); - } - - private String getTextFilter() { - if (mSearchEditor != null) { - return mSearchEditor.getText().toString(); - } - return null; + InputMethodManager inputMethodManager = + (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(mSearchView.getWindowToken(), 0); } protected static void log(String msg) { - if (DEBUG) - Log.d(TAG, msg); + if (DEBUG) Log.d(TAG, msg); } private Uri querySimContacts(int subscription) { @@ -1509,7 +1526,7 @@ public class MultiPickContactActivity extends ListActivity implements return uri; } long[] subId = SubscriptionManager.getSubId(subscription); - if (subId != null && TelephonyManager.getDefault().isMultiSimEnabled()) { + if (subId != null && isMultiSimEnabled()) { uri = Uri.parse(SimContactsConstants.SIM_SUB_URI + subId[0]); } else { @@ -1519,13 +1536,16 @@ public class MultiPickContactActivity extends ListActivity implements return uri; } + private boolean isMultiSimEnabled() { + return TelephonyManager.getDefault().isMultiSimEnabled(); + } + protected Account[] getSimAccounts() { - return accountManager - .getAccountsByType(SimContactsConstants.ACCOUNT_TYPE_SIM); + return mAccountManager.getAccountsByType(SimContactsConstants.ACCOUNT_TYPE_SIM); } private class ImportAllSimContactsThread extends Thread - implements OnCancelListener, DialogInterface.OnClickListener { + implements DialogInterface.OnCancelListener, DialogInterface.OnClickListener { boolean mCanceled = false; // The total count how many to import. private int mTotalCount = 0; @@ -1540,19 +1560,19 @@ public class MultiPickContactActivity extends ListActivity implements @Override public void run() { final ContentValues emptyContentValues = new ContentValues(); - final ContentResolver resolver = mContext.getContentResolver(); + final ContentResolver resolver = getContentResolver(); String type = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_TYPE); String name = getIntent().getStringExtra(SimContactsConstants.ACCOUNT_NAME); mAccount = new Account(name != null ? name : SimContactsConstants.PHONE_NAME, - type != null ? type - : SimContactsConstants.ACCOUNT_TYPE_PHONE); + type != null ? type : SimContactsConstants.ACCOUNT_TYPE_PHONE); log("import sim contact to account: " + mAccount); - Set<String> keySet = mChoiceSet.keySet(); - mTotalCount = keySet.size(); - Iterator<String> it = keySet.iterator(); - while (!mCanceled && it.hasNext()) { - String key = it.next(); + mTotalCount = mChoiceSet.size(); + + for (String key : mChoiceSet.keySet()) { + if (mCanceled) { + break; + } String[] values = mChoiceSet.getStringArray(key); actuallyImportOneSimContact(values, resolver, mAccount); mActualCount++; @@ -1561,14 +1581,17 @@ public class MultiPickContactActivity extends ListActivity implements finish(); } + @Override public void onCancel(DialogInterface dialog) { + final Context context = MultiPickContactActivity.this; mCanceled = true; // Give a toast show to tell user import termination. if (mActualCount < mTotalCount) { - Toast.makeText(mContext, R.string.import_stop, Toast.LENGTH_SHORT).show(); + String text = getResources().getQuantityString(R.plurals.import_progress, + mActualCount, mActualCount); + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); } else { - Toast.makeText(mContext, R.string.import_finish, Toast.LENGTH_SHORT) - .show(); + Toast.makeText(context, R.string.import_finish, Toast.LENGTH_SHORT).show(); } } @@ -1689,7 +1712,7 @@ public class MultiPickContactActivity extends ListActivity implements }, null); if (cursor == null || cursor.getCount() == 0) { - Toast.makeText(mContext, R.string.message_can_not_move_members, + Toast.makeText(this, R.string.message_can_not_move_members, Toast.LENGTH_LONG).show(); return; } else { @@ -1707,7 +1730,7 @@ public class MultiPickContactActivity extends ListActivity implements } } if (mGroupIds.size() == 0) { - Toast.makeText(mContext, R.string.message_can_not_move_members, + Toast.makeText(this, R.string.message_can_not_move_members, Toast.LENGTH_LONG).show(); return; } @@ -1722,7 +1745,7 @@ public class MultiPickContactActivity extends ListActivity implements private class ChooseActionListener implements DialogInterface.OnClickListener { public void onClick(DialogInterface dialog, int which) { new MoveGroupMemberTask(mChoiceSet, - getIntent().getLongExtra(KEY_GROUP_ID, -1), + getIntent().getLongExtra(EXTRA_GROUP_ID, -1), mGroupIds.get(which)).execute(); } } @@ -1771,7 +1794,7 @@ public class MultiPickContactActivity extends ListActivity implements mProgressDialog.setMax(mChoiceSet != null ? mChoiceSet.keySet().size() : 100); mProgressDialog.setProgress(0); mProgressDialog.setCanceledOnTouchOutside(false); - mProgressDialog.setOnCancelListener(new OnCancelListener() { + mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { mCanceled = true; } @@ -1784,7 +1807,7 @@ public class MultiPickContactActivity extends ListActivity implements if (mChoiceSet == null || mSrcGroupId <= 0) { return null; } - ContentResolver resolver = mContext.getContentResolver(); + ContentResolver resolver = getContentResolver(); Cursor memberCursor = null; memberCursor = resolver.query(Data.CONTENT_URI, diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java index 40f483e45..424cb9eb2 100644..100755 --- a/src/com/android/contacts/activities/PeopleActivity.java +++ b/src/com/android/contacts/activities/PeopleActivity.java @@ -39,6 +39,8 @@ import android.preference.PreferenceManager; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; +import android.telephony.TelephonyManager; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; import android.view.KeyCharacterMap; @@ -57,8 +59,11 @@ import com.android.contacts.ContactsActivity; import com.android.contacts.R; import com.android.contacts.activities.ActionBarAdapter.TabState; import com.android.contacts.common.ContactsUtils; +import com.android.contacts.common.MoreContactUtils; import com.android.contacts.common.dialog.ClearFrequentsDialog; import com.android.contacts.common.editor.SelectAccountDialogFragment; +import com.android.contacts.common.interactions.ImportSIMContactsDialogFragment; +import com.android.contacts.common.preference.ContactsPreferences; import com.android.contacts.group.GroupBrowseListFragment; import com.android.contacts.group.GroupBrowseListFragment.OnGroupBrowserActionListener; import com.android.contacts.group.GroupDetailFragment; @@ -478,6 +483,51 @@ public class PeopleActivity extends ContactsActivity implements // Current tab may have changed since the last onSaveInstanceState(). Make sure // the actual contents match the tab. updateFragmentsVisibility(); + + // Check if SIM Contacts reload is necessary + checkSIMContacts(); + } + + private void checkSIMContacts() { + boolean showImport = getResources().getBoolean(R.bool.config_show_sms_import_dialog); + + if (showImport) { + // SIM Serial Number + ContactsPreferences contactPrefs = new ContactsPreferences(this); + String[] sims = contactPrefs.getImportedSims(); + boolean shouldImport = false; + int count = MoreContactUtils.getEnabledSimCount(); + for (int i = 0; i < count; i++) { + boolean simImported = false; + if (TelephonyManager.SIM_STATE_READY == TelephonyManager + .getDefault().getSimState(i)) { + long[] subId = SubscriptionManager.getSubId(i); + if (subId == null) { + continue; + } + String simSN = TelephonyManager.getDefault().getSimSerialNumber( + subId[0]); + + for (String sn : sims) { + if (sn.equals(simSN)) { + simImported = true; + break; + } + } + + if (!simImported) { + shouldImport = true; + contactPrefs.addImportedSims(simSN); + } + } + } + + if (shouldImport) { + ImportSIMContactsDialogFragment dialogFragment = new + ImportSIMContactsDialogFragment(); + dialogFragment.show(getFragmentManager(), PeopleActivity.class.getName()); + } + } } @Override @@ -900,6 +950,9 @@ public class PeopleActivity extends ContactsActivity implements mAllFragment.setVerticalScrollbarPosition(getScrollBarPosition()); mAllFragment.setSelectionVisible(false); + final boolean cmccFeature = getResources(). + getBoolean(R.bool.config_show_quick_call_button); + mAllFragment.setQuickCallButtonEnabled(cmccFeature); } private int getScrollBarPosition() { diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java index 81cc28c11..1b2398445 100644 --- a/src/com/android/contacts/group/GroupBrowseListFragment.java +++ b/src/com/android/contacts/group/GroupBrowseListFragment.java @@ -159,17 +159,6 @@ public class GroupBrowseListFragment extends Fragment private void configureVerticalScrollbar() { mListView.setVerticalScrollbarPosition(mVerticalScrollbarPosition); mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); - int leftPadding = 0; - int rightPadding = 0; - if (mVerticalScrollbarPosition == View.SCROLLBAR_POSITION_LEFT) { - leftPadding = mContext.getResources().getDimensionPixelOffset( - R.dimen.list_visible_scrollbar_padding); - } else { - rightPadding = mContext.getResources().getDimensionPixelOffset( - R.dimen.list_visible_scrollbar_padding); - } - mListView.setPadding(leftPadding, mListView.getPaddingTop(), - rightPadding, mListView.getPaddingBottom()); } @Override diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java index 6bd890acb..142dc8aa4 100644 --- a/src/com/android/contacts/group/GroupDetailFragment.java +++ b/src/com/android/contacts/group/GroupDetailFragment.java @@ -52,15 +52,15 @@ import android.widget.Toast; import com.android.contacts.GroupMemberLoader; import com.android.contacts.GroupMetaDataLoader; import com.android.contacts.R; +import com.android.contacts.activities.MultiPickContactActivity; import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.interactions.GroupDeletionDialogFragment; +import com.android.contacts.common.SimContactsConstants; import com.android.contacts.common.list.ContactTileAdapter; import com.android.contacts.common.list.ContactTileView; -import com.android.contacts.list.GroupMemberTileAdapter; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountType; -import com.android.contacts.editor.MultiPickContactActivity; -import com.android.contacts.common.SimContactsConstants; +import com.android.contacts.interactions.GroupDeletionDialogFragment; +import com.android.contacts.list.GroupMemberTileAdapter; /** * Displays the details of a group and shows a list of actions possible for the group. @@ -480,11 +480,11 @@ public class GroupDetailFragment extends Fragment implements OnScrollListener { Intent intent = new Intent(SimContactsConstants.ACTION_MULTI_PICK); intent.setType(Contacts.CONTENT_TYPE); intent.putExtra(SimContactsConstants.IS_CONTACT, true); - intent.putExtra(MultiPickContactActivity.KEY_GROUP_ID, getGroupId()); + intent.putExtra(MultiPickContactActivity.EXTRA_GROUP_ID, getGroupId()); intent.putExtra(SimContactsConstants.ACCOUNT_TYPE, mAccountTypeString); intent.putExtra(SimContactsConstants.ACCOUNT_NAME, mAccountNameString); - intent.putExtra(MultiPickContactActivity.ADD_MOVE_GROUP_MEMBER_KEY, - MultiPickContactActivity.ACTION_MOVE_GROUP_MEMBER); + intent.putExtra(MultiPickContactActivity.EXTRA_GROUP_ACTION, + MultiPickContactActivity.GROUP_ACTION_MOVE_MEMBER); startActivity(intent); return true; } diff --git a/src/com/android/contacts/group/GroupEditorFragment.java b/src/com/android/contacts/group/GroupEditorFragment.java index 333ebb6fa..a45767ce4 100755 --- a/src/com/android/contacts/group/GroupEditorFragment.java +++ b/src/com/android/contacts/group/GroupEditorFragment.java @@ -63,18 +63,18 @@ import com.android.contacts.GroupMemberLoader.GroupEditorQuery; import com.android.contacts.GroupMetaDataLoader; import com.android.contacts.R; import com.android.contacts.activities.GroupEditorActivity; +import com.android.contacts.activities.MultiPickContactActivity; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; import com.android.contacts.common.model.account.AccountType; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.common.model.account.PhoneAccountType; import com.android.contacts.common.editor.SelectAccountDialogFragment; -import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter; import com.android.contacts.common.util.ViewUtil; -import com.android.contacts.editor.MultiPickContactActivity; import com.android.contacts.common.SimContactsConstants; +import com.android.contacts.group.SuggestedMemberListAdapter.SuggestedMember; import com.google.common.base.Objects; @@ -479,9 +479,9 @@ public class GroupEditorFragment extends Fragment implements SelectAccountDialog intent.putExtra(SimContactsConstants.IS_CONTACT, true); intent.putExtra(SimContactsConstants.ACCOUNT_NAME, mAccountName); intent.putExtra(SimContactsConstants.ACCOUNT_TYPE, mAccountType); - intent.putExtra(MultiPickContactActivity.ADD_MOVE_GROUP_MEMBER_KEY, - MultiPickContactActivity.ACTION_ADD_GROUP_MEMBER); - intent.putExtra(MultiPickContactActivity.KEY_GROUP_ID, mGroupId); + intent.putExtra(MultiPickContactActivity.EXTRA_GROUP_ACTION, + MultiPickContactActivity.GROUP_ACTION_ADD_MEMBER); + intent.putExtra(MultiPickContactActivity.EXTRA_GROUP_ID, mGroupId); startActivityForResult(intent, REQUEST_CODE_PICK_GROUP_MEM); } }); |