1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.contacts.common.util; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.provider.ContactsContract.CommonDataKinds.Phone; 22 import android.support.annotation.NonNull; 23 import android.support.annotation.Nullable; 24 import android.telephony.PhoneNumberUtils; 25 import android.text.Spannable; 26 import android.text.SpannableString; 27 import android.text.TextUtils; 28 import android.text.style.TtsSpan; 29 import android.util.Patterns; 30 import com.android.dialer.common.LogUtil; 31 import com.android.dialer.contacts.resources.R; 32 import java.util.Objects; 33 34 /** Methods for handling various contact data labels. */ 35 public class ContactDisplayUtils { 36 37 public static final int INTERACTION_CALL = 1; 38 public static final int INTERACTION_SMS = 2; 39 40 /** 41 * Checks if the given data type is a custom type. 42 * 43 * @param type Phone data type. 44 * @return {@literal true} if the type is custom. {@literal false} if not. 45 */ isCustomPhoneType(Integer type)46 public static boolean isCustomPhoneType(Integer type) { 47 return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT; 48 } 49 50 /** 51 * Gets a display label for a given phone type. 52 * 53 * @param type The type of number. 54 * @param customLabel A custom label to use if the phone is determined to be of custom type 55 * determined by {@link #isCustomPhoneType(Integer))} 56 * @param interactionType whether this is a call or sms. Either {@link #INTERACTION_CALL} or 57 * {@link #INTERACTION_SMS}. 58 * @param context The application context. 59 * @return An appropriate string label 60 */ getLabelForCallOrSms( Integer type, CharSequence customLabel, int interactionType, @NonNull Context context)61 public static CharSequence getLabelForCallOrSms( 62 Integer type, CharSequence customLabel, int interactionType, @NonNull Context context) { 63 Objects.requireNonNull(context); 64 65 if (isCustomPhoneType(type)) { 66 return (customLabel == null) ? "" : customLabel; 67 } else { 68 int resId; 69 if (interactionType == INTERACTION_SMS) { 70 resId = getSmsLabelResourceId(type); 71 } else { 72 resId = getPhoneLabelResourceId(type); 73 if (interactionType != INTERACTION_CALL) { 74 LogUtil.e( 75 "ContactDisplayUtils.getLabelForCallOrSms", 76 "un-recognized interaction type: " 77 + interactionType 78 + ". Defaulting to ContactDisplayUtils.INTERACTION_CALL."); 79 } 80 } 81 82 return context.getResources().getText(resId); 83 } 84 } 85 86 /** 87 * Find a label for calling. 88 * 89 * @param type The type of number. 90 * @return An appropriate string label. 91 */ getPhoneLabelResourceId(Integer type)92 public static int getPhoneLabelResourceId(Integer type) { 93 if (type == null) { 94 return R.string.call_other; 95 } 96 switch (type) { 97 case Phone.TYPE_HOME: 98 return R.string.call_home; 99 case Phone.TYPE_MOBILE: 100 return R.string.call_mobile; 101 case Phone.TYPE_WORK: 102 return R.string.call_work; 103 case Phone.TYPE_FAX_WORK: 104 return R.string.call_fax_work; 105 case Phone.TYPE_FAX_HOME: 106 return R.string.call_fax_home; 107 case Phone.TYPE_PAGER: 108 return R.string.call_pager; 109 case Phone.TYPE_OTHER: 110 return R.string.call_other; 111 case Phone.TYPE_CALLBACK: 112 return R.string.call_callback; 113 case Phone.TYPE_CAR: 114 return R.string.call_car; 115 case Phone.TYPE_COMPANY_MAIN: 116 return R.string.call_company_main; 117 case Phone.TYPE_ISDN: 118 return R.string.call_isdn; 119 case Phone.TYPE_MAIN: 120 return R.string.call_main; 121 case Phone.TYPE_OTHER_FAX: 122 return R.string.call_other_fax; 123 case Phone.TYPE_RADIO: 124 return R.string.call_radio; 125 case Phone.TYPE_TELEX: 126 return R.string.call_telex; 127 case Phone.TYPE_TTY_TDD: 128 return R.string.call_tty_tdd; 129 case Phone.TYPE_WORK_MOBILE: 130 return R.string.call_work_mobile; 131 case Phone.TYPE_WORK_PAGER: 132 return R.string.call_work_pager; 133 case Phone.TYPE_ASSISTANT: 134 return R.string.call_assistant; 135 case Phone.TYPE_MMS: 136 return R.string.call_mms; 137 default: 138 return R.string.call_custom; 139 } 140 } 141 142 /** 143 * Find a label for sending an sms. 144 * 145 * @param type The type of number. 146 * @return An appropriate string label. 147 */ getSmsLabelResourceId(Integer type)148 public static int getSmsLabelResourceId(Integer type) { 149 if (type == null) { 150 return R.string.sms_other; 151 } 152 switch (type) { 153 case Phone.TYPE_HOME: 154 return R.string.sms_home; 155 case Phone.TYPE_MOBILE: 156 return R.string.sms_mobile; 157 case Phone.TYPE_WORK: 158 return R.string.sms_work; 159 case Phone.TYPE_FAX_WORK: 160 return R.string.sms_fax_work; 161 case Phone.TYPE_FAX_HOME: 162 return R.string.sms_fax_home; 163 case Phone.TYPE_PAGER: 164 return R.string.sms_pager; 165 case Phone.TYPE_OTHER: 166 return R.string.sms_other; 167 case Phone.TYPE_CALLBACK: 168 return R.string.sms_callback; 169 case Phone.TYPE_CAR: 170 return R.string.sms_car; 171 case Phone.TYPE_COMPANY_MAIN: 172 return R.string.sms_company_main; 173 case Phone.TYPE_ISDN: 174 return R.string.sms_isdn; 175 case Phone.TYPE_MAIN: 176 return R.string.sms_main; 177 case Phone.TYPE_OTHER_FAX: 178 return R.string.sms_other_fax; 179 case Phone.TYPE_RADIO: 180 return R.string.sms_radio; 181 case Phone.TYPE_TELEX: 182 return R.string.sms_telex; 183 case Phone.TYPE_TTY_TDD: 184 return R.string.sms_tty_tdd; 185 case Phone.TYPE_WORK_MOBILE: 186 return R.string.sms_work_mobile; 187 case Phone.TYPE_WORK_PAGER: 188 return R.string.sms_work_pager; 189 case Phone.TYPE_ASSISTANT: 190 return R.string.sms_assistant; 191 case Phone.TYPE_MMS: 192 return R.string.sms_mms; 193 default: 194 return R.string.sms_custom; 195 } 196 } 197 198 /** 199 * Whether the given text could be a phone number. 200 * 201 * <p>Note this will miss many things that are legitimate phone numbers, for example, phone 202 * numbers with letters. 203 */ isPossiblePhoneNumber(CharSequence text)204 public static boolean isPossiblePhoneNumber(CharSequence text) { 205 return text != null && Patterns.PHONE.matcher(text.toString()).matches(); 206 } 207 208 /** 209 * Returns a Spannable for the given message with a telephone {@link TtsSpan} set for the given 210 * phone number text wherever it is found within the message. 211 */ getTelephoneTtsSpannable( @ullable String message, @Nullable String phoneNumber)212 public static Spannable getTelephoneTtsSpannable( 213 @Nullable String message, @Nullable String phoneNumber) { 214 if (message == null) { 215 return null; 216 } 217 final Spannable spannable = new SpannableString(message); 218 int start = TextUtils.isEmpty(phoneNumber) ? -1 : message.indexOf(phoneNumber); 219 while (start >= 0) { 220 final int end = start + phoneNumber.length(); 221 final TtsSpan ttsSpan = PhoneNumberUtils.createTtsSpan(phoneNumber); 222 spannable.setSpan( 223 ttsSpan, 224 start, 225 end, 226 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // this is consistenly done in a misleading way.. 227 start = message.indexOf(phoneNumber, end); 228 } 229 return spannable; 230 } 231 232 /** 233 * Retrieves a string from a string template that takes 1 phone number as argument, span the 234 * number with a telephone {@link TtsSpan}, and return the spanned string. 235 * 236 * @param resources to retrieve the string from 237 * @param stringId ID of the string 238 * @param number to pass in the template 239 * @return CharSequence with the phone number wrapped in a TtsSpan 240 */ getTtsSpannedPhoneNumber( Resources resources, int stringId, String number)241 public static CharSequence getTtsSpannedPhoneNumber( 242 Resources resources, int stringId, String number) { 243 String msg = resources.getString(stringId, number); 244 return ContactDisplayUtils.getTelephoneTtsSpannable(msg, number); 245 } 246 } 247