summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout/blocked_number_fragment.xml56
-rw-r--r--res/layout/blocked_number_header.xml40
-rw-r--r--res/layout/blocked_number_item.xml75
-rw-r--r--res/values/colors.xml7
-rw-r--r--res/values/dimens.xml8
-rw-r--r--res/values/strings.xml34
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViewHolder.java2
-rw-r--r--src/com/android/dialer/database/DialerDatabaseHelper.java6
-rw-r--r--src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java2
-rw-r--r--src/com/android/dialer/database/FilteredNumberContract.java2
-rw-r--r--src/com/android/dialer/filterednumber/BlockedNumberAdapter.java148
-rw-r--r--src/com/android/dialer/filterednumber/BlockedNumberFragment.java154
-rw-r--r--src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java15
-rw-r--r--src/com/android/dialer/settings/DialerSettingsActivity.java11
-rw-r--r--src/com/android/dialer/util/PhoneNumberUtil.java43
15 files changed, 587 insertions, 16 deletions
diff --git a/res/layout/blocked_number_fragment.xml b/res/layout/blocked_number_fragment.xml
new file mode 100644
index 000000000..b1e4d0f57
--- /dev/null
+++ b/res/layout/blocked_number_fragment.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@color/blocked_number_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.CardView
+ android:layout_width="match_parent"
+ 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">
+
+ <include layout="@layout/blocked_number_header" />
+
+ <TextView android:id="@id/android:empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/blocked_number_horizontal_margin"
+ android:paddingTop="@dimen/blocked_number_top_margin"
+ android:paddingBottom="@dimen/blocked_number_bottom_margin"
+ android:text="@string/listNoBlockedNumbers" />
+
+ </LinearLayout>
+
+ </android.support.v7.widget.CardView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml
new file mode 100644
index 000000000..fed94cc37
--- /dev/null
+++ b/res/layout/blocked_number_header.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/textView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/blockList"
+ android:paddingStart="@dimen/blocked_number_horizontal_margin"
+ android:paddingTop="@dimen/blocked_number_top_margin"
+ android:paddingBottom="@dimen/blocked_number_bottom_margin"
+ android:textColor="@color/blocked_number_accent_color"
+ style="@android:style/TextAppearance.Material.Subhead" />
+
+ <Button
+ android:id="@+id/add_number_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/blockNumber"
+ android:layout_gravity="right"
+ android:textColor="@color/blocked_number_accent_color"
+ style="?android:attr/borderlessButtonStyle" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/blocked_number_item.xml b/res/layout/blocked_number_item.xml
new file mode 100644
index 000000000..6c87533f1
--- /dev/null
+++ b/res/layout/blocked_number_item.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/caller_information"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/blocked_number_horizontal_margin"
+ android:paddingTop="@dimen/blocked_number_top_margin"
+ android:paddingBottom="@dimen/blocked_number_bottom_margin"
+ android:baselineAligned="false"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:focusable="true"
+ android:background="@color/background_dialer_white">
+
+ <QuickContactBadge
+ android:id="@+id/quick_contact_photo"
+ android:layout_width="@dimen/contact_photo_size"
+ android:layout_height="@dimen/contact_photo_size"
+ android:focusable="true" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:layout_marginStart="@dimen/blocked_number_horizontal_margin">
+
+ <TextView
+ android:id="@+id/caller_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/blocked_number_primary_text_color"
+ android:textSize="@dimen/blocked_number_primary_text_size"
+ android:includeFontPadding="false"
+ android:layout_marginBottom="5dp"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/caller_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/blocked_number_secondary_text_color"
+ android:textSize="@dimen/blocked_number_secondary_text_size"
+ android:layout_marginBottom="1dp"
+ android:singleLine="true" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/delete_button"
+ android:layout_width="@dimen/blocked_number_delete_icon_size"
+ android:layout_height="@dimen/blocked_number_delete_icon_size"
+ android:layout_marginEnd="16dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_remove"
+ android:scaleType="center"
+ android:tint="@color/delete_icon_tint"
+ android:contentDescription="@string/description_blocked_number_list_delete" />
+
+</LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8ce3c17ba..a747927d1 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -104,4 +104,11 @@
<color name="floating_action_button_touch_tint">#80ffffff</color>
<color name="call_log_action_divider">#eeeeee</color>
+
+ <!-- Colors for blocked numbers list -->
+ <color name="blocked_number_primary_text_color">@color/dialtacts_primary_text_color</color>
+ <color name="blocked_number_secondary_text_color">@color/dialtacts_secondary_text_color</color>
+ <color name="delete_icon_tint">#6D6D6D</color>
+ <color name="blocked_number_background">#E0E0E0</color>
+ <color name="blocked_number_accent_color">#42A5F5</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 776cd1150..b5acf2019 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -147,4 +147,12 @@
<dimen name="promo_card_line_spacing">4dp</dimen>
<dimen name="voicemail_playback_top_padding">12dp</dimen>
+
+ <!-- Size of entries in blocked numbers list -->
+ <dimen name="blocked_number_horizontal_margin">16dp</dimen>
+ <dimen name="blocked_number_top_margin">16dp</dimen>
+ <dimen name="blocked_number_bottom_margin">16dp</dimen>
+ <dimen name="blocked_number_primary_text_size">16sp</dimen>
+ <dimen name="blocked_number_secondary_text_size">12sp</dimen>
+ <dimen name="blocked_number_delete_icon_size">32dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7bd88baef..093aa190e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -805,6 +805,40 @@
<!-- Label for the call settings section [CHAR LIMIT=30] -->
<string name="call_settings_label">Calls</string>
+ <!-- Label for the blocked calls settings section [CHAR LIMIT=30] -->
+ <string name="blocked_calls_settings_label">Spam and blocked calls</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]-->
+ <string name="description_blocked_number_list_delete">Unblock number</string>
+
+ <!-- Displayed in the blocked numbers list when there are no blocked numbers.
+ [CHAR LIMIT=NONE] -->
+ <string name="listNoBlockedNumbers">No blocked numbers</string>
+
+ <!-- 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] -->
+ <string name="blockList">Block list</string>
+
+ <!-- Label for progress dialog when validating a number to be added to the block list.
+ [CHAR LIMIT=64] -->
+ <string name="checkingNumber">Checking
+ <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
+ </string>
+
+ <!-- Error message shown when user tries to add invalid number to the block list.
+ [CHAR LIMIT=64] -->
+ <string name="invalidNumber"><xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
+ is invalid.</string>
+
+ <!-- Error message shown when user tries to add a number to the block list that was already
+ blocked. [CHAR LIMIT=64] -->
+ <string name="alreadyBlocked"><xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
+ is already blocked.</string>
+
<!-- Label for the phone account settings [CHAR LIMIT=30] -->
<string name="phone_account_settings_label">Calling accounts</string>
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 521b2a429..7fc62a222 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -320,6 +320,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
FilterNumberDialogFragment.newInstance(blockId, info.normalizedNumber,
number, countryIso, info.formattedNumber);
newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
+ newFragment.setParentView(
+ ((Activity) mContext).findViewById(R.id.floating_action_button_container));
newFragment.show(((Activity) mContext).getFragmentManager(),
FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
return true;
diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java
index d36a0f6d8..271afeed3 100644
--- a/src/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/src/com/android/dialer/database/DialerDatabaseHelper.java
@@ -75,7 +75,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
* 0-98 KitKat
* </pre>
*/
- public static final int DATABASE_VERSION = 6;
+ public static final int DATABASE_VERSION = 7;
public static final String DATABASE_NAME = "dialer.db";
/**
@@ -440,7 +440,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
return;
}
- if (oldVersion < 6) {
+ if (oldVersion < 7) {
db.execSQL("DROP TABLE IF EXISTS " + Tables.FILTERED_NUMBER_TABLE);
db.execSQL("CREATE TABLE " + Tables.FILTERED_NUMBER_TABLE + " ("
+ FilteredNumberColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
@@ -453,7 +453,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
+ FilteredNumberColumns.TYPE + " INTEGER,"
+ FilteredNumberColumns.SOURCE + " INTEGER"
+ ");");
- oldVersion = 6;
+ oldVersion = 7;
}
if (oldVersion != DATABASE_VERSION) {
diff --git a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
index cedde27f6..061d62883 100644
--- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
+++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
@@ -121,7 +121,7 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler {
isBlocked(listener, normalizedNumber);
}
- private String getNormalizedNumber(String number, String countryIso) {
+ public static String getNormalizedNumber(String number, String countryIso) {
if (PhoneNumberHelper.isUriNumber(number)) {
return number;
} else {
diff --git a/src/com/android/dialer/database/FilteredNumberContract.java b/src/com/android/dialer/database/FilteredNumberContract.java
index 0ec171b15..38c49dc9d 100644
--- a/src/com/android/dialer/database/FilteredNumberContract.java
+++ b/src/com/android/dialer/database/FilteredNumberContract.java
@@ -61,7 +61,7 @@ public final class FilteredNumberContract {
public interface FilteredNumberColumns {
// TYPE: INTEGER
- static final String _ID = "id";
+ static final String _ID = "_id";
/**
* Represents the number to be filtered, normalized to compare phone numbers for equality.
*
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java b/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java
new file mode 100644
index 000000000..504b5205b
--- /dev/null
+++ b/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java
@@ -0,0 +1,148 @@
+/*
+ * 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.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.provider.ContactsContract;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.QuickContactBadge;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+
+import com.android.contacts.common.ContactPhotoManager;
+import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.util.UriUtils;
+import com.android.dialer.R;
+import com.android.dialer.calllog.ContactInfo;
+import com.android.dialer.calllog.ContactInfoHelper;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
+import com.android.dialer.util.PhoneNumberUtil;
+
+public class BlockedNumberAdapter extends SimpleCursorAdapter {
+
+ private Context mContext;
+ private ContactInfoHelper mContactInfoHelper;
+ private Resources mResources;
+ private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
+ private ContactPhotoManager mContactPhotoManager;
+ private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
+
+ public BlockedNumberAdapter(Context context,
+ FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) {
+ super(context, R.layout.blocked_number_item, null, new String[]{}, new int[]{}, 0);
+ mContext = context;
+ mContactInfoHelper = new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context));
+ mContactPhotoManager = ContactPhotoManager.getInstance(context);
+ mResources = context.getResources();
+ mFilteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler;
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ super.bindView(view, context, cursor);
+ final TextView callerName = (TextView) view.findViewById(R.id.caller_name);
+ final TextView callerNumber = (TextView) view.findViewById(R.id.caller_number);
+ final View deleteNumber = view.findViewById(R.id.delete_button);
+ final QuickContactBadge quickContactBadge =
+ (QuickContactBadge) view.findViewById(R.id.quick_contact_photo);
+ quickContactBadge.setOverlay(null);
+ quickContactBadge.setPrioritizedMimeType(
+ ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
+
+ final Integer id = cursor.getInt(cursor.getColumnIndex(FilteredNumberColumns._ID));
+ final String countryIso = cursor.getString(cursor.getColumnIndex(
+ FilteredNumberColumns.COUNTRY_ISO));
+ final String number = cursor.getString(cursor.getColumnIndex(FilteredNumberColumns.NUMBER));
+ final String normalizedNumber = cursor.getString(cursor.getColumnIndex(
+ FilteredNumberColumns.NORMALIZED_NUMBER));
+ final ContactInfo info = mContactInfoHelper.lookupNumber(number, countryIso);
+ final CharSequence locationOrType = getNumberTypeOrLocation(info);
+ final String displayNumber = getDisplayNumber(info);
+ final String displayNumberStr = mBidiFormatter.unicodeWrap(
+ displayNumber.toString(), TextDirectionHeuristics.LTR);
+
+ deleteNumber.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ FilterNumberDialogFragment newFragment =
+ FilterNumberDialogFragment.newInstance(id, normalizedNumber, number,
+ countryIso, displayNumber);
+ newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
+ newFragment.setParentView(view);
+ newFragment.show(((Activity) mContext).getFragmentManager(),
+ FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
+ }
+ });
+
+ String nameForDefaultImage;
+ if (!TextUtils.isEmpty(info.name)) {
+ nameForDefaultImage = info.name;
+ callerName.setText(info.name);
+ callerNumber.setText(locationOrType + " " + displayNumberStr);
+ } else {
+ nameForDefaultImage = displayNumber;
+ callerName.setText(displayNumberStr);
+ if (!TextUtils.isEmpty(locationOrType)) {
+ callerNumber.setText(locationOrType);
+ callerNumber.setVisibility(View.VISIBLE);
+ } else {
+ callerNumber.setVisibility(View.GONE);
+ }
+ }
+ loadContactPhoto(info, nameForDefaultImage, quickContactBadge);
+ }
+
+ private void loadContactPhoto(ContactInfo info, String displayName, QuickContactBadge badge) {
+ final String lookupKey = info.lookupUri == null
+ ? null : UriUtils.getLookupKeyFromUri(info.lookupUri);
+ final int contactType = mContactInfoHelper.isBusiness(info.sourceType)
+ ? ContactPhotoManager.TYPE_BUSINESS : ContactPhotoManager.TYPE_DEFAULT;
+ final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
+ contactType, true /* isCircular */);
+ badge.assignContactUri(info.lookupUri);
+ badge.setContentDescription(
+ mResources.getString(R.string.description_contact_details, displayName));
+ mContactPhotoManager.loadDirectoryPhoto(badge, info.photoUri,
+ false /* darkTheme */, true /* isCircular */, request);
+ }
+
+ private String getDisplayNumber(ContactInfo info) {
+ if (!TextUtils.isEmpty(info.formattedNumber)) {
+ return info.formattedNumber;
+ } else if (!TextUtils.isEmpty(info.number)) {
+ return info.number;
+ } else {
+ return "";
+ }
+ }
+
+ private CharSequence getNumberTypeOrLocation(ContactInfo info) {
+ if (!TextUtils.isEmpty(info.name)) {
+ return ContactsContract.CommonDataKinds.Phone.getTypeLabel(mResources, info.type,
+ info.label);
+ } else {
+ return PhoneNumberUtil.getGeoDescription(mContext, info.number);
+ }
+ }
+}
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
new file mode 100644
index 000000000..a65013ac6
--- /dev/null
+++ b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
@@ -0,0 +1,154 @@
+/*
+ * 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.app.AlertDialog;
+import android.app.ListFragment;
+import android.app.LoaderManager;
+import android.content.CursorLoader;
+import android.content.DialogInterface;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.dialog.IndeterminateProgressDialog;
+import com.android.dialer.R;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener;
+import com.android.dialer.database.FilteredNumberContract;
+
+public class BlockedNumberFragment extends ListFragment implements
+ LoaderManager.LoaderCallbacks<Cursor>, View.OnClickListener {
+
+ private BlockedNumberAdapter mAdapter;
+ private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ getListView().addHeaderView(inflater.inflate(R.layout.blocked_number_header, null));
+ mFilteredNumberAsyncQueryHandler =
+ new FilteredNumberAsyncQueryHandler(getActivity().getContentResolver());
+ if (mAdapter == null) {
+ mAdapter = new BlockedNumberAdapter(getContext(), mFilteredNumberAsyncQueryHandler);
+ }
+ setListAdapter(mAdapter);
+ final Button addNumberBtn = (Button) getActivity().findViewById(R.id.add_number_button);
+ addNumberBtn.setOnClickListener(this);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ setListAdapter(null);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getLoaderManager().initLoader(0, null, this);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.blocked_number_fragment, container, false);
+ return view;
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ final String[] projection = {
+ FilteredNumberContract.FilteredNumberColumns._ID,
+ FilteredNumberContract.FilteredNumberColumns.COUNTRY_ISO,
+ FilteredNumberContract.FilteredNumberColumns.NUMBER,
+ FilteredNumberContract.FilteredNumberColumns.NORMALIZED_NUMBER
+ };
+ final String selection = FilteredNumberContract.FilteredNumberColumns.TYPE
+ + "=" + FilteredNumberContract.FilteredNumberTypes.BLOCKED_NUMBER;
+ final CursorLoader cursorLoader = new CursorLoader(
+ getContext(), FilteredNumberContract.FilteredNumber.CONTENT_URI, projection,
+ selection, null, null);
+ return cursorLoader;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mAdapter.swapCursor(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ mAdapter.swapCursor(null);
+ }
+
+ @Override
+ public void onClick(final View v) {
+ final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
+ final EditText numberField = new EditText(getContext());
+ final DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ final String number = numberField.getText().toString();
+ final IndeterminateProgressDialog progressDialog =
+ IndeterminateProgressDialog.show(getFragmentManager(),
+ getString(R.string.checkingNumber, number), null, 1000);
+ final String normalizedNumber =
+ FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+ if (normalizedNumber == null) {
+ progressDialog.dismiss();
+ Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+ Toast.LENGTH_LONG).show();
+ } else {
+ final OnCheckBlockedListener onCheckListener = new OnCheckBlockedListener() {
+ @Override
+ public void onCheckComplete(Integer id) {
+ progressDialog.dismiss();
+ if (id == null) {
+ FilterNumberDialogFragment newFragment =
+ FilterNumberDialogFragment.newInstance(id, normalizedNumber,
+ number, countryIso, number);
+ newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
+ newFragment.setParentView(v);
+ newFragment.show(getActivity().getFragmentManager(),
+ FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
+ } else {
+ Toast.makeText(getContext(),
+ getString(R.string.alreadyBlocked, number),
+ Toast.LENGTH_LONG).show();
+ }
+ }
+ };
+ mFilteredNumberAsyncQueryHandler.isBlocked(
+ onCheckListener, normalizedNumber, number, countryIso);
+ }
+ }
+ };
+ new AlertDialog.Builder(getContext())
+ .setTitle(getString(R.string.blockNumber))
+ .setView(numberField)
+ .setPositiveButton(getString(R.string.blockNumberOk), okListener)
+ .setNegativeButton(android.R.string.cancel, null)
+ .show();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index f94d0f842..e9a88c845 100644
--- a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
+++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
@@ -39,11 +39,16 @@ public class FilterNumberDialogFragment extends DialogFragment {
private static final String ARG_DISPLAY_NUMBER = "argDisplayNumber";
private FilteredNumberAsyncQueryHandler mHandler;
+ private View mParentView;
public void setQueryHandler (FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) {
mHandler = filteredNumberAsyncQueryHandler;
}
+ public void setParentView(View view) {
+ mParentView = view;
+ }
+
public static FilterNumberDialogFragment newInstance(Integer blockId, String normalizedNumber,
String number, String countryIso, String displayNumber) {
final FilterNumberDialogFragment fragment = new FilterNumberDialogFragment();
@@ -91,7 +96,6 @@ public class FilterNumberDialogFragment extends DialogFragment {
}
public void blockNumber() {
- final View view = getActivity().findViewById(R.id.floating_action_button_container);
final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
final String message = getString(R.string.snackbar_number_blocked, displayNumber);
final String undoMessage = getString(R.string.snackbar_number_unblocked, displayNumber);
@@ -99,7 +103,7 @@ public class FilterNumberDialogFragment extends DialogFragment {
new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() {
@Override
public void onUnblockComplete(int rows, ContentValues values) {
- Snackbar.make(view, undoMessage, Snackbar.LENGTH_LONG).show();
+ Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
}
};
@@ -107,7 +111,7 @@ public class FilterNumberDialogFragment extends DialogFragment {
new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() {
@Override
public void onBlockComplete(final Uri uri) {
- Snackbar.make(view, message, Snackbar.LENGTH_LONG)
+ Snackbar.make(mParentView, message, Snackbar.LENGTH_LONG)
.setAction(R.string.block_number_undo,
// Delete the newly created row on 'undo'.
new View.OnClickListener() {
@@ -123,7 +127,6 @@ public class FilterNumberDialogFragment extends DialogFragment {
}
public void unblockNumber() {
- final View view = getActivity().findViewById(R.id.floating_action_button_container);
final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
final String message = getString(R.string.snackbar_number_unblocked, displayNumber);
final String undoMessage = getString(R.string.snackbar_number_blocked, displayNumber);
@@ -131,14 +134,14 @@ public class FilterNumberDialogFragment extends DialogFragment {
new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() {
@Override
public void onBlockComplete(final Uri uri) {
- Snackbar.make(view, undoMessage, Snackbar.LENGTH_LONG).show();
+ Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
}
};
mHandler.unblock(
new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() {
@Override
public void onUnblockComplete(int rows, final ContentValues values) {
- Snackbar.make(view, message, Snackbar.LENGTH_LONG)
+ Snackbar.make(mParentView, message, Snackbar.LENGTH_LONG)
.setAction(R.string.block_number_undo,
new View.OnClickListener() {
// Re-insert the row on 'undo', with a new ID.
diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java
index 01a9fcf5f..2b7277224 100644
--- a/src/com/android/dialer/settings/DialerSettingsActivity.java
+++ b/src/com/android/dialer/settings/DialerSettingsActivity.java
@@ -15,24 +15,20 @@
*/
package com.android.dialer.settings;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.os.Process;
import android.os.UserManager;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
-import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;
-import com.android.contacts.common.util.PermissionsUtil;
import com.android.dialer.R;
+import com.android.dialer.filterednumber.BlockedNumberFragment;
import java.util.List;
@@ -90,6 +86,11 @@ public class DialerSettingsActivity extends AppCompatPreferenceActivity {
target.add(phoneAccountSettingsHeader);
}
+ Header blockedCallsHeader = new Header();
+ blockedCallsHeader.titleRes = R.string.blocked_calls_settings_label;
+ blockedCallsHeader.fragment = BlockedNumberFragment.class.getName();
+ target.add(blockedCallsHeader);
+
if (telephonyManager.isTtyModeSupported()
|| telephonyManager.isHearingAidCompatibilitySupported()) {
Header accessibilitySettingsHeader = new Header();
diff --git a/src/com/android/dialer/util/PhoneNumberUtil.java b/src/com/android/dialer/util/PhoneNumberUtil.java
index 84f58aa85..539d8b9ba 100644
--- a/src/com/android/dialer/util/PhoneNumberUtil.java
+++ b/src/com/android/dialer/util/PhoneNumberUtil.java
@@ -25,13 +25,19 @@ import android.util.Log;
import android.util.Pair;
import com.android.contacts.common.util.PhoneNumberHelper;
+import com.android.contacts.common.util.TelephonyManagerUtils;
import com.google.common.collect.Sets;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.Phonenumber;
+import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class PhoneNumberUtil {
+ private static final String TAG = "PhoneNumberUtil";
private static final Set<String> LEGACY_UNKNOWN_NUMBERS = Sets.newHashSet("-1", "-2", "-3");
/** Returns true if it is possible to place a call to the given number. */
@@ -92,4 +98,41 @@ public class PhoneNumberUtil {
public static boolean isLegacyUnknownNumbers(CharSequence number) {
return number != null && LEGACY_UNKNOWN_NUMBERS.contains(number.toString());
}
+
+ /**
+ * @return a geographical description string for the specified number.
+ * @see com.android.i18n.phonenumbers.PhoneNumberOfflineGeocoder
+ */
+ public static String getGeoDescription(Context context, String number) {
+ Log.v(TAG, "getGeoDescription('" + number + "')...");
+
+ if (TextUtils.isEmpty(number)) {
+ return null;
+ }
+
+ com.google.i18n.phonenumbers.PhoneNumberUtil util =
+ com.google.i18n.phonenumbers.PhoneNumberUtil.getInstance();
+ PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
+
+ Locale locale = context.getResources().getConfiguration().locale;
+ String countryIso = TelephonyManagerUtils.getCurrentCountryIso(context, locale);
+ Phonenumber.PhoneNumber pn = null;
+ try {
+ Log.v(TAG, "parsing '" + number
+ + "' for countryIso '" + countryIso + "'...");
+ pn = util.parse(number, countryIso);
+ Log.v(TAG, "- parsed number: " + pn);
+ } catch (NumberParseException e) {
+ Log.v(TAG, "getGeoDescription: NumberParseException for incoming number '" +
+ number + "'");
+ }
+
+ if (pn != null) {
+ String description = geocoder.getDescriptionForNumber(pn, locale);
+ Log.v(TAG, "- got description: '" + description + "'");
+ return description;
+ }
+
+ return null;
+ }
}