Merge "Use initLoader instead of restartLoader for ContactTileListFragment"
diff --git a/res/layout-sw680dp-w1000dp/contact_detail_list_item.xml b/res/layout-sw680dp-w1000dp/contact_detail_list_item.xml
index 98ffce6..2016131 100644
--- a/res/layout-sw680dp-w1000dp/contact_detail_list_item.xml
+++ b/res/layout-sw680dp-w1000dp/contact_detail_list_item.xml
@@ -50,15 +50,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/footer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:visibility="gone" />
-
</LinearLayout>
<ImageView
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index 44f5a53..666b67c 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -82,15 +82,6 @@
</LinearLayout>
- <TextView
- android:id="@+id/footer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:visibility="gone" />
-
</LinearLayout>
<View
diff --git a/res/layout/quickcontact_list_item.xml b/res/layout/quickcontact_list_item.xml
index ee3a89f..1b66ec3 100755
--- a/res/layout/quickcontact_list_item.xml
+++ b/res/layout/quickcontact_list_item.xml
@@ -27,13 +27,27 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:singleLine="true"
android:ellipsize="end" />
- <TextView
- android:id="@android:id/text2"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="@color/secondary_text_color"
- android:textAllCaps="true"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/presence_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="1dip"
+ android:layout_marginRight="4dip"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:scaleType="centerInside" />
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/secondary_text_color"
+ android:textAllCaps="true"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
</LinearLayout>
<include layout="@layout/quickcontact_list_item_base"/>
</LinearLayout>
diff --git a/res/layout/quickcontact_list_item_address.xml b/res/layout/quickcontact_list_item_address.xml
index 9773b10..cb99673 100755
--- a/res/layout/quickcontact_list_item_address.xml
+++ b/res/layout/quickcontact_list_item_address.xml
@@ -28,13 +28,27 @@
android:layout_height="wrap_content"
android:textColor="@color/primary_text_color"
android:textAppearance="?android:attr/textAppearanceMedium" />
- <TextView
- android:id="@android:id/text2"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="@color/secondary_text_color"
- android:textAllCaps="true"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/presence_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="1dip"
+ android:layout_marginRight="4dip"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:scaleType="centerInside" />
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/secondary_text_color"
+ android:textAllCaps="true"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
</LinearLayout>
<include layout="@layout/quickcontact_list_item_base"/>
</LinearLayout>
diff --git a/res/layout/quickcontact_photo_container.xml b/res/layout/quickcontact_photo_container.xml
index e970934..3b46ef9 100644
--- a/res/layout/quickcontact_photo_container.xml
+++ b/res/layout/quickcontact_photo_container.xml
@@ -26,11 +26,6 @@
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_alignParentTop="true"
- android:background="#4CFFFFFF" />
- <View
android:id="@+id/photo_text_bar"
android:layout_width="0dip"
android:layout_height="42dip"
diff --git a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
index 4b297d9..98abfbc 100644
--- a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
+++ b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
@@ -319,15 +319,23 @@
// Apply a limit of 1 result to the query because we only need to
// determine whether or not at least one other contact has the same
// name. We don't need to find ALL other contacts with the same name.
- Builder builder = Contacts.CONTENT_URI.buildUpon();
+ final Builder builder = Contacts.CONTENT_URI.buildUpon();
builder.appendQueryParameter("limit", String.valueOf(1));
- Uri uri = builder.build();
+ final Uri uri = builder.build();
+ final String displayNameSelection;
+ final String[] selectionArgs;
+ if (TextUtils.isEmpty(contactDisplayName)) {
+ displayNameSelection = Contacts.DISPLAY_NAME_PRIMARY + " IS NULL";
+ selectionArgs = new String[] { String.valueOf(mContactId) };
+ } else {
+ displayNameSelection = Contacts.DISPLAY_NAME_PRIMARY + " = ?";
+ selectionArgs = new String[] { contactDisplayName, String.valueOf(mContactId) };
+ }
mQueryHandler.startQuery(TOKEN_DISAMBIGUATION_QUERY, null, uri,
new String[] { Contacts._ID } /* unused projection but a valid one was needed */,
- Contacts.DISPLAY_NAME_PRIMARY + " = ? and " + Contacts.PHOTO_ID + " is null and "
- + Contacts._ID + " <> ?",
- new String[] { contactDisplayName, String.valueOf(mContactId) }, null);
+ displayNameSelection + " AND " + Contacts.PHOTO_ID + " IS NULL AND "
+ + Contacts._ID + " <> ?", selectionArgs, null);
}
/**
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 8f77371..f24b7eb 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -84,7 +84,6 @@
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.Intents.UI;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.StatusUpdates;
@@ -149,7 +148,6 @@
private Button mQuickFixButton;
private QuickFix mQuickFix;
- private int mNumPhoneNumbers = 0;
private String mDefaultCountryIso;
private boolean mContactHasSocialUpdates;
private boolean mShowStaticPhoto = true;
@@ -543,7 +541,6 @@
mRawContactIds.clear();
mPrimaryPhoneUri = null;
- mNumPhoneNumbers = 0;
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
@@ -598,7 +595,6 @@
// Always ignore the name. It is shown in the header if set
} else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
// Build phone entries
- mNumPhoneNumbers++;
String phoneNumberE164 =
entryValues.getAsString(PhoneLookup.NORMALIZED_NUMBER);
entry.data = PhoneNumberUtils.formatNumber(
@@ -644,7 +640,7 @@
imKind, dataId, entryValues, mContactData.isDirectoryEntry(),
mContactData.getDirectoryId());
buildImActions(mContext, imEntry, entryValues);
- imEntry.applyStatus(status, false);
+ imEntry.setPresence(status.getPresence());
imEntry.maxLines = imKind.maxLinesForDisplay;
mImEntries.add(imEntry);
}
@@ -656,10 +652,10 @@
// Build IM entries
buildImActions(mContext, entry, entryValues);
- // Apply presence and status details when available
+ // Apply presence when available
final DataStatus status = mContactData.getStatuses().get(entry.id);
if (status != null) {
- entry.applyStatus(status, false);
+ entry.setPresence(status.getPresence());
}
mImEntries.add(entry);
} else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
@@ -1228,8 +1224,6 @@
public int presence = -1;
public int chatCapability = 0;
- public CharSequence footerLine = null;
-
private boolean mIsInSubSection = false;
DetailViewEntry() {
@@ -1280,21 +1274,8 @@
return entry;
}
- /**
- * Apply given {@link DataStatus} values over this {@link DetailViewEntry}
- *
- * @param fillData When true, the given status replaces {@link #data}
- * and {@link #footerLine}. Otherwise only {@link #presence}
- * is updated.
- */
- public DetailViewEntry applyStatus(DataStatus status, boolean fillData) {
- presence = status.getPresence();
- if (fillData && status.isValid()) {
- this.data = status.getStatus().toString();
- this.footerLine = status.getTimestampLabel(context);
- }
-
- return this;
+ public void setPresence(int presence) {
+ this.presence = presence;
}
public void setIsInSubSection(boolean isInSubSection) {
@@ -1428,7 +1409,6 @@
private static class DetailViewCache {
public final TextView type;
public final TextView data;
- public final TextView footer;
public final ImageView presenceIcon;
public final ImageView secondaryActionButton;
public final View actionsViewContainer;
@@ -1442,7 +1422,6 @@
OnClickListener secondaryActionClickListener) {
type = (TextView) view.findViewById(R.id.type);
data = (TextView) view.findViewById(R.id.data);
- footer = (TextView) view.findViewById(R.id.footer);
primaryIndicator = view.findViewById(R.id.primary_indicator);
presenceIcon = (ImageView) view.findViewById(R.id.presence_icon);
@@ -1630,14 +1609,6 @@
views.data.setText(entry.data);
setMaxLines(views.data, entry.maxLines);
- // Set the footer
- if (!TextUtils.isEmpty(entry.footerLine)) {
- views.footer.setText(entry.footerLine);
- views.footer.setVisibility(View.VISIBLE);
- } else {
- views.footer.setVisibility(View.GONE);
- }
-
// Set the default contact method
views.primaryIndicator.setVisibility(entry.isPrimary ? View.VISIBLE : View.GONE);
@@ -2158,17 +2129,14 @@
private final static class InvitableAccountTypesAdapter extends BaseAdapter {
private final Context mContext;
private final LayoutInflater mInflater;
- private final ContactLoader.Result mContactData;
private final ArrayList<AccountType> mAccountTypes;
public InvitableAccountTypesAdapter(Context context, ContactLoader.Result contactData) {
mContext = context;
mInflater = LayoutInflater.from(context);
- mContactData = contactData;
final List<AccountType> types = contactData.getInvitableAccountTypes();
mAccountTypes = new ArrayList<AccountType>(types.size());
- AccountTypeManager manager = AccountTypeManager.getInstance(context);
for (int i = 0; i < types.size(); i++) {
mAccountTypes.add(types.get(i));
}
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index 2a1ec5e..c9e713b 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -286,7 +286,17 @@
}
// Field changes are saved directly
+ saveValue(column, value);
+
+ // Notify listener if applicable
+ notifyEditorListener();
+ }
+
+ protected void saveValue(String column, String value) {
mEntry.put(column, value);
+ }
+
+ protected void notifyEditorListener() {
if (mListener != null) {
mListener.onRequest(EditorListener.FIELD_CHANGED);
}
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index 6911628..af1b3cf 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -77,11 +77,12 @@
if (!isFieldChanged(column, value)) {
return;
}
- super.onFieldChanged(column, value);
+ // First save the new value for the column.
+ saveValue(column, value);
mChanged = true;
- // Make sure the display name and the structured name are synced
+ // Next make sure the display name and the structured name are synced
if (hasShortAndLongForms()) {
if (areOptionalFieldsVisible()) {
rebuildFullName(getValues());
@@ -89,6 +90,10 @@
rebuildStructuredName(getValues());
}
}
+
+ // Then notify the listener, which will rely on the display and structured names to be
+ // synced (in order to provide aggregate suggestions).
+ notifyEditorListener();
}
@Override
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index d95a1bc..ac4d399 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -18,7 +18,6 @@
import com.android.contacts.ContactPhotoManager;
import com.android.contacts.R;
import com.android.contacts.widget.IndexerListAdapter;
-import com.android.contacts.widget.TextWithHighlightingFactory;
import android.content.Context;
import android.content.CursorLoader;
@@ -619,8 +618,16 @@
// TODO: move sharable logic (bindXX() methods) to here with extra arguments
+ /**
+ * Loads the photo for the quick contact view and assigns the contact uri.
+ * @param photoIdColumn Index of the photo id column
+ * @param photoUriColumn Index of the photo uri column. Optional: Can be -1
+ * @param contactIdColumn Index of the contact id column
+ * @param lookUpKeyColumn Index of the lookup key column
+ */
protected void bindQuickContact(final ContactListItemView view, int partitionIndex,
- Cursor cursor, int photoIdColumn, int contactIdColumn, int lookUpKeyColumn) {
+ Cursor cursor, int photoIdColumn, int photoUriColumn, int contactIdColumn,
+ int lookUpKeyColumn) {
long photoId = 0;
if (!cursor.isNull(photoIdColumn)) {
photoId = cursor.getLong(photoIdColumn);
@@ -629,7 +636,15 @@
QuickContactBadge quickContact = view.getQuickContact();
quickContact.assignContactUri(
getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
- getPhotoLoader().loadPhoto(quickContact, photoId, false, mDarkTheme);
+
+ if (photoId != 0 || photoUriColumn == -1) {
+ getPhotoLoader().loadPhoto(quickContact, photoId, false, mDarkTheme);
+ } else {
+ final String photoUriString = cursor.getString(photoUriColumn);
+ final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
+ getPhotoLoader().loadPhoto(quickContact, photoUri, false, mDarkTheme);
+ }
+
}
protected Uri getContactUri(int partitionIndex, Cursor cursor,
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index a8caf3b..81fcb84 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -23,7 +23,6 @@
import android.provider.ContactsContract;
import android.provider.ContactsContract.ContactCounts;
import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.SearchSnippetColumns;
import android.text.TextUtils;
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
index 348abb9..7a32e25 100644
--- a/src/com/android/contacts/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/list/DefaultContactListAdapter.java
@@ -26,9 +26,7 @@
import android.net.Uri.Builder;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.SearchSnippetColumns;
@@ -209,7 +207,8 @@
if (isQuickContactEnabled()) {
bindQuickContact(view, partition, cursor, ContactQuery.CONTACT_PHOTO_ID,
- ContactQuery.CONTACT_ID, ContactQuery.CONTACT_LOOKUP_KEY);
+ ContactQuery.CONTACT_PHOTO_URI, ContactQuery.CONTACT_ID,
+ ContactQuery.CONTACT_LOOKUP_KEY);
} else {
bindPhoto(view, partition, cursor);
}
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index 79114eb..960614c 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -15,8 +15,6 @@
*/
package com.android.contacts.list;
-import com.android.contacts.R;
-
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
@@ -262,7 +260,9 @@
if (isFirstEntry) {
bindName(view, cursor);
if (isQuickContactEnabled()) {
- bindQuickContact(view, partition, cursor, PhoneQuery.PHONE_PHOTO_ID,
+ // No need for photo uri here, because we can not have directory results. If we
+ // ever do, we need to add photo uri to the query
+ bindQuickContact(view, partition, cursor, PhoneQuery.PHONE_PHOTO_ID, -1,
PhoneQuery.PHONE_CONTACT_ID, PhoneQuery.PHONE_LOOKUP_KEY);
} else {
bindPhoto(view, cursor);
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index 22ea884..3cc54f1 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -25,7 +25,6 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
@@ -270,6 +269,7 @@
* {@link Comparator} to sort by {@link DataKind#weight}.
*/
private static Comparator<DataKind> sWeightComparator = new Comparator<DataKind>() {
+ @Override
public int compare(DataKind object1, DataKind object2) {
return object1.weight - object2.weight;
}
@@ -460,13 +460,12 @@
}
/**
- * Generic method of inflating a given {@link Cursor} into a user-readable
+ * Generic method of inflating a given {@link ContentValues} into a user-readable
* {@link CharSequence}. For example, an inflater could combine the multiple
* columns of {@link StructuredPostal} together using a string resource
* before presenting to the user.
*/
public interface StringInflater {
- public CharSequence inflateUsing(Context context, Cursor cursor);
public CharSequence inflateUsing(Context context, ContentValues values);
}
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index 4d82ece..ce74148 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -17,18 +17,13 @@
package com.android.contacts.model;
import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DefinitionException;
import com.android.contacts.util.DateUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
-import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -48,6 +43,9 @@
import android.util.Log;
import android.view.inputmethod.EditorInfo;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.List;
import java.util.Locale;
@@ -466,25 +464,7 @@
mColumnName = columnName;
}
- public CharSequence inflateUsing(Context context, Cursor cursor) {
- final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
- final boolean validString = mStringRes > 0;
- final boolean validColumn = index != -1;
-
- final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
- final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
-
- if (validString && validColumn) {
- return String.format(stringValue.toString(), columnValue);
- } else if (validString) {
- return stringValue;
- } else if (validColumn) {
- return columnValue;
- } else {
- return null;
- }
- }
-
+ @Override
public CharSequence inflateUsing(Context context, ContentValues values) {
final boolean validColumn = values.containsKey(mColumnName);
final boolean validString = mStringRes > 0;
@@ -541,12 +521,7 @@
}
}
- public CharSequence inflateUsing(Context context, Cursor cursor) {
- final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
- final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
- return getTypeLabel(context.getResources(), type, label);
- }
-
+ @Override
public CharSequence inflateUsing(Context context, ContentValues values) {
final Integer type = values.getAsInteger(getTypeColumn());
final String label = values.getAsString(getLabelColumn());
diff --git a/src/com/android/contacts/quickcontact/Action.java b/src/com/android/contacts/quickcontact/Action.java
index b2d869d..3a283fb 100644
--- a/src/com/android/contacts/quickcontact/Action.java
+++ b/src/com/android/contacts/quickcontact/Action.java
@@ -58,4 +58,7 @@
* row
*/
public long getDataId();
+
+ /** Returns the presence of this item or -1 if it was never set */
+ public int getPresence();
}
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index 415fa18..e839cda 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -21,14 +21,14 @@
import com.android.contacts.model.AccountType.EditType;
import com.android.contacts.model.DataKind;
import com.android.contacts.util.Constants;
-import com.android.contacts.util.StructuredPostalUtils;
import com.android.contacts.util.PhoneCapabilityTester;
+import com.android.contacts.util.StructuredPostalUtils;
import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.net.WebAddress;
@@ -59,6 +59,7 @@
private Intent mAlternateIntent;
private int mAlternateIconDescriptionRes;
private int mAlternateIconRes;
+ private int mPresence = -1;
private Uri mDataUri;
private long mDataId;
@@ -67,7 +68,8 @@
/**
* Create an action from common {@link Data} elements.
*/
- public DataAction(Context context, String mimeType, DataKind kind, long dataId, Cursor cursor) {
+ public DataAction(Context context, String mimeType, DataKind kind, long dataId,
+ ContentValues entryValues) {
mContext = context;
mKind = kind;
mMimeType = mimeType;
@@ -75,9 +77,8 @@
// Determine type for subtitle
mSubtitle = "";
if (kind.typeColumn != null) {
- final int typeColumnIndex = cursor.getColumnIndex(kind.typeColumn);
- if (typeColumnIndex != -1) {
- final int typeValue = cursor.getInt(typeColumnIndex);
+ if (entryValues.containsKey(kind.typeColumn)) {
+ final int typeValue = entryValues.getAsInteger(kind.typeColumn);
// get type string
for (EditType type : kind.typeList) {
@@ -87,8 +88,7 @@
mSubtitle = context.getString(type.labelRes);
} else {
// Custom type. Read it from the database
- mSubtitle = cursor.getString(cursor.getColumnIndexOrThrow(
- type.customColumn));
+ mSubtitle = entryValues.getAsString(type.customColumn);
}
break;
}
@@ -96,12 +96,11 @@
}
}
- if (getAsInt(cursor, Data.IS_SUPER_PRIMARY) != 0) {
- mIsPrimary = true;
- }
+ final Integer superPrimary = entryValues.getAsInteger(Data.IS_SUPER_PRIMARY);
+ mIsPrimary = superPrimary != null && superPrimary != 0;
if (mKind.actionBody != null) {
- mBody = mKind.actionBody.inflateUsing(context, cursor);
+ mBody = mKind.actionBody.inflateUsing(context, entryValues);
}
mDataId = dataId;
@@ -113,7 +112,7 @@
// Handle well-known MIME-types with special care
if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
if (PhoneCapabilityTester.isPhone(mContext)) {
- final String number = getAsString(cursor, Phone.NUMBER);
+ final String number = entryValues.getAsString(Phone.NUMBER);
if (!TextUtils.isEmpty(number)) {
final Intent phoneIntent = hasPhone ? ContactsUtils.getCallIntent(number)
@@ -136,7 +135,7 @@
}
} else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
if (PhoneCapabilityTester.isSipPhone(mContext)) {
- final String address = getAsString(cursor, SipAddress.SIP_ADDRESS);
+ final String address = entryValues.getAsString(SipAddress.SIP_ADDRESS);
if (!TextUtils.isEmpty(address)) {
final Uri callUri = Uri.fromParts(Constants.SCHEME_SIP, address, null);
mIntent = ContactsUtils.getCallIntent(callUri);
@@ -149,14 +148,14 @@
}
}
} else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final String address = getAsString(cursor, Email.DATA);
+ final String address = entryValues.getAsString(Email.DATA);
if (!TextUtils.isEmpty(address)) {
final Uri mailUri = Uri.fromParts(Constants.SCHEME_MAILTO, address, null);
mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
}
} else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final String url = getAsString(cursor, Website.URL);
+ final String url = entryValues.getAsString(Website.URL);
if (!TextUtils.isEmpty(url)) {
WebAddress webAddress = new WebAddress(url);
mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
@@ -164,21 +163,21 @@
} else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
- getAsString(cursor, Data.MIMETYPE));
- if (isEmail || isProtocolValid(cursor)) {
+ entryValues.getAsString(Data.MIMETYPE));
+ if (isEmail || isProtocolValid(entryValues)) {
final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK :
- getAsInt(cursor, Im.PROTOCOL);
+ entryValues.getAsInteger(Im.PROTOCOL);
if (isEmail) {
// Use Google Talk string when using Email, and clear data
// Uri so we don't try saving Email as primary.
- mSubtitle = context.getText(R.string.chat_gtalk);
+ mSubtitle = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK,
+ null);
mDataUri = null;
}
- String host = getAsString(cursor, Im.CUSTOM_PROTOCOL);
- String data = getAsString(cursor,
- isEmail ? Email.DATA : Im.DATA);
+ String host = entryValues.getAsString(Im.CUSTOM_PROTOCOL);
+ String data = entryValues.getAsString(isEmail ? Email.DATA : Im.DATA);
if (protocol != Im.PROTOCOL_CUSTOM) {
// Try bringing in a well-known host for specific protocols
host = ContactsUtils.lookupProviderNameFromId(protocol);
@@ -192,7 +191,8 @@
// If the address is also available for a video chat, we'll show the capability
// as a secondary action.
- final int chatCapability = getAsInt(cursor, Data.CHAT_CAPABILITY);
+ final Integer chatCapabilityObj = entryValues.getAsInteger(Im.CHAT_CAPABILITY);
+ final int chatCapability = chatCapabilityObj == null ? 0 : chatCapabilityObj;
final boolean isVideoChatCapable =
(chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
final boolean isAudioChatCapable =
@@ -211,7 +211,8 @@
}
}
} else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final String postalAddress = getAsString(cursor, StructuredPostal.FORMATTED_ADDRESS);
+ final String postalAddress =
+ entryValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
if (!TextUtils.isEmpty(postalAddress)) {
mIntent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
}
@@ -227,25 +228,22 @@
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
- /** Read {@link String} from the given {@link Cursor}. */
- private static String getAsString(Cursor cursor, String columnName) {
- final int index = cursor.getColumnIndex(columnName);
- return cursor.getString(index);
+ @Override
+ public int getPresence() {
+ return mPresence;
}
- /** Read {@link Integer} from the given {@link Cursor}. */
- private static int getAsInt(Cursor cursor, String columnName) {
- final int index = cursor.getColumnIndex(columnName);
- return cursor.getInt(index);
+ public void setPresence(int presence) {
+ mPresence = presence;
}
- private boolean isProtocolValid(Cursor cursor) {
- final int columnIndex = cursor.getColumnIndex(Im.PROTOCOL);
- if (cursor.isNull(columnIndex)) {
+ private boolean isProtocolValid(ContentValues entryValues) {
+ final String protocol = entryValues.getAsString(Im.PROTOCOL);
+ if (protocol == null) {
return false;
}
try {
- Integer.valueOf(cursor.getString(columnIndex));
+ Integer.valueOf(protocol);
} catch (NumberFormatException e) {
return false;
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 2c62fe4..b603e42 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -17,44 +17,42 @@
package com.android.contacts.quickcontact;
import com.android.contacts.Collapser;
+import com.android.contacts.ContactLoader;
import com.android.contacts.ContactPhotoManager;
import com.android.contacts.R;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.DataKind;
import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.NotifyingAsyncQueryHandler;
-import com.android.contacts.util.NotifyingAsyncQueryHandler.AsyncQueryListener;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
+import android.app.LoaderManager.LoaderCallbacks;
import android.content.ActivityNotFoundException;
import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
+import android.content.Entity;
+import android.content.Entity.NamedContentValues;
import android.content.Intent;
+import android.content.Loader;
import android.content.pm.PackageManager;
-import android.content.res.AssetFileDescriptor;
-import android.database.Cursor;
-import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.DisplayPhoto;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsContract.RawContacts;
import android.support.v13.app.FragmentPagerAdapter;
@@ -74,7 +72,6 @@
import android.widget.TextView;
import android.widget.Toast;
-import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -96,8 +93,6 @@
@SuppressWarnings("deprecation")
private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY;
- private NotifyingAsyncQueryHandler mHandler;
-
private Uri mLookupUri;
private String[] mExcludeMimes;
private List<String> mSortedActionMimeTypes = Lists.newArrayList();
@@ -147,8 +142,8 @@
private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList(
StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE);
- /** Id for the background handler that loads the data */
- private static final int HANDLER_ID_DATA = 1;
+ /** Id for the background loader */
+ private static final int LOADER_ID = 0;
@Override
protected void onCreate(Bundle icicle) {
@@ -190,8 +185,6 @@
mListPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
mListPager.setOnPageChangeListener(new PageChangeListener());
- mHandler = new NotifyingAsyncQueryHandler(this, mQueryListener);
-
show();
}
@@ -225,16 +218,7 @@
mPhotoContainer = findViewById(R.id.photo_container);
setHeaderNameText(R.id.name, R.string.missing_name);
- // Start background query for data, but only select photo rows when they
- // directly match the super-primary PHOTO_ID.
- final Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY);
- mHandler.cancelOperation(HANDLER_ID_DATA);
-
- // Select all data items of the contact (except for photos, where we only select the display
- // photo)
- mHandler.startQuery(HANDLER_ID_DATA, lookupUri, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
- + "!=? OR (" + Data.MIMETYPE + "=? AND " + Data._ID + "=" + Contacts.PHOTO_ID
- + ")", new String[] { Photo.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE }, null);
+ getLoaderManager().initLoader(LOADER_ID, null, mLoaderCallbacks);
}
private boolean handleOutsideTouch() {
@@ -248,7 +232,7 @@
private void hide(boolean withAnimation) {
// cancel any pending queries
- mHandler.cancelOperation(HANDLER_ID_DATA);
+ getLoaderManager().destroyLoader(LOADER_ID);
if (withAnimation) {
mFloatingLayout.hideChild(new Runnable() {
@@ -268,47 +252,6 @@
hide(true);
}
- private final AsyncQueryListener mQueryListener = new AsyncQueryListener() {
- @Override
- public synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
- try {
- if (isFinishing()) {
- hide(false);
- return;
- } else if (cursor == null || cursor.getCount() == 0) {
- Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
- Toast.LENGTH_LONG).show();
- hide(false);
- return;
- }
-
- bindData(cursor);
-
- if (TRACE_LAUNCH) {
- android.os.Debug.stopMethodTracing();
- }
-
- // Data bound and ready, pull curtain to show. Put this on the Handler to ensure
- // that the layout passes are completed
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mFloatingLayout.showChild(new Runnable() {
- @Override
- public void run() {
- mHasFinishedAnimatingIn = true;
- }
- });
- }
- });
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
- };
-
/** Assign this string to the view if it is not empty. */
private void setHeaderNameText(int id, int resId) {
setHeaderNameText(id, getText(resId));
@@ -325,35 +268,6 @@
}
/**
- * Assign this string to the view (if found in {@link #mPhotoContainer}), or hiding this view
- * if there is no string.
- */
- private void setHeaderText(int id, int resId) {
- setHeaderText(id, getText(resId));
- }
-
- /**
- * Assign this string to the view (if found in {@link #mPhotoContainer}), or hiding this view
- * if there is no string.
- */
- private void setHeaderText(int id, CharSequence value) {
- final View view = mPhotoContainer.findViewById(id);
- if (view instanceof TextView) {
- ((TextView)view).setText(value);
- view.setVisibility(TextUtils.isEmpty(value) ? View.GONE : View.VISIBLE);
- }
- }
-
- /** Assign this image to the view, if found in {@link #mPhotoContainer}. */
- private void setHeaderImage(int id, Drawable drawable) {
- final View view = mPhotoContainer.findViewById(id);
- if (view instanceof ImageView) {
- ((ImageView)view).setImageDrawable(drawable);
- view.setVisibility(drawable == null ? View.GONE : View.VISIBLE);
- }
- }
-
- /**
* Check if the given MIME-type appears in the list of excluded MIME-types
* that the most-recent caller requested.
*/
@@ -368,9 +282,9 @@
}
/**
- * Handle the result from the {@link #TOKEN_DATA} query.
+ * Handle the result from the ContactLoader
*/
- private void bindData(Cursor cursor) {
+ private void bindData(ContactLoader.Result data) {
final ResolveCache cache = ResolveCache.getInstance(this);
final Context context = this;
@@ -379,90 +293,63 @@
mDefaultsMap.clear();
- final DataStatus status = new DataStatus();
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
context.getApplicationContext());
final ImageView photoView = (ImageView) mPhotoContainer.findViewById(R.id.photo);
+ final byte[] photo = data.getPhotoBinaryData();
+ if (photo != null) {
+ photoView.setImageBitmap(BitmapFactory.decodeByteArray(photo, 0, photo.length));
+ } else {
+ photoView.setImageResource(
+ ContactPhotoManager.getDefaultAvatarResId(true, false));
+ }
- Bitmap photoBitmap = null;
- while (cursor.moveToNext()) {
- // Handle any social status updates from this row
- status.possibleUpdate(cursor);
+ for (Entity entity : data.getEntities()) {
+ final ContentValues entityValues = entity.getEntityValues();
+ final String accountType = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
+ final String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
+ for (NamedContentValues subValue : entity.getSubValues()) {
+ final ContentValues entryValues = subValue.values;
+ final String mimeType = entryValues.getAsString(Data.MIMETYPE);
- final String mimeType = cursor.getString(DataQuery.MIMETYPE);
+ // Skip this data item if MIME-type excluded
+ if (isMimeExcluded(mimeType)) continue;
- // Skip this data item if MIME-type excluded
- if (isMimeExcluded(mimeType)) continue;
+ final long dataId = entryValues.getAsLong(Data._ID);
+ final Integer primary = entryValues.getAsInteger(Data.IS_PRIMARY);
+ final boolean isPrimary = primary != null && primary != 0;
+ final Integer superPrimary = entryValues.getAsInteger(Data.IS_SUPER_PRIMARY);
+ final boolean isSuperPrimary = superPrimary != null && superPrimary != 0;
- final long dataId = cursor.getLong(DataQuery._ID);
- final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE);
- final String dataSet = cursor.getString(DataQuery.DATA_SET);
- final boolean isPrimary = cursor.getInt(DataQuery.IS_PRIMARY) != 0;
- final boolean isSuperPrimary = cursor.getInt(DataQuery.IS_SUPER_PRIMARY) != 0;
+ final DataKind kind =
+ accountTypes.getKindOrFallback(accountType, dataSet, mimeType);
- // Handle photos included as data row
- if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final int displayPhotoColumnIndex = cursor.getColumnIndex(Photo.PHOTO_FILE_ID);
- final boolean hasDisplayPhoto = !cursor.isNull(displayPhotoColumnIndex);
- if (hasDisplayPhoto) {
- final long displayPhotoId = cursor.getLong(displayPhotoColumnIndex);
- final Uri displayPhotoUri = ContentUris.withAppendedId(
- DisplayPhoto.CONTENT_URI, displayPhotoId);
- // Fetch and JPEG uncompress on the background thread
- new AsyncTask<Void, Void, Bitmap>() {
- @Override
- protected Bitmap doInBackground(Void... params) {
- try {
- AssetFileDescriptor fd = getContentResolver()
- .openAssetFileDescriptor(displayPhotoUri, "r");
- return BitmapFactory.decodeStream(fd.createInputStream());
- } catch (IOException e) {
- Log.e(TAG, "Error getting display photo. Ignoring, as we already " +
- "have the thumbnail", e);
- return null;
- }
+ if (kind != null) {
+ // Build an action for this data entry, find a mapping to a UI
+ // element, build its summary from the cursor, and collect it
+ // along with all others of this MIME-type.
+ final Action action = new DataAction(context, mimeType, kind, dataId,
+ entryValues);
+ final boolean wasAdded = considerAdd(action, cache);
+ if (wasAdded) {
+ // Remember the default
+ if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
+ mDefaultsMap.put(mimeType, action);
}
-
- @Override
- protected void onPostExecute(Bitmap result) {
- if (result == null) return;
- photoView.setImageBitmap(result);
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
- }
- final int photoColumnIndex = cursor.getColumnIndex(Photo.PHOTO);
- final byte[] photoBlob = cursor.getBlob(photoColumnIndex);
- if (photoBlob != null) {
- photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
- }
- continue;
- }
-
- final DataKind kind = accountTypes.getKindOrFallback(accountType, dataSet, mimeType);
-
- if (kind != null) {
- // Build an action for this data entry, find a mapping to a UI
- // element, build its summary from the cursor, and collect it
- // along with all others of this MIME-type.
- final Action action = new DataAction(context, mimeType, kind, dataId, cursor);
- final boolean wasAdded = considerAdd(action, cache);
- if (wasAdded) {
- // Remember the default
- if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
- mDefaultsMap.put(mimeType, action);
}
}
- }
- // Handle Email rows with presence data as Im entry
- final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
- if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
- Im.CONTENT_ITEM_TYPE);
- if (imKind != null) {
- final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
- dataId, cursor);
- considerAdd(action, cache);
+ // Handle Email rows with presence data as Im entry
+ final DataStatus status = data.getStatuses().get(dataId);
+ if (status != null && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
+ Im.CONTENT_ITEM_TYPE);
+ if (imKind != null) {
+ final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE,
+ imKind, dataId, entryValues);
+ action.setPresence(status.getPresence());
+ considerAdd(action, cache);
+ }
}
}
}
@@ -472,20 +359,7 @@
Collapser.collapseList(actionChildren);
}
- if (cursor.moveToLast()) {
- // Read contact name from last data row
- final String name = cursor.getString(DataQuery.DISPLAY_NAME);
- setHeaderNameText(R.id.name, name);
- }
-
- if (photoView != null) {
- // Place photo when discovered in data, otherwise show generic avatar
- if (photoBitmap != null) {
- photoView.setImageBitmap(photoBitmap);
- } else {
- photoView.setImageResource(ContactPhotoManager.getDefaultAvatarResId(true, false));
- }
- }
+ setHeaderNameText(R.id.name, data.getDisplayName());
// All the mime-types to add.
final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
@@ -515,6 +389,7 @@
}
// Add buttons for each mimetype
+ mTrack.removeAllViews();
for (String mimeType : mSortedActionMimeTypes) {
final View actionView = inflateAction(mimeType, cache, mTrack);
mTrack.addView(actionView);
@@ -574,6 +449,61 @@
listFragment.setListener(mListFragmentListener);
}
+ private LoaderCallbacks<ContactLoader.Result> mLoaderCallbacks =
+ new LoaderCallbacks<ContactLoader.Result>() {
+ @Override
+ public void onLoaderReset(Loader<ContactLoader.Result> loader) {
+ }
+
+ @Override
+ public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
+ if (isFinishing()) {
+ hide(false);
+ return;
+ }
+ if (data.isError()) {
+ // This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
+ // should log the actual exception.
+ throw new IllegalStateException("Failed to load contact", data.getException());
+ }
+ if (data.isNotFound()) {
+ Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
+ Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
+ Toast.LENGTH_LONG).show();
+ hide(false);
+ return;
+ }
+
+ bindData(data);
+
+ if (TRACE_LAUNCH) {
+ android.os.Debug.stopMethodTracing();
+ }
+
+ // Data bound and ready, pull curtain to show. Put this on the Handler to ensure
+ // that the layout passes are completed
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ mFloatingLayout.showChild(new Runnable() {
+ @Override
+ public void run() {
+ mHasFinishedAnimatingIn = true;
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public Loader<ContactLoader.Result> onCreateLoader(int id, Bundle args) {
+ if (mLookupUri == null) {
+ Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early");
+ }
+ return new ContactLoader(getApplicationContext(), mLookupUri);
+ }
+ };
+
/** A type (e.g. Call/Addresses was clicked) */
private final OnClickListener mTypeViewClickListener = new OnClickListener() {
@Override
@@ -653,53 +583,4 @@
new Handler().post(startAppRunnable);
}
};
-
- private interface DataQuery {
- final String[] PROJECTION = new String[] {
- Data._ID,
-
- RawContacts.ACCOUNT_TYPE,
- RawContacts.DATA_SET,
- Contacts.STARRED,
- Contacts.DISPLAY_NAME,
-
- Data.STATUS,
- Data.STATUS_RES_PACKAGE,
- Data.STATUS_ICON,
- Data.STATUS_LABEL,
- Data.STATUS_TIMESTAMP,
- Data.PRESENCE,
- Data.CHAT_CAPABILITY,
-
- Data.RES_PACKAGE,
- Data.MIMETYPE,
- Data.IS_PRIMARY,
- Data.IS_SUPER_PRIMARY,
- Data.RAW_CONTACT_ID,
-
- Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
- Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11,
- Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
- };
-
- final int _ID = 0;
-
- final int ACCOUNT_TYPE = 1;
- final int DATA_SET = 2;
- final int STARRED = 3;
- final int DISPLAY_NAME = 4;
-
- final int STATUS = 5;
- final int STATUS_RES_PACKAGE = 6;
- final int STATUS_ICON = 7;
- final int STATUS_LABEL = 8;
- final int STATUS_TIMESTAMP = 9;
- final int PRESENCE = 10;
- final int CHAT_CAPABILITY = 11;
-
- final int RES_PACKAGE = 12;
- final int MIMETYPE = 13;
- final int IS_PRIMARY = 14;
- final int IS_SUPER_PRIMARY = 15;
- }
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactListFragment.java b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
index c6187e9..da8fef8 100644
--- a/src/com/android/contacts/quickcontact/QuickContactListFragment.java
+++ b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
@@ -16,14 +16,14 @@
package com.android.contacts.quickcontact;
+import com.android.contacts.ContactPresenceIconUtil;
import com.android.contacts.R;
import android.app.Fragment;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -111,6 +111,8 @@
final ImageView alternateActionButton = (ImageView) resultView.findViewById(
R.id.secondary_action_button);
final View alternateActionDivider = resultView.findViewById(R.id.vertical_divider);
+ final ImageView presenceIconView =
+ (ImageView) resultView.findViewById(R.id.presence_icon);
actionsContainer.setOnClickListener(mPrimaryActionClickListener);
actionsContainer.setTag(action);
@@ -143,6 +145,14 @@
text2.setVisibility(View.VISIBLE);
}
}
+ final Drawable presenceIcon = ContactPresenceIconUtil.getPresenceIcon(
+ getActivity(), action.getPresence());
+ if (presenceIcon != null) {
+ presenceIconView.setImageDrawable(presenceIcon);
+ presenceIconView.setVisibility(View.VISIBLE);
+ } else {
+ presenceIconView.setVisibility(View.GONE);
+ }
return resultView;
}
});
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index 19ebde3..c3cbc10 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -23,7 +23,7 @@
<!-- List modes -->
<item>LIST_DEFAULT</item>
<item>LIST_ALL_CONTACTS_ACTION</item>
- <item>LIST_CONTACTS_WITH_PHONES_ACTION</item>
+ <item>LIST_CONTACTS_WITH_PHONES_ACTION (deprecated)</item>
<item>LIST_STARRED_ACTION</item>
<item>LIST_FREQUENT_ACTION</item>
<item>LIST_STREQUENT_ACTION</item>