ContactStatusLoader.java revision 958b15e8f30fd4e9eae1b05d48cb9a817326be6d
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.emailcommon.Logging; 20import com.android.emailcommon.utility.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 photo. 38 */ 39public class ContactStatusLoader extends AsyncTaskLoader<ContactStatusLoader.Result> { 40 public static final int PRESENCE_UNKNOWN_RESOURCE_ID = android.R.drawable.presence_offline; 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 getContactInfo(mContext, mEmailAddress); 90 } 91 92 /** 93 * Synchronously loads contact data. 94 * 95 * NOTE: DO NOT CALL THIS METHOD FROM THE UI THREAD (DATABASE ACCESS) 96 */ 97 public static Result getContactInfo(Context context, String emailAddress) { 98 // Load photo-id and presence status. 99 Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)); 100 Cursor c = context.getContentResolver().query( 101 uri, 102 PROJECTION_PHOTO_ID_PRESENCE, null, null, null); 103 if (c == null) { 104 return Result.UNKNOWN; 105 } 106 final long photoId; 107 final int presenceStatus; 108 try { 109 if (!c.moveToFirst()) { 110 return Result.UNKNOWN; 111 } 112 photoId = c.getLong(COLUMN_PHOTO_ID); 113 presenceStatus = c.getInt(COLUMN_PRESENCE); 114 } finally { 115 c.close(); 116 } 117 118 // Convert presence status into the res id. 119 final int presenceStatusResId = StatusUpdates.getPresenceIconResourceId(presenceStatus); 120 121 // load photo from photo-id. 122 Bitmap photo = null; 123 if (photoId != -1) { 124 final byte[] photoData = Utility.getFirstRowBlob(context, 125 ContentUris.withAppendedId(Data.CONTENT_URI, photoId), PHOTO_PROJECTION, 126 null, null, null, PHOTO_COLUMN, null); 127 if (photoData != null) { 128 try { 129 photo = BitmapFactory.decodeByteArray(photoData, 0, photoData.length, null); 130 } catch (OutOfMemoryError e) { 131 Log.d(Logging.LOG_TAG, "Decoding bitmap failed with " + e.getMessage()); 132 } 133 } 134 } 135 136 // Get lookup URI 137 final Uri lookupUri = Data.getContactLookupUri(context.getContentResolver(), uri); 138 return new Result(photo, presenceStatusResId, lookupUri); 139 } 140 141 @Override 142 protected void onStartLoading() { 143 cancelLoad(); 144 forceLoad(); 145 } 146 147 @Override 148 protected void onStopLoading() { 149 cancelLoad(); 150 } 151 152 @Override 153 protected void onReset() { 154 stopLoading(); 155 } 156} 157