ContactStatusLoader.java revision 8b9f2a7284337bfb23d5e2f8de9f1c70cb9532a1
1/* 2 * Copyright (C) 2010 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.email.activity; 18 19import com.android.email.R; 20import com.android.email.Utility; 21 22import android.content.AsyncTaskLoader; 23import android.content.ContentUris; 24import android.content.Context; 25import android.database.Cursor; 26import android.graphics.Bitmap; 27import android.graphics.BitmapFactory; 28import android.net.Uri; 29import android.provider.ContactsContract.CommonDataKinds.Email; 30import android.provider.ContactsContract.CommonDataKinds.Photo; 31import android.provider.ContactsContract.Contacts; 32import android.provider.ContactsContract.Data; 33import android.provider.ContactsContract.StatusUpdates; 34import android.util.Log; 35 36/** 37 * Loader to load presence statuses and the contact photoes. 38 */ 39public class ContactStatusLoader extends AsyncTaskLoader<ContactStatusLoader.Result> { 40 public static final int PRESENCE_UNKNOWN_RESOURCE_ID = R.drawable.presence_inactive; 41 42 /** email address -> photo id, presence */ 43 /* package */ static final String[] PROJECTION_PHOTO_ID_PRESENCE = new String[] { 44 Contacts.PHOTO_ID, 45 Contacts.CONTACT_PRESENCE 46 }; 47 private static final int COLUMN_PHOTO_ID = 0; 48 private static final int COLUMN_PRESENCE = 1; 49 50 /** photo id -> photo data */ 51 /* package */ static final String[] PHOTO_PROJECTION = new String[] { 52 Photo.PHOTO 53 }; 54 private static final int PHOTO_COLUMN = 0; 55 56 private final Context mContext; 57 private final String mEmailAddress; 58 59 /** 60 * Class that encapsulates the result. 61 */ 62 public static class Result { 63 public static final Result UNKNOWN = new Result(null, PRESENCE_UNKNOWN_RESOURCE_ID, null); 64 65 /** Contact photo. Null if unknown */ 66 public final Bitmap mPhoto; 67 68 /** Presence image resource ID. Always has a valid value, even if unknown. */ 69 public final int mPresenceResId; 70 71 /** URI for opening quick contact. Null if unknown. */ 72 public final Uri mLookupUri; 73 74 public Result(Bitmap photo, int presenceResId, Uri lookupUri) { 75 mPhoto = photo; 76 mPresenceResId = presenceResId; 77 mLookupUri = lookupUri; 78 } 79 } 80 81 public ContactStatusLoader(Context context, String emailAddress) { 82 super(context); 83 mContext = context; 84 mEmailAddress = emailAddress; 85 } 86 87 @Override 88 public Result loadInBackground() { 89 return load(mContext, mEmailAddress); 90 } 91 92 /** 93 * Load synchronously. 94 * 95 * Used to fetch a photo for notification, in which calls the callsite is already on a worker 96 * thread. 97 */ 98 public static Result load(Context context, String emailAddress) { 99 // Load photo-id and presence status. 100 Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)); 101 Cursor c = context.getContentResolver().query( 102 uri, 103 PROJECTION_PHOTO_ID_PRESENCE, null, null, null); 104 if (c == null) { 105 return Result.UNKNOWN; 106 } 107 final long photoId; 108 final int presenceStatus; 109 try { 110 if (!c.moveToFirst()) { 111 return Result.UNKNOWN; 112 } 113 photoId = c.getLong(COLUMN_PHOTO_ID); 114 presenceStatus = c.getInt(COLUMN_PRESENCE); 115 } finally { 116 c.close(); 117 } 118 119 // Convert presence status into the res id. 120 final int presenceStatusResId = StatusUpdates.getPresenceIconResourceId(presenceStatus); 121 122 // load photo from photo-id. 123 Bitmap photo = null; 124 if (photoId != -1) { 125 final byte[] photoData = Utility.getFirstRowBlob(context, 126 ContentUris.withAppendedId(Data.CONTENT_URI, photoId), PHOTO_PROJECTION, 127 null, null, null, PHOTO_COLUMN, null); 128 if (photoData != null) { 129 try { 130 photo = BitmapFactory.decodeByteArray(photoData, 0, photoData.length, null); 131 } catch (OutOfMemoryError e) { 132 Log.d(com.android.email.Email.LOG_TAG, 133 "Decoding bitmap failed with " + e.getMessage()); 134 } 135 } 136 } 137 138 // Get lookup URI 139 final Uri lookupUri = Data.getContactLookupUri(context.getContentResolver(), uri); 140 return new Result(photo, presenceStatusResId, lookupUri); 141 } 142 143 @Override 144 protected void onStartLoading() { 145 cancelLoad(); 146 forceLoad(); 147 } 148 149 @Override 150 protected void onStopLoading() { 151 cancelLoad(); 152 } 153 154 @Override 155 protected void onReset() { 156 stopLoading(); 157 } 158} 159