diff options
author | Andrew Lee <anwlee@google.com> | 2015-10-15 10:45:19 -0700 |
---|---|---|
committer | Andrew Lee <anwlee@google.com> | 2015-10-16 15:06:37 -0700 |
commit | c412f94fb20db5cd177421e373fdf941e0135c81 (patch) | |
tree | a75f9138f6401c2704bf377ebdb1535347ad6603 | |
parent | 8d0847ca13ca46730756e1d3a3dff3d7d27fd18b (diff) |
Add import for SEND_TO_VOICEMAIL.
+ Add utility class for async import functions.
+ Move check for contacts with SEND_TO_VOICEMAIl to util.
+ Add function for adding phone numbers of contacts with
SEND_TO_VOICEMAIL to the block list, then clearing the
SEND_TO_VOICEMAIL flag.
+ Fixed bug where the import text would not be shown for an empty
block list. Rearranged layouts slightly to facilitate this.
+ Protect against null listeners in FilteredNumberAsyncQueryHandler.
Bug: 23351616
Change-Id: Id526e16f20a3d28966bbc5e458cecfcd03ecb20f
-rw-r--r-- | res/layout/blocked_number_fragment.xml | 25 | ||||
-rw-r--r-- | res/layout/blocked_number_header.xml | 9 | ||||
-rw-r--r-- | res/values/strings.xml | 7 | ||||
-rw-r--r-- | src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java | 8 | ||||
-rw-r--r-- | src/com/android/dialer/filterednumber/BlockedNumberFragment.java | 82 | ||||
-rw-r--r-- | src/com/android/dialer/filterednumber/FilteredNumbersUtil.java | 181 |
6 files changed, 234 insertions, 78 deletions
diff --git a/res/layout/blocked_number_fragment.xml b/res/layout/blocked_number_fragment.xml index e86ccb596..bb4b7f20f 100644 --- a/res/layout/blocked_number_fragment.xml +++ b/res/layout/blocked_number_fragment.xml @@ -27,23 +27,22 @@ android:layout_height="wrap_content" card_view:cardCornerRadius="0dp"> - <ListView android:id="@id/android:list" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/background_dialer_white" - android:layout_weight="1" - android:drawSelectorOnTop="false" - android:headerDividersEnabled="false" /> - <LinearLayout - android:id="@android:id/empty" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@color/background_dialer_white"> <include layout="@layout/blocked_number_header" /> - <TextView android:id="@id/android:empty" + <ListView android:id="@id/android:list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" + android:drawSelectorOnTop="false" + android:headerDividersEnabled="false" /> + + <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingStart="@dimen/blocked_number_horizontal_margin" diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml index 95880a7c0..39f532281 100644 --- a/res/layout/blocked_number_header.xml +++ b/res/layout/blocked_number_header.xml @@ -13,10 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" @@ -26,7 +23,7 @@ android:padding="@dimen/blocked_number_container_padding" style="@android:style/TextAppearance.Material.Subhead" /> - <RelativeLayout android:id="@+id/importsettings" + <RelativeLayout android:id="@+id/import_settings" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"> @@ -77,4 +74,4 @@ android:layout_marginTop="8dp" android:text="@string/blockNumber" /> -</LinearLayout> +</merge> diff --git a/res/values/strings.xml b/res/values/strings.xml index cd7ce8fa8..0b7d82c61 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -833,7 +833,7 @@ You previously marked some callers to be automatically sent to voicemail via other apps. </string> - <!-- Labe for button to view numbers of contacts previous marked to be sent to voicemail. + <!-- Label for button to view numbers of contacts previous marked to be sent to voicemail. [CHAR_LIMIT=20] --> <string name="blocked_call_settings_view_numbers_button">View Numbers</string> @@ -841,6 +841,9 @@ list. [CHAR_LIMIT=20] --> <string name="blocked_call_settings_import_button">Import</string> + <!-- Error toast message for when send to voicemail import fails. [CHAR LIMIT=40] --> + <string name="send_to_voicemail_import_failed">Import failed</string> + <!-- String describing the delete icon on a blocked number list item. When tapped, it will show a dialog confirming the unblocking of the number. [CHAR LIMIT=NONE]--> @@ -853,7 +856,7 @@ <!-- Button to bring up UI to add a number to the blocked call list. [CHAR LIMIT=40] --> <string name="blockNumber">Add number</string> - <!-- Heading for the block list in the "Spam and blocked calls" settings. [CHAR LIMIT=64] --> + <!-- Heading for the block list in the "Spam and blocked cal)ls" settings. [CHAR LIMIT=64] --> <string name="blockList">Block list</string> <!-- Label for progress dialog when validating a number to be added to the block list. diff --git a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java index c5d2f6f70..25613a6f8 100644 --- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java +++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java @@ -202,7 +202,9 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { new Listener() { @Override public void onInsertComplete(int token, Object cookie, Uri uri) { - listener.onBlockComplete(uri); + if (listener != null ) { + listener.onBlockComplete(uri); + } } }, getContentUri(null), values); } @@ -241,7 +243,9 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { startDelete(NO_TOKEN, new Listener() { @Override public void onDeleteComplete(int token, Object cookie, int result) { - listener.onUnblockComplete(result, values); + if (listener != null) { + listener.onUnblockComplete(result, values); + } } }, uri, null, null); } diff --git a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java index 5740305f7..60c35ab9b 100644 --- a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java +++ b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java @@ -21,45 +21,49 @@ import android.content.CursorLoader; import android.content.Intent; import android.content.Loader; import android.database.Cursor; -import android.os.AsyncTask; import android.os.Bundle; -import android.provider.ContactsContract.Contacts; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.dialer.R; import com.android.dialer.database.FilteredNumberContract; +import com.android.dialer.filterednumber.FilteredNumbersUtil.CheckForSendToVoicemailContactListener; +import com.android.dialer.filterednumber.FilteredNumbersUtil.ImportSendToVoicemailContactsListener; public class BlockedNumberFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>, View.OnClickListener { - private static class SendToVoicemailContactQuery { - static final String[] PROJECTION = { - Contacts._ID - }; - - static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1"; - } - private BlockedNumberAdapter mAdapter; + private View mImportSettings; + private View mImportButton; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - LayoutInflater inflater = LayoutInflater.from(getContext()); - getListView().addHeaderView(inflater.inflate(R.layout.blocked_number_header, null)); if (mAdapter == null) { mAdapter = new BlockedNumberAdapter(getContext()); } setListAdapter(mAdapter); getActivity().findViewById(R.id.add_number_button).setOnClickListener(this); - getListView().getEmptyView().findViewById(R.id.add_number_button).setOnClickListener(this); - mImportSettings = getActivity().findViewById(R.id.importsettings); + mImportSettings = getActivity().findViewById(R.id.import_settings); + mImportButton = getActivity().findViewById(R.id.import_button); + mImportButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + FilteredNumbersUtil.importSendToVoicemailContacts( + getActivity(), new ImportSendToVoicemailContactsListener() { + @Override + public void onImportComplete() { + mImportSettings.setVisibility(View.GONE); + } + }); + } + }); } @Override @@ -77,7 +81,15 @@ public class BlockedNumberFragment extends ListFragment implements @Override public void onResume() { super.onResume(); - checkForSendToVoicemailContact(); + + FilteredNumbersUtil.checkForSendToVoicemailContact( + getActivity(), new CheckForSendToVoicemailContactListener() { + @Override + public void onComplete(boolean hasSendToVoicemailContact) { + final int visibility = hasSendToVoicemailContact ? View.VISIBLE : View.GONE; + mImportSettings.setVisibility(visibility); + } + }); } @Override @@ -121,44 +133,4 @@ public class BlockedNumberFragment extends ListFragment implements manageBlockedNumbersActivity.enterSearchUi(); } } - - /** - * Checks if there exists a contact with {@code Contacts.SEND_TO_VOICEMAIL} set to true, - * and updates the visibility of the import settings buttons accordingly. - */ - private void checkForSendToVoicemailContact() { - final AsyncTask task = new AsyncTask<Object, Void, Boolean>() { - @Override - public Boolean doInBackground(Object[] params) { - if (getActivity() == null) { - return false; - } - - final Cursor cursor = getActivity().getContentResolver().query( - Contacts.CONTENT_URI, - SendToVoicemailContactQuery.PROJECTION, - SendToVoicemailContactQuery.SELECT_SEND_TO_VOICEMAIL_TRUE, - null, - null); - - boolean hasSendToVoicemailContacts = false; - if (cursor != null) { - try { - hasSendToVoicemailContacts = cursor.getCount() > 0; - } finally { - cursor.close(); - } - } - - return hasSendToVoicemailContacts; - } - - @Override - public void onPostExecute(Boolean hasSendToVoicemailContact) { - final int visibility = hasSendToVoicemailContact ? View.VISIBLE : View.GONE; - mImportSettings.setVisibility(visibility); - } - }; - task.execute(); - } } diff --git a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java new file mode 100644 index 000000000..56417e11d --- /dev/null +++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.dialer.filterednumber; + +import android.content.Context; +import android.content.ContentValues; +import android.database.Cursor; +import android.os.AsyncTask; +import android.provider.ContactsContract.Data; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Contacts; +import android.text.TextUtils; +import android.widget.Toast; + +import java.util.LinkedList; +import java.util.List; + +import com.android.dialer.R; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler; + +/** + * Utility to help with tasks related to importing filtered numbers, namely migrating the + * SEND_TO_VOICEMAIL from Contacts. + */ +public class FilteredNumbersUtil { + + public interface CheckForSendToVoicemailContactListener { + public void onComplete(boolean hasSendToVoicemailContact); + } + + public interface ImportSendToVoicemailContactsListener { + public void onImportComplete(); + } + + private static class ContactsQuery { + static final String[] PROJECTION = { + Contacts._ID + }; + + static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1"; + + static final int ID_COLUMN_INDEX = 0; + } + + private static class PhoneQuery { + static final String[] PROJECTION = { + Phone.NORMALIZED_NUMBER, + Phone.NUMBER + }; + + static final int NORMALIZED_NUMBER_COLUMN_INDEX = 0; + static final int NUMBER_COLUMN_INDEX = 1; + + static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1"; + } + + /** + * Checks if there exists a contact with {@code Contacts.SEND_TO_VOICEMAIL} set to true. + */ + public static void checkForSendToVoicemailContact( + final Context context, final CheckForSendToVoicemailContactListener listener) { + final AsyncTask task = new AsyncTask<Object, Void, Boolean>() { + @Override + public Boolean doInBackground(Object[] params) { + if (context == null) { + return false; + } + + final Cursor cursor = context.getContentResolver().query( + Contacts.CONTENT_URI, + ContactsQuery.PROJECTION, + ContactsQuery.SELECT_SEND_TO_VOICEMAIL_TRUE, + null, + null); + + boolean hasSendToVoicemailContacts = false; + if (cursor != null) { + try { + hasSendToVoicemailContacts = cursor.getCount() > 0; + } finally { + cursor.close(); + } + } + + return hasSendToVoicemailContacts; + } + + @Override + public void onPostExecute(Boolean hasSendToVoicemailContact) { + if (listener != null) { + listener.onComplete(hasSendToVoicemailContact); + } + } + }; + task.execute(); + } + + /** + * Blocks all the phone numbers of any contacts marked as SEND_TO_VOICEMAIL, then clears the + * SEND_TO_VOICEMAIL flag on those contacts. + */ + public static void importSendToVoicemailContacts( + final Context context, final ImportSendToVoicemailContactsListener listener) { + final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler = + new FilteredNumberAsyncQueryHandler(context.getContentResolver()); + + final AsyncTask task = new AsyncTask<Object, Void, Boolean>() { + @Override + public Boolean doInBackground(Object[] params) { + if (context == null) { + return false; + } + + // Get the phone number of contacts marked as SEND_TO_VOICEMAIL. + final Cursor phoneCursor = context.getContentResolver().query( + Phone.CONTENT_URI, + PhoneQuery.PROJECTION, + PhoneQuery.SELECT_SEND_TO_VOICEMAIL_TRUE, + null, + null); + + if (phoneCursor == null) { + return false; + } + + try { + while (phoneCursor.moveToNext()) { + final String normalizedNumber = phoneCursor.getString( + PhoneQuery.NORMALIZED_NUMBER_COLUMN_INDEX); + final String number = phoneCursor.getString( + PhoneQuery.NUMBER_COLUMN_INDEX); + if (normalizedNumber != null) { + // Block the phone number of the contact. + mFilteredNumberAsyncQueryHandler.blockNumber( + null, normalizedNumber, number, null); + } + } + } finally { + phoneCursor.close(); + } + + // Clear SEND_TO_VOICEMAIL on all contacts. The setting has been imported to Dialer. + ContentValues newValues = new ContentValues(); + newValues.put(Contacts.SEND_TO_VOICEMAIL, 0); + context.getContentResolver().update( + Contacts.CONTENT_URI, + newValues, + ContactsQuery.SELECT_SEND_TO_VOICEMAIL_TRUE, + null); + + return true; + } + + @Override + public void onPostExecute(Boolean success) { + if (success) { + if (listener != null) { + listener.onImportComplete(); + } + } else if (context != null) { + String toastStr = context.getString(R.string.send_to_voicemail_import_failed); + Toast.makeText(context, toastStr, Toast.LENGTH_SHORT).show(); + } + } + }; + task.execute(); + } +} |