PhoneCallDetailsHelper.java revision 7e8ea191d0858f02b6b1c002f54c18ab798bd732
1/* 2 * Copyright (C) 2011 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 17package com.android.dialer; 18 19import android.content.res.Resources; 20import android.graphics.Typeface; 21import android.provider.ContactsContract; 22import android.provider.ContactsContract.CommonDataKinds.Phone; 23import android.telephony.PhoneNumberUtils; 24import android.text.SpannableString; 25import android.text.Spanned; 26import android.text.TextUtils; 27import android.text.format.DateUtils; 28import android.text.style.ForegroundColorSpan; 29import android.text.style.StyleSpan; 30import android.view.View; 31import android.widget.TextView; 32 33import com.android.contacts.common.test.NeededForTesting; 34import com.android.dialer.calllog.CallTypeHelper; 35import com.android.dialer.calllog.ContactInfo; 36import com.android.dialer.calllog.PhoneNumberHelper; 37 38/** 39 * Helper class to fill in the views in {@link PhoneCallDetailsViews}. 40 */ 41public class PhoneCallDetailsHelper { 42 /** The maximum number of icons will be shown to represent the call types in a group. */ 43 private static final int MAX_CALL_TYPE_ICONS = 3; 44 45 private final Resources mResources; 46 /** The injected current time in milliseconds since the epoch. Used only by tests. */ 47 private Long mCurrentTimeMillisForTest; 48 // Helper classes. 49 private final CallTypeHelper mCallTypeHelper; 50 private final PhoneNumberHelper mPhoneNumberHelper; 51 52 /** 53 * Creates a new instance of the helper. 54 * <p> 55 * Generally you should have a single instance of this helper in any context. 56 * 57 * @param resources used to look up strings 58 */ 59 public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper, 60 PhoneNumberHelper phoneNumberHelper) { 61 mResources = resources; 62 mCallTypeHelper = callTypeHelper; 63 mPhoneNumberHelper = phoneNumberHelper; 64 } 65 66 /** Fills the call details views with content. */ 67 public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details, 68 boolean isHighlighted) { 69 // Display up to a given number of icons. 70 views.callTypeIcons.clear(); 71 int count = details.callTypes.length; 72 for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) { 73 views.callTypeIcons.add(details.callTypes[index]); 74 } 75 views.callTypeIcons.requestLayout(); 76 views.callTypeIcons.setVisibility(View.VISIBLE); 77 78 // Show the total call count only if there are more than the maximum number of icons. 79 final Integer callCount; 80 if (count > MAX_CALL_TYPE_ICONS) { 81 callCount = count; 82 } else { 83 callCount = null; 84 } 85 // The color to highlight the count and date in, if any. This is based on the first call. 86 Integer highlightColor = 87 isHighlighted ? mCallTypeHelper.getHighlightedColor(details.callTypes[0]) : null; 88 89 // The date of this call, relative to the current time. 90 CharSequence dateText = 91 DateUtils.getRelativeTimeSpanString(details.date, 92 getCurrentTimeMillis(), 93 DateUtils.MINUTE_IN_MILLIS, 94 DateUtils.FORMAT_ABBREV_RELATIVE); 95 96 // Set the call count and date. 97 setCallCountAndDate(views, callCount, dateText, highlightColor); 98 99 CharSequence numberFormattedLabel = null; 100 // Only show a label if the number is shown and it is not a SIP address. 101 if (!TextUtils.isEmpty(details.number) 102 && !PhoneNumberUtils.isUriNumber(details.number.toString())) { 103 if (details.numberLabel == ContactInfo.GEOCODE_AS_LABEL) { 104 numberFormattedLabel = details.geocode; 105 } else { 106 numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType, 107 details.numberLabel); 108 } 109 } 110 111 final CharSequence nameText; 112 final CharSequence numberText; 113 final CharSequence labelText; 114 final CharSequence displayNumber = 115 mPhoneNumberHelper.getDisplayNumber(details.number, 116 details.numberPresentation, details.formattedNumber); 117 if (TextUtils.isEmpty(details.name)) { 118 nameText = displayNumber; 119 if (TextUtils.isEmpty(details.geocode) 120 || mPhoneNumberHelper.isVoicemailNumber(details.number)) { 121 numberText = mResources.getString(R.string.call_log_empty_gecode); 122 } else { 123 numberText = details.geocode; 124 } 125 labelText = numberText; 126 // We have a real phone number as "nameView" so make it always LTR 127 views.nameView.setTextDirection(View.TEXT_DIRECTION_LTR); 128 } else { 129 nameText = details.name; 130 numberText = displayNumber; 131 labelText = TextUtils.isEmpty(numberFormattedLabel) ? numberText : 132 numberFormattedLabel; 133 } 134 135 views.nameView.setText(nameText); 136 137 views.labelView.setText(labelText); 138 views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE); 139 } 140 141 /** Sets the text of the header view for the details page of a phone call. */ 142 public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) { 143 final CharSequence nameText; 144 final CharSequence displayNumber = 145 mPhoneNumberHelper.getDisplayNumber(details.number, details.numberPresentation, 146 mResources.getString(R.string.recentCalls_addToContact)); 147 if (TextUtils.isEmpty(details.name)) { 148 nameText = displayNumber; 149 } else { 150 nameText = details.name; 151 } 152 153 nameView.setText(nameText); 154 } 155 156 @NeededForTesting 157 public void setCurrentTimeForTest(long currentTimeMillis) { 158 mCurrentTimeMillisForTest = currentTimeMillis; 159 } 160 161 /** 162 * Returns the current time in milliseconds since the epoch. 163 * <p> 164 * It can be injected in tests using {@link #setCurrentTimeForTest(long)}. 165 */ 166 private long getCurrentTimeMillis() { 167 if (mCurrentTimeMillisForTest == null) { 168 return System.currentTimeMillis(); 169 } else { 170 return mCurrentTimeMillisForTest; 171 } 172 } 173 174 /** Sets the call count and date. */ 175 private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount, 176 CharSequence dateText, Integer highlightColor) { 177 // Combine the count (if present) and the date. 178 final CharSequence text; 179 if (callCount != null) { 180 text = mResources.getString( 181 R.string.call_log_item_count_and_date, callCount.intValue(), dateText); 182 } else { 183 text = dateText; 184 } 185 186 // Apply the highlight color if present. 187 final CharSequence formattedText; 188 if (highlightColor != null) { 189 formattedText = addBoldAndColor(text, highlightColor); 190 } else { 191 formattedText = text; 192 } 193 194 views.callTypeAndDate.setText(formattedText); 195 } 196 197 /** Creates a SpannableString for the given text which is bold and in the given color. */ 198 private CharSequence addBoldAndColor(CharSequence text, int color) { 199 int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE; 200 SpannableString result = new SpannableString(text); 201 result.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), flags); 202 result.setSpan(new ForegroundColorSpan(color), 0, text.length(), flags); 203 return result; 204 } 205} 206