summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWalter Jang <wjang@google.com>2014-10-15 18:32:44 -0700
committerWalter Jang <wjang@google.com>2014-10-29 18:03:10 -0700
commitd4c540b696b2575f32b3bb9f7f34248ea18c37b4 (patch)
treec59e97e7a5e798b0c30b8361031e9903bc37bfb3 /src
parent1db9ddd5c13d74424b864175603dcffb4c997b8e (diff)
downloadandroid_packages_apps_ContactsCommon-d4c540b696b2575f32b3bb9f7f34248ea18c37b4.tar.gz
android_packages_apps_ContactsCommon-d4c540b696b2575f32b3bb9f7f34248ea18c37b4.tar.bz2
android_packages_apps_ContactsCommon-d4c540b696b2575f32b3bb9f7f34248ea18c37b4.zip
Set TtsSpans on names and snippets that could be phone numbers
Bug: 17322140 Change-Id: I9afa9c59e1db6c5ad7123bdb37d288fa64faeddf
Diffstat (limited to 'src')
-rw-r--r--src/com/android/contacts/common/list/ContactListItemView.java16
-rw-r--r--src/com/android/contacts/common/util/ContactDisplayUtils.java78
2 files changed, 94 insertions, 0 deletions
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index e5de1f46..d90af136 100644
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -49,6 +49,7 @@ import com.android.contacts.common.ContactPresenceIconUtil;
import com.android.contacts.common.ContactStatusUtil;
import com.android.contacts.common.R;
import com.android.contacts.common.format.TextHighlighter;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.contacts.common.util.SearchUtil;
import com.android.contacts.common.util.ViewUtil;
@@ -1038,6 +1039,13 @@ public class ContactListItemView extends ViewGroup
} else {
mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix);
mSnippetView.setVisibility(VISIBLE);
+ if (ContactDisplayUtils.isPossiblePhoneNumber(text)) {
+ // Give the text-to-speech engine a hint that it's a phone number
+ mSnippetView.setContentDescription(
+ ContactDisplayUtils.getTelephoneTtsSpannable(text));
+ } else {
+ mSnippetView.setContentDescription(null);
+ }
}
}
@@ -1149,6 +1157,14 @@ public class ContactListItemView extends ViewGroup
name = mUnknownNameText;
}
setMarqueeText(getNameTextView(), name);
+
+ if (ContactDisplayUtils.isPossiblePhoneNumber(name)) {
+ // Give the text-to-speech engine a hint that it's a phone number
+ mNameTextView.setContentDescription(
+ ContactDisplayUtils.getTelephoneTtsSpannable(name.toString()));
+ } else {
+ mNameTextView.setContentDescription(null);
+ }
}
public void hideDisplayName() {
diff --git a/src/com/android/contacts/common/util/ContactDisplayUtils.java b/src/com/android/contacts/common/util/ContactDisplayUtils.java
index 7ec751a2..24bb6ef3 100644
--- a/src/com/android/contacts/common/util/ContactDisplayUtils.java
+++ b/src/com/android/contacts/common/util/ContactDisplayUtils.java
@@ -19,10 +19,18 @@ package com.android.contacts.common.util;
import static android.provider.ContactsContract.CommonDataKinds.Phone;
import android.content.Context;
+import android.telephony.PhoneNumberUtils;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.TtsSpan;
import android.util.Log;
+import android.util.Patterns;
import com.android.contacts.common.R;
+import com.android.i18n.phonenumbers.NumberParseException;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.google.common.base.Preconditions;
/**
@@ -187,4 +195,74 @@ public class ContactDisplayUtils {
}
}
+ /**
+ * Whether the given text could be a phone number.
+ *
+ * Note this will miss many things that are legitimate phone numbers, for example,
+ * phone numbers with letters.
+ */
+ public static boolean isPossiblePhoneNumber(CharSequence text) {
+ return text == null ? false : Patterns.PHONE.matcher(text.toString()).matches();
+ }
+
+ /**
+ * Returns a Spannable for the given phone number with a telephone {@link TtsSpan} set over
+ * the entire length of the given phone number.
+ */
+ public static Spannable getTelephoneTtsSpannable(String phoneNumber) {
+ final Spannable spannable = new SpannableString(phoneNumber);
+ final TtsSpan ttsSpan = getTelephoneTtsSpan(phoneNumber);
+ spannable.setSpan(ttsSpan, 0, phoneNumber.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return spannable;
+ }
+
+ /**
+ * Returns a Spannable for the given message with a telephone {@link TtsSpan} set for
+ * the given phone number text wherever it is found within the message.
+ */
+ public static Spannable getTelephoneTtsSpannable(String message, String phoneNumber) {
+ final Spannable spannable = new SpannableString(message);
+ int start = message.indexOf(phoneNumber);
+ while (start >= 0) {
+ final int end = start + phoneNumber.length();
+ final TtsSpan ttsSpan = getTelephoneTtsSpan(phoneNumber);
+ spannable.setSpan(ttsSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ start = message.indexOf(phoneNumber, end);
+ }
+ return spannable;
+ }
+
+ /**
+ * Returns a telephone {@link TtsSpan} for the given phone number.
+ */
+ public static TtsSpan getTelephoneTtsSpan(String phoneNumberString) {
+ if (phoneNumberString == null) {
+ throw new NullPointerException();
+ }
+
+ // Parse the phone number
+ final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+ PhoneNumber phoneNumber = null;
+ try {
+ // Don't supply a defaultRegion so this fails for non-international numbers because
+ // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+ // present
+ phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+ } catch (NumberParseException ignored) {
+ }
+
+ // Build a telephone tts span
+ final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+ if (phoneNumber == null) {
+ // Strip separators otherwise TalkBack will be silent
+ // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+ builder.setNumberParts(PhoneNumberUtils.stripSeparators(phoneNumberString));
+ } else {
+ if (phoneNumber.hasCountryCode()) {
+ builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+ }
+ builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+ }
+ return builder.build();
+ }
}