Clean up header view. Speed up image loading by not spawning yet another async-task
Bug:2733187
Change-Id: Ibb59d9866af0b86e7dfbc89eecfec2b95091f889
diff --git a/res/layout/contact_detail_header_view.xml b/res/layout/contact_detail_header_view.xml
index dc8239a..3e47d51 100644
--- a/res/layout/contact_detail_header_view.xml
+++ b/res/layout/contact_detail_header_view.xml
@@ -36,32 +36,16 @@
android:orientation="vertical"
android:layout_gravity="center_vertical" >
- <LinearLayout
+ <TextView android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/aggregate_badge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="3dip"
- android:paddingTop="3dip"
- android:src="@drawable/ic_aggregated"
- android:visibility="gone"
- />
-
- <TextView android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:shadowColor="#BB000000"
- android:shadowRadius="2.75"
- />
- </LinearLayout>
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:shadowColor="#BB000000"
+ android:shadowRadius="2.75"
+ />
<TextView android:id="@+id/phonetic_name"
android:layout_width="match_parent"
@@ -120,7 +104,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:visibility="gone"
android:contentDescription="@string/description_star"
style="?android:attr/starStyle" />
</LinearLayout>
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index f005efa..bfbd4d7 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -166,11 +166,10 @@
final View view = inflater.inflate(R.layout.contact_detail_fragment, container, false);
setHasOptionsMenu(true);
-
+
mInflater = inflater;
mHeaderView = (ContactDetailHeaderView) view.findViewById(R.id.contact_header_widget);
- mHeaderView.showStar(true);
mHeaderView.setExcludeMimes(new String[] {
Contacts.CONTENT_ITEM_TYPE
});
@@ -238,15 +237,7 @@
private void bindData() {
// Set the header
- mHeaderView.setContactUri(mContactData.getLookupUri());
- mHeaderView.setDisplayName(mContactData.getDisplayName(),
- mContactData.getPhoneticName());
- mHeaderView.setPhotoId(mContactData.getPhotoId(), mContactData.getLookupUri());
- mHeaderView.setStared(mContactData.getStarred());
- mHeaderView.setPresence(mContactData.getPresence());
- mHeaderView.setStatus(
- mContactData.getStatus(), mContactData.getStatusTimestamp(),
- mContactData.getStatusLabel(), mContactData.getStatusResPackage());
+ mHeaderView.loadData(mContactData);
// Build up the contact entries
buildEntries();
diff --git a/src/com/android/contacts/views/detail/ContactDetailHeaderView.java b/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
index fcff6c1..85afd2d 100644
--- a/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
+++ b/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
@@ -17,27 +17,24 @@
package com.android.contacts.views.detail;
import com.android.contacts.R;
+import com.android.contacts.views.ContactLoader;
-import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
-import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Entity;
+import android.content.Entity.NamedContentValues;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
-import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.SystemClock;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.PhoneLookup;
-import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.StatusUpdates;
-import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -54,29 +51,24 @@
/**
* Header for displaying a title bar with contact info. You
- * can bind specific values on the header
+ * can bind specific values by calling
+ * {@link ContactDetailHeaderView#loadData(com.android.contacts.views.ContactLoader.Result)}
*/
public class ContactDetailHeaderView extends FrameLayout implements View.OnClickListener {
private static final String TAG = "ContactDetailHeaderView";
private TextView mDisplayNameView;
- private View mAggregateBadge;
private TextView mPhoneticNameView;
private CheckBox mStarredView;
private QuickContactBadge mPhotoView;
private ImageView mPresenceView;
private TextView mStatusView;
private TextView mStatusAttributionView;
- private int mNoPhotoResource;
- private QueryHandler mQueryHandler;
private ImageButton mEditButton;
private Uri mContactUri;
-
- protected String[] mExcludeMimes = null;
-
- protected ContentResolver mContentResolver;
+ private Listener mListener;
/**
* Interface for callbacks invoked when the user interacts with a header.
@@ -87,73 +79,6 @@
public void onEditClicked();
}
- private Listener mListener;
-
-
- private interface ContactQuery {
- //Projection used for the summary info in the header.
- String[] COLUMNS = new String[] {
- Contacts._ID,
- Contacts.LOOKUP_KEY,
- Contacts.PHOTO_ID,
- Contacts.DISPLAY_NAME,
- Contacts.PHONETIC_NAME,
- Contacts.STARRED,
- Contacts.CONTACT_PRESENCE,
- Contacts.CONTACT_STATUS,
- Contacts.CONTACT_STATUS_TIMESTAMP,
- Contacts.CONTACT_STATUS_RES_PACKAGE,
- Contacts.CONTACT_STATUS_LABEL,
- };
- int _ID = 0;
- int LOOKUP_KEY = 1;
- int PHOTO_ID = 2;
- int DISPLAY_NAME = 3;
- int PHONETIC_NAME = 4;
- //TODO: We need to figure out how we're going to get the phonetic name.
- //static final int HEADER_PHONETIC_NAME_COLUMN_INDEX
- int STARRED = 5;
- int CONTACT_PRESENCE_STATUS = 6;
- int CONTACT_STATUS = 7;
- int CONTACT_STATUS_TIMESTAMP = 8;
- int CONTACT_STATUS_RES_PACKAGE = 9;
- int CONTACT_STATUS_LABEL = 10;
- }
-
- private interface PhotoQuery {
- String[] COLUMNS = new String[] {
- Photo.PHOTO
- };
-
- int PHOTO = 0;
- }
-
- //Projection used for looking up contact id from phone number
- protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
- PhoneLookup._ID,
- PhoneLookup.LOOKUP_KEY,
- };
- protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
- protected static final int PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
-
- //Projection used for looking up contact id from email address
- protected static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
- RawContacts.CONTACT_ID,
- Contacts.LOOKUP_KEY,
- };
- protected static final int EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
- protected static final int EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
-
- protected static final String[] CONTACT_LOOKUP_PROJECTION = new String[] {
- Contacts._ID,
- };
- protected static final int CONTACT_LOOKUP_ID_COLUMN_INDEX = 0;
-
- private static final int TOKEN_CONTACT_INFO = 0;
- private static final int TOKEN_PHONE_LOOKUP = 1;
- private static final int TOKEN_EMAIL_LOOKUP = 2;
- private static final int TOKEN_PHOTO_QUERY = 3;
-
public ContactDetailHeaderView(Context context) {
this(context, null);
}
@@ -165,14 +90,11 @@
public ContactDetailHeaderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mContentResolver = mContext.getContentResolver();
-
final LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.contact_detail_header_view, this);
mDisplayNameView = (TextView) findViewById(R.id.name);
- mAggregateBadge = findViewById(R.id.aggregate_badge);
mPhoneticNameView = (TextView) findViewById(R.id.phonetic_name);
@@ -188,27 +110,49 @@
mStatusView = (TextView)findViewById(R.id.status);
mStatusAttributionView = (TextView)findViewById(R.id.status_date);
-
- // Set the photo with a random "no contact" image
- long now = SystemClock.elapsedRealtime();
- int num = (int) now & 0xf;
- if (num < 9) {
- // Leaning in from right, common
- mNoPhotoResource = R.drawable.ic_contact_picture;
- } else if (num < 14) {
- // Leaning in from left uncommon
- mNoPhotoResource = R.drawable.ic_contact_picture_2;
- } else {
- // Coming in from the top, rare
- mNoPhotoResource = R.drawable.ic_contact_picture_3;
- }
-
- resetAsyncQueryHandler();
}
- public void enableClickListeners() {
- mDisplayNameView.setOnClickListener(this);
- mPhotoView.setOnClickListener(this);
+ /**
+ * Loads the data from the Loader-Result. This is the only function that has to be called
+ * from the outside to fully setup the View
+ */
+ public void loadData(ContactLoader.Result contactData) {
+ mContactUri = contactData.getLookupUri();
+ mPhotoView.assignContactUri(contactData.getLookupUri());
+
+ setDisplayName(contactData.getDisplayName(), contactData.getPhoneticName());
+ setPhoto(findPhoto(contactData));
+ setStared(contactData.getStarred());
+ setPresence(contactData.getPresence());
+ setStatus(
+ contactData.getStatus(), contactData.getStatusTimestamp(),
+ contactData.getStatusLabel(), contactData.getStatusResPackage());
+ }
+
+ /**
+ * Looks for the photo data item in entities. If found, creates a new Bitmap instance. If
+ * not found, returns null
+ */
+ private Bitmap findPhoto(ContactLoader.Result contactData) {
+ final long photoId = contactData.getPhotoId();
+
+ for (Entity entity : contactData.getEntities()) {
+ for (NamedContentValues subValue : entity.getSubValues()) {
+ final ContentValues entryValues = subValue.values;
+ final long dataId = entryValues.getAsLong(Data._ID);
+ final String mimeType = entryValues.getAsString(Data.MIMETYPE);
+
+ if (dataId == photoId) {
+ // Correct Data Id but incorrect MimeType? Don't load
+ if (!Photo.CONTENT_ITEM_TYPE.equals(mimeType)) return null;
+ final byte[] binaryData = entryValues.getAsByteArray(Photo.PHOTO);
+ if (binaryData == null) return null;
+ return BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length);
+ }
+ }
+ }
+
+ return null;
}
/**
@@ -236,211 +180,51 @@
}
}
- private class QueryHandler extends AsyncQueryHandler {
-
- public QueryHandler(ContentResolver cr) {
- super(cr);
- }
-
- @Override
- protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- try{
- if (this != mQueryHandler) {
- Log.d(TAG, "onQueryComplete: discard result, the query handler is reset!");
- return;
- }
-
- switch (token) {
- case TOKEN_PHOTO_QUERY: {
- //Set the photo
- Bitmap photoBitmap = null;
- if (cursor != null && cursor.moveToFirst()
- && !cursor.isNull(PhotoQuery.PHOTO)) {
- byte[] photoData = cursor.getBlob(PhotoQuery.PHOTO);
- photoBitmap = BitmapFactory.decodeByteArray(photoData, 0,
- photoData.length, null);
- }
-
- if (photoBitmap == null) {
- photoBitmap = loadPlaceholderPhoto(null);
- }
- setPhoto(photoBitmap);
- if (cookie != null && cookie instanceof Uri) {
- mPhotoView.assignContactUri((Uri) cookie);
- }
- invalidate();
- break;
- }
- case TOKEN_CONTACT_INFO: {
- if (cursor != null && cursor.moveToFirst()) {
- bindContactInfo(cursor);
- final Uri lookupUri = Contacts.getLookupUri(
- cursor.getLong(ContactQuery._ID),
- cursor.getString(ContactQuery.LOOKUP_KEY));
-
- final long photoId = cursor.getLong(ContactQuery.PHOTO_ID);
-
- setPhotoId(photoId, lookupUri);
- } else {
- // shouldn't really happen
- setDisplayName(null, null);
- setSocialSnippet(null);
- setPhoto(loadPlaceholderPhoto(null));
- }
- break;
- }
- case TOKEN_PHONE_LOOKUP: {
- if (cursor != null && cursor.moveToFirst()) {
- long contactId = cursor.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
- String lookupKey = cursor.getString(
- PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
- bindFromContactUriInternal(Contacts.getLookupUri(contactId, lookupKey),
- false /* don't reset query handler */);
- } else {
- String phoneNumber = (String) cookie;
- setDisplayName(phoneNumber, null);
- setSocialSnippet(null);
- setPhoto(loadPlaceholderPhoto(null));
- mPhotoView.assignContactFromPhone(phoneNumber, true);
- }
- break;
- }
- case TOKEN_EMAIL_LOOKUP: {
- if (cursor != null && cursor.moveToFirst()) {
- long contactId = cursor.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
- String lookupKey = cursor.getString(
- EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
- bindFromContactUriInternal(Contacts.getLookupUri(contactId, lookupKey),
- false /* don't reset query handler */);
- } else {
- String emailAddress = (String) cookie;
- setDisplayName(emailAddress, null);
- setSocialSnippet(null);
- setPhoto(loadPlaceholderPhoto(null));
- mPhotoView.assignContactFromEmail(emailAddress, true);
- }
- break;
- }
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
- }
-
/**
- * Turn on/off showing of the aggregate badge element.
+ * Set the starred state of this header widget.
*/
- public void showAggregateBadge(boolean showBagde) {
- mAggregateBadge.setVisibility(showBagde ? View.VISIBLE : View.GONE);
- }
-
- /**
- * Turn on/off showing of the star element.
- */
- public void showStar(boolean showStar) {
- mStarredView.setVisibility(showStar ? View.VISIBLE : View.GONE);
- }
-
- /**
- * Manually set the starred state of this header widget. This doesn't change
- * the underlying {@link Contacts} value, only the UI state.
- */
- public void setStared(boolean starred) {
+ private void setStared(boolean starred) {
mStarredView.setChecked(starred);
}
/**
- * Manually set the presence.
+ * Set the presence. If presence is null, it is hidden.
*/
- public void setPresence(int presence) {
- mPresenceView.setImageResource(StatusUpdates.getPresenceIconResourceId(presence));
- }
-
- /**
- * Manually set the presence. If presence is null, it is hidden.
- * This doesn't change the underlying {@link Contacts} value, only the UI state.
- * @hide
- */
- public void setPresence(Integer presence) {
+ private void setPresence(Integer presence) {
if (presence == null) {
- showPresence(false);
+ mPresenceView.setVisibility(View.GONE);
} else {
- showPresence(true);
- setPresence(presence.intValue());
+ mPresenceView.setVisibility(View.VISIBLE);
+ mPresenceView.setImageResource(StatusUpdates.getPresenceIconResourceId(
+ presence.intValue()));
}
}
/**
- * Turn on/off showing the presence.
- * @hide this is here for consistency with setStared/showStar and should be public
+ * Set the photo to display in the header. If bitmap is null, the default placeholder
+ * image is shown
*/
- public void showPresence(boolean showPresence) {
- mPresenceView.setVisibility(showPresence ? View.VISIBLE : View.GONE);
+ private void setPhoto(Bitmap bitmap) {
+ mPhotoView.setImageBitmap(bitmap == null ? loadPlaceholderPhoto() : bitmap);
}
/**
- * Manually set the contact uri without loading any data
+ * Set the display name and phonetic name to show in the header.
*/
- public void setContactUri(Uri uri) {
- setContactUri(uri, true);
- }
-
- /**
- * Manually set the contact uri without loading any data
- */
- public void setContactUri(Uri uri, boolean sendToQuickContact) {
- mContactUri = uri;
- if (sendToQuickContact) {
- mPhotoView.assignContactUri(uri);
- }
- }
-
- /**
- * Manually set the photo to display in the header. This doesn't change the
- * underlying {@link Contacts}, only the UI state.
- */
- public void setPhoto(Bitmap bitmap) {
- mPhotoView.setImageBitmap(bitmap);
- }
-
- /**
- * Manually set the photo given its id. If the id is 0, a placeholder picture will
- * be loaded. For any other Id, an async query is started
- * @hide
- */
- public void setPhotoId(final long photoId, final Uri lookupUri) {
- if (photoId == 0) {
- setPhoto(loadPlaceholderPhoto(null));
- mPhotoView.assignContactUri(lookupUri);
- invalidate();
- } else {
- startPhotoQuery(photoId, lookupUri,
- false /* don't reset query handler */);
- }
- }
-
- /**
- * Manually set the display name and phonetic name to show in the header.
- * This doesn't change the underlying {@link Contacts}, only the UI state.
- */
- public void setDisplayName(CharSequence displayName, CharSequence phoneticName) {
+ private void setDisplayName(CharSequence displayName, CharSequence phoneticName) {
mDisplayNameView.setText(displayName);
- if (!TextUtils.isEmpty(phoneticName)) {
+ if (TextUtils.isEmpty(phoneticName)) {
+ mPhoneticNameView.setVisibility(View.GONE);
+ } else {
mPhoneticNameView.setText(phoneticName);
mPhoneticNameView.setVisibility(View.VISIBLE);
- } else {
- mPhoneticNameView.setVisibility(View.GONE);
}
}
/**
- * Manually set the social snippet text to display in the header. This doesn't change the
- * underlying {@link Contacts}, only the UI state.
+ * Set the social snippet text to display in the header.
*/
- public void setSocialSnippet(CharSequence snippet) {
+ private void setSocialSnippet(CharSequence snippet) {
if (snippet == null) {
mStatusView.setVisibility(View.GONE);
mStatusAttributionView.setVisibility(View.GONE);
@@ -451,16 +235,14 @@
}
/**
- * Manually set the status attribution text to display in the header.
- * This doesn't change the underlying {@link Contacts}, only the UI state.
- * @hide
+ * Set the status attribution text to display in the header.
*/
- public void setStatusAttribution(CharSequence attribution) {
- if (attribution != null) {
+ private void setStatusAttribution(CharSequence attribution) {
+ if (attribution == null) {
+ mStatusAttributionView.setVisibility(View.GONE);
+ } else {
mStatusAttributionView.setText(attribution);
mStatusAttributionView.setVisibility(View.VISIBLE);
- } else {
- mStatusAttributionView.setVisibility(View.GONE);
}
}
@@ -470,14 +252,11 @@
* profile icon.
*/
public void setExcludeMimes(String[] excludeMimes) {
- mExcludeMimes = excludeMimes;
mPhotoView.setExcludeMimes(excludeMimes);
}
/**
- * Manually set all the status values to display in the header.
- * This doesn't change the underlying {@link Contacts}, only the UI state.
- * @hide
+ * Set all the status values to display in the header.
* @param status The status of the contact. If this is either null or empty,
* the status is cleared and the other parameters are ignored.
* @param statusTimestamp The timestamp (retrieved via a call to
@@ -488,7 +267,7 @@
* @param statusResPackage The name of the resource package containing the resource string
* referenced in the parameter statusLabel.
*/
- public void setStatus(final String status, final Long statusTimestamp,
+ private void setStatus(final String status, final Long statusTimestamp,
final Integer statusLabel, final String statusResPackage) {
if (TextUtils.isEmpty(status)) {
setSocialSnippet(null);
@@ -556,141 +335,6 @@
setStatusAttribution(attribution);
}
- /**
- * Convenience method for binding all available data from an existing
- * contact.
- *
- * @param contactUri a {Contacts.CONTENT_URI} style URI.
- * @param resetQueryHandler whether to use a new AsyncQueryHandler or not.
- */
- private void bindFromContactUriInternal(Uri contactUri, boolean resetQueryHandler) {
- mContactUri = contactUri;
- startContactQuery(contactUri, resetQueryHandler);
- }
-
- /**
- * Convenience method for binding all available data from an existing
- * contact.
- *
- * @param emailAddress The email address used to do a reverse lookup in
- * the contacts database. If more than one contact contains this email
- * address, one of them will be chosen to bind to.
- */
- public void bindFromEmail(String emailAddress) {
- resetAsyncQueryHandler();
-
- mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, emailAddress,
- Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)),
- EMAIL_LOOKUP_PROJECTION, null, null, null);
- }
-
- /**
- * Convenience method for binding all available data from an existing
- * contact.
- *
- * @param number The phone number used to do a reverse lookup in
- * the contacts database. If more than one contact contains this phone
- * number, one of them will be chosen to bind to.
- */
- public void bindFromPhoneNumber(String number) {
- resetAsyncQueryHandler();
-
- mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, number,
- Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
- PHONE_LOOKUP_PROJECTION, null, null, null);
- }
-
- /**
- * startContactQuery
- *
- * internal method to query contact by Uri.
- *
- * @param contactUri the contact uri
- * @param resetQueryHandler whether to use a new AsyncQueryHandler or not
- */
- private void startContactQuery(Uri contactUri, boolean resetQueryHandler) {
- if (resetQueryHandler) {
- resetAsyncQueryHandler();
- }
-
- mQueryHandler.startQuery(TOKEN_CONTACT_INFO, contactUri, contactUri, ContactQuery.COLUMNS,
- null, null, null);
- }
-
- /**
- * startPhotoQuery
- *
- * internal method to query contact photo by photo id and uri.
- *
- * @param photoId the photo id.
- * @param lookupKey the lookup uri.
- * @param resetQueryHandler whether to use a new AsyncQueryHandler or not.
- */
- protected void startPhotoQuery(long photoId, Uri lookupKey, boolean resetQueryHandler) {
- if (resetQueryHandler) {
- resetAsyncQueryHandler();
- }
-
- mQueryHandler.startQuery(TOKEN_PHOTO_QUERY, lookupKey,
- ContentUris.withAppendedId(Data.CONTENT_URI, photoId), PhotoQuery.COLUMNS,
- null, null, null);
- }
-
- /**
- * Method to force this widget to forget everything it knows about the contact.
- * We need to stop any existing async queries for phone, email, contact, and photos.
- */
- public void wipeClean() {
- resetAsyncQueryHandler();
-
- setDisplayName(null, null);
- setPhoto(loadPlaceholderPhoto(null));
- setSocialSnippet(null);
- setPresence(0);
- mContactUri = null;
- mExcludeMimes = null;
- }
-
-
- private void resetAsyncQueryHandler() {
- // the api AsyncQueryHandler.cancelOperation() doesn't really work. Since we really
- // need the old async queries to be cancelled, let's do it the hard way.
- mQueryHandler = new QueryHandler(mContentResolver);
- }
-
- /**
- * Bind the contact details provided by the given {@link Cursor}.
- */
- protected void bindContactInfo(Cursor c) {
- final String displayName = c.getString(ContactQuery.DISPLAY_NAME);
- final String phoneticName = c.getString(ContactQuery.PHONETIC_NAME);
- this.setDisplayName(displayName, phoneticName);
-
- final boolean starred = c.getInt(ContactQuery.STARRED) != 0;
- setStared(starred);
-
- //Set the presence status
- if (!c.isNull(ContactQuery.CONTACT_PRESENCE_STATUS)) {
- int presence = c.getInt(ContactQuery.CONTACT_PRESENCE_STATUS);
- setPresence(presence);
- showPresence(true);
- } else {
- showPresence(false);
- }
-
- //Set the status update
- final String status = c.getString(ContactQuery.CONTACT_STATUS);
- final Long statusTimestamp = c.isNull(ContactQuery.CONTACT_STATUS_TIMESTAMP)
- ? null
- : c.getLong(ContactQuery.CONTACT_STATUS_TIMESTAMP);
- final Integer statusLabel = c.isNull(ContactQuery.CONTACT_STATUS_LABEL)
- ? null
- : c.getInt(ContactQuery.CONTACT_STATUS_LABEL);
- final String statusResPackage = c.getString(ContactQuery.CONTACT_STATUS_RES_PACKAGE);
-
- setStatus(status, statusTimestamp, statusLabel, statusResPackage);
- }
-
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit: {
@@ -701,9 +345,10 @@
// Toggle "starred" state
// Make sure there is a contact
if (mContactUri != null) {
+ // TODO: This should be done in the background
final ContentValues values = new ContentValues(1);
values.put(Contacts.STARRED, mStarredView.isChecked());
- mContentResolver.update(mContactUri, values, null, null);
+ mContext.getContentResolver().update(mContactUri, values, null, null);
}
break;
}
@@ -718,11 +363,22 @@
}
}
- private Bitmap loadPlaceholderPhoto(BitmapFactory.Options options) {
- if (mNoPhotoResource == 0) {
- return null;
+ private Bitmap loadPlaceholderPhoto() {
+ // Set the photo with a random "no contact" image
+ final long now = SystemClock.elapsedRealtime();
+ final int num = (int) now & 0xf;
+ final int resourceId;
+ if (num < 9) {
+ // Leaning in from right, common
+ resourceId = R.drawable.ic_contact_picture;
+ } else if (num < 14) {
+ // Leaning in from left uncommon
+ resourceId = R.drawable.ic_contact_picture_2;
+ } else {
+ // Coming in from the top, rare
+ resourceId = R.drawable.ic_contact_picture_3;
}
- return BitmapFactory.decodeResource(mContext.getResources(),
- mNoPhotoResource, options);
+
+ return BitmapFactory.decodeResource(mContext.getResources(), resourceId);
}
}