diff options
author | Walter Jang <wjang@google.com> | 2014-10-15 18:32:44 -0700 |
---|---|---|
committer | Walter Jang <wjang@google.com> | 2014-10-29 18:03:10 -0700 |
commit | d4c540b696b2575f32b3bb9f7f34248ea18c37b4 (patch) | |
tree | c59e97e7a5e798b0c30b8361031e9903bc37bfb3 /src | |
parent | 1db9ddd5c13d74424b864175603dcffb4c997b8e (diff) | |
download | android_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.java | 16 | ||||
-rw-r--r-- | src/com/android/contacts/common/util/ContactDisplayUtils.java | 78 |
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(); + } } |