blob: 83c59df8deb6d269cc4e7785defde87b616d2740 [file] [log] [blame]
Chiao Chengddd4e822012-12-06 12:18:01 -08001/*
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
17package com.android.contacts.editor;
18
Walter Jang2d3f31c2015-06-18 23:15:31 -070019import android.content.Context;
Walter Jang31a74ad2015-10-02 19:17:39 -070020import android.content.res.Resources;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
Walter Jangf5dfea42015-09-16 12:30:36 -070023import android.graphics.drawable.Drawable;
Marcus Hagerottfac695a2016-08-24 17:02:40 -070024import android.media.RingtoneManager;
25import android.net.Uri;
26import android.os.Build;
Walter Jangf5dfea42015-09-16 12:30:36 -070027import android.provider.ContactsContract.CommonDataKinds.Email;
28import android.provider.ContactsContract.CommonDataKinds.Event;
29import android.provider.ContactsContract.CommonDataKinds.Im;
30import android.provider.ContactsContract.CommonDataKinds.Note;
31import android.provider.ContactsContract.CommonDataKinds.Organization;
32import android.provider.ContactsContract.CommonDataKinds.Phone;
33import android.provider.ContactsContract.CommonDataKinds.Photo;
34import android.provider.ContactsContract.CommonDataKinds.Relation;
35import android.provider.ContactsContract.CommonDataKinds.SipAddress;
36import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
37import android.provider.ContactsContract.CommonDataKinds.Website;
Walter Jang2d3f31c2015-06-18 23:15:31 -070038import android.text.TextUtils;
Walter Jang31a74ad2015-10-02 19:17:39 -070039import android.widget.ImageView;
40
Chiao Chengddd4e822012-12-06 12:18:01 -080041import com.android.contacts.R;
Walter Jang31a74ad2015-10-02 19:17:39 -070042import com.android.contacts.common.ContactPhotoManager;
43import com.android.contacts.common.ContactPhotoManager.DefaultImageProvider;
44import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
45import com.android.contacts.common.ContactsUtils;
46import com.android.contacts.common.model.ValuesDelta;
Chiao Chengddd4e822012-12-06 12:18:01 -080047import com.android.contacts.common.model.dataitem.DataKind;
Walter Jang31a74ad2015-10-02 19:17:39 -070048import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
Marcus Hagerottfac695a2016-08-24 17:02:40 -070049import com.android.contacts.common.model.account.AccountDisplayInfo;
Walter Jang31a74ad2015-10-02 19:17:39 -070050import com.android.contacts.util.ContactPhotoUtils;
51import com.android.contacts.widget.QuickContactImageView;
Chiao Chengddd4e822012-12-06 12:18:01 -080052import com.google.common.collect.Maps;
53
Walter Jang31a74ad2015-10-02 19:17:39 -070054import java.io.FileNotFoundException;
Chiao Chengddd4e822012-12-06 12:18:01 -080055import java.util.HashMap;
56
Marcus Hagerottfac695a2016-08-24 17:02:40 -070057import static android.provider.ContactsContract.CommonDataKinds.GroupMembership;
58import static android.provider.ContactsContract.CommonDataKinds.StructuredName;
59import static com.android.contacts.common.util.MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors;
60
Chiao Chengddd4e822012-12-06 12:18:01 -080061/**
62 * Utility methods for creating contact editor.
63 */
64public class EditorUiUtils {
65
66 // Maps DataKind.mimeType to editor view layouts.
67 private static final HashMap<String, Integer> mimetypeLayoutMap = Maps.newHashMap();
68 static {
69 // Generally there should be a layout mapped to each existing DataKind mimetype but lots of
70 // them use the default text_fields_editor_view which we return as default so they don't
71 // need to be mapped.
72 //
73 // Other possible mime mappings are:
74 // DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME
75 // Nickname.CONTENT_ITEM_TYPE
76 // Email.CONTENT_ITEM_TYPE
77 // StructuredPostal.CONTENT_ITEM_TYPE
78 // Im.CONTENT_ITEM_TYPE
79 // Note.CONTENT_ITEM_TYPE
80 // Organization.CONTENT_ITEM_TYPE
81 // Phone.CONTENT_ITEM_TYPE
82 // SipAddress.CONTENT_ITEM_TYPE
83 // Website.CONTENT_ITEM_TYPE
84 // Relation.CONTENT_ITEM_TYPE
85 //
86 // Un-supported mime types need to mapped with -1.
87
88 mimetypeLayoutMap.put(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
89 R.layout.phonetic_name_editor_view);
90 mimetypeLayoutMap.put(StructuredName.CONTENT_ITEM_TYPE,
91 R.layout.structured_name_editor_view);
92 mimetypeLayoutMap.put(GroupMembership.CONTENT_ITEM_TYPE, -1);
93 mimetypeLayoutMap.put(Photo.CONTENT_ITEM_TYPE, -1);
94 mimetypeLayoutMap.put(Event.CONTENT_ITEM_TYPE, R.layout.event_field_editor_view);
95 }
96
97 /**
98 * Fetches a layout for a given mimetype.
99 *
100 * @param mimetype The mime type (e.g. StructuredName.CONTENT_ITEM_TYPE)
101 * @return The layout resource id.
102 */
103 public static int getLayoutResourceId(String mimetype) {
104 final Integer id = mimetypeLayoutMap.get(mimetype);
105 if (id == null) {
106 return R.layout.text_fields_editor_view;
107 }
108 return id;
109 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700110
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700111
112 public static String getAccountHeaderLabelForMyProfile(Context context,
113 AccountDisplayInfo displayableAccount) {
114 if (displayableAccount.isDeviceAccount()) {
115 return context.getString(R.string.local_profile_title);
116 } else {
117 return context.getString(R.string.external_profile_title,
118 displayableAccount.getTypeLabel());
Walter Jangc4cecc72015-06-25 10:45:50 -0700119 }
Walter Jangbe5e1b12015-10-17 11:38:29 -0700120 }
Walter Jangc4cecc72015-06-25 10:45:50 -0700121
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700122 public static String getAccountTypeHeaderLabel(Context context, AccountDisplayInfo
123 displayableAccount) {
124 if (displayableAccount.isDeviceAccount()) {
125 // Do nothing. Type label should be "Device"
126 return displayableAccount.getTypeLabel().toString();
127 } else if (displayableAccount.isGoogleAccount()) {
128 return context.getString(R.string.google_account_type_format,
129 displayableAccount.getTypeLabel());
Wenyi Wang541743c2016-06-30 12:24:39 -0700130 } else {
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700131 return context.getString(R.string.account_type_format,
132 displayableAccount.getTypeLabel());
Walter Jangdefc69c2015-08-25 16:46:43 -0700133 }
Walter Jang2d3f31c2015-06-18 23:15:31 -0700134 }
135
136 /**
137 * Returns a content description String for the container of the account information
Marcus Hagerottfac695a2016-08-24 17:02:40 -0700138 * returned by {@link #getAccountTypeHeaderLabel(Context, AccountDisplayInfo)}.
Walter Jang2d3f31c2015-06-18 23:15:31 -0700139 */
140 public static String getAccountInfoContentDescription(CharSequence accountName,
141 CharSequence accountType) {
142 final StringBuilder builder = new StringBuilder();
143 if (!TextUtils.isEmpty(accountType)) {
144 builder.append(accountType).append('\n');
145 }
146 if (!TextUtils.isEmpty(accountName)) {
Walter Jangbe5e1b12015-10-17 11:38:29 -0700147 builder.append(accountName);
Walter Jang2d3f31c2015-06-18 23:15:31 -0700148 }
149 return builder.toString();
150 }
Walter Jangf5dfea42015-09-16 12:30:36 -0700151
152 /**
153 * Return an icon that represents {@param mimeType}.
154 */
155 public static Drawable getMimeTypeDrawable(Context context, String mimeType) {
156 switch (mimeType) {
Walter Jang3e5ae0d2015-09-20 12:43:37 -0700157 case StructuredName.CONTENT_ITEM_TYPE:
158 return context.getResources().getDrawable(R.drawable.ic_person_black_24dp);
Walter Jangf5dfea42015-09-16 12:30:36 -0700159 case StructuredPostal.CONTENT_ITEM_TYPE:
160 return context.getResources().getDrawable(R.drawable.ic_place_24dp);
161 case SipAddress.CONTENT_ITEM_TYPE:
162 return context.getResources().getDrawable(R.drawable.ic_dialer_sip_black_24dp);
163 case Phone.CONTENT_ITEM_TYPE:
164 return context.getResources().getDrawable(R.drawable.ic_phone_24dp);
165 case Im.CONTENT_ITEM_TYPE:
166 return context.getResources().getDrawable(R.drawable.ic_message_24dp);
167 case Event.CONTENT_ITEM_TYPE:
168 return context.getResources().getDrawable(R.drawable.ic_event_24dp);
169 case Email.CONTENT_ITEM_TYPE:
170 return context.getResources().getDrawable(R.drawable.ic_email_24dp);
171 case Website.CONTENT_ITEM_TYPE:
172 return context.getResources().getDrawable(R.drawable.ic_public_black_24dp);
173 case Photo.CONTENT_ITEM_TYPE:
174 return context.getResources().getDrawable(R.drawable.ic_camera_alt_black_24dp);
175 case GroupMembership.CONTENT_ITEM_TYPE:
Wenyi Wang5663f082016-05-02 20:27:18 -0700176 return context.getResources().getDrawable(R.drawable.ic_menu_label);
Walter Jangf5dfea42015-09-16 12:30:36 -0700177 case Organization.CONTENT_ITEM_TYPE:
178 return context.getResources().getDrawable(R.drawable.ic_business_black_24dp);
179 case Note.CONTENT_ITEM_TYPE:
180 return context.getResources().getDrawable(R.drawable.ic_insert_comment_black_24dp);
181 case Relation.CONTENT_ITEM_TYPE:
182 return context.getResources().getDrawable(
183 R.drawable.ic_circles_extended_black_24dp);
184 default:
185 return null;
186 }
187 }
Wenyi Wang3daa9a32015-09-25 09:59:06 -0700188
189 /**
190 * Returns a ringtone string based on the ringtone URI and version #.
191 */
192 public static String getRingtoneStringFromUri(Uri pickedUri, int currentVersion) {
193 if (isNewerThanM(currentVersion)) {
194 if (pickedUri == null) return ""; // silent ringtone
195 if (RingtoneManager.isDefault(pickedUri)) return null; // default ringtone
196 }
197 if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) return null;
198 return pickedUri.toString();
199 }
200
201 /**
202 * Returns a ringtone URI, based on the string and version #.
203 */
204 public static Uri getRingtoneUriFromString(String str, int currentVersion) {
205 if (str != null) {
206 if (isNewerThanM(currentVersion) && TextUtils.isEmpty(str)) return null;
207 return Uri.parse(str);
208 }
209 return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
210 }
211
212 private static boolean isNewerThanM(int currentVersion) {
213 return currentVersion > Build.VERSION_CODES.M;
214 }
Walter Jang31a74ad2015-10-02 19:17:39 -0700215
Walter Jang3f18d612015-10-07 16:01:05 -0700216 /** Returns the {@link Photo#PHOTO_FILE_ID} from the given ValuesDelta. */
Walter Jang31a74ad2015-10-02 19:17:39 -0700217 public static Long getPhotoFileId(ValuesDelta valuesDelta) {
218 if (valuesDelta == null) return null;
Wenyi Wang2a4848a2016-03-29 01:44:01 +0000219 if (valuesDelta.getAfter() == null || valuesDelta.getAfter().get(Photo.PHOTO) == null) {
Walter Jang31a74ad2015-10-02 19:17:39 -0700220 return valuesDelta.getAsLong(Photo.PHOTO_FILE_ID);
221 }
222 return null;
223 }
224
225 /** Binds the full resolution image at the given Uri to the provided ImageView. */
226 static void loadPhoto(ContactPhotoManager contactPhotoManager, ImageView imageView,
227 Uri photoUri) {
228 final DefaultImageProvider fallbackToPreviousImage = new DefaultImageProvider() {
229 @Override
230 public void applyDefaultImage(ImageView view, int extent, boolean darkTheme,
231 DefaultImageRequest defaultImageRequest) {
232 // Before we finish setting the full sized image, don't change the current
233 // image that is set in any way.
234 }
235 };
236 contactPhotoManager.loadPhoto(imageView, photoUri, imageView.getWidth(),
237 /* darkTheme =*/ false, /* isCircular =*/ false,
238 /* defaultImageRequest =*/ null, fallbackToPreviousImage);
239 }
240
241 /** Decodes the Bitmap from the photo bytes from the given ValuesDelta. */
242 public static Bitmap getPhotoBitmap(ValuesDelta valuesDelta) {
243 if (valuesDelta == null) return null;
244 final byte[] bytes = valuesDelta.getAsByteArray(Photo.PHOTO);
245 if (bytes == null) return null;
246 return BitmapFactory.decodeByteArray(bytes, /* offset =*/ 0, bytes.length);
247 }
248
249 /** Binds the default avatar to the given ImageView and tints it to match QuickContacts. */
250 public static void setDefaultPhoto(ImageView imageView , Resources resources,
251 MaterialPalette materialPalette) {
252 // Use the default avatar drawable
253 imageView.setImageDrawable(ContactPhotoManager.getDefaultAvatarDrawableForContact(
254 resources, /* hires =*/ false, /* defaultImageRequest =*/ null));
255
256 // Tint it to match the quick contacts
257 if (imageView instanceof QuickContactImageView) {
258 ((QuickContactImageView) imageView).setTint(materialPalette == null
259 ? getDefaultPrimaryAndSecondaryColors(resources).mPrimaryColor
260 : materialPalette.mPrimaryColor);
261 }
262 }
263
264 /** Returns compressed bitmap bytes from the given Uri, scaled to the thumbnail dimensions. */
265 public static byte[] getCompressedThumbnailBitmapBytes(Context context, Uri uri)
266 throws FileNotFoundException {
267 final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(context, uri);
268 final int size = ContactsUtils.getThumbnailSize(context);
269 final Bitmap bitmapScaled = Bitmap.createScaledBitmap(
270 bitmap, size, size, /* filter =*/ false);
271 return ContactPhotoUtils.compressBitmap(bitmapScaled);
272 }
Walter Jang7b0970f2016-09-01 10:40:19 -0700273
Chiao Chengddd4e822012-12-06 12:18:01 -0800274}