Adding proper chat capability icons to contact detail
Change-Id: I4d9e01e08a8d70bb6e1591f92436a5ab7c194be6
diff --git a/src/com/android/contacts/ContactPresenceIconUtil.java b/src/com/android/contacts/ContactPresenceIconUtil.java
index 1a2d58e..81a1bed 100644
--- a/src/com/android/contacts/ContactPresenceIconUtil.java
+++ b/src/com/android/contacts/ContactPresenceIconUtil.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.StatusUpdates;
/**
@@ -26,7 +27,7 @@
public class ContactPresenceIconUtil {
/**
* Get the presence icon resource according the status.
- *
+ *
* @return null means don't show the status icon.
*/
public static Drawable getPresenceIcon (Context context, int status) {
@@ -45,4 +46,41 @@
return null;
}
}
+
+ public static Drawable getCapabilityIcon(Context context, int status, int chatCapability) {
+ int resourceId = 0;
+ if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
+ switch(status) {
+ case StatusUpdates.AVAILABLE:
+ resourceId = android.R.drawable.presence_video_online;
+ break;
+ case StatusUpdates.IDLE:
+ case StatusUpdates.AWAY:
+ resourceId = android.R.drawable.presence_video_away;
+ break;
+ case StatusUpdates.DO_NOT_DISTURB:
+ resourceId = android.R.drawable.presence_video_busy;
+ break;
+ }
+ } else if ((chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
+ switch(status) {
+ case StatusUpdates.AVAILABLE:
+ resourceId = android.R.drawable.presence_audio_online;
+ break;
+ case StatusUpdates.IDLE:
+ case StatusUpdates.AWAY:
+ resourceId = android.R.drawable.presence_audio_away;
+ break;
+ case StatusUpdates.DO_NOT_DISTURB:
+ resourceId = android.R.drawable.presence_audio_busy;
+ break;
+ }
+ }
+
+ if (resourceId != 0) {
+ return context.getResources().getDrawable(resourceId);
+ }
+
+ return null;
+ }
}
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 181fb37..0e75a7f 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -16,17 +16,11 @@
package com.android.contacts;
-import com.android.contacts.util.Constants;
-
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.location.CountryDetector;
-import android.net.Uri;
-import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Data;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
@@ -80,120 +74,6 @@
return null;
}
- public static final class ImActions {
- private final Intent mPrimaryIntent;
- private final Intent mSecondaryIntent;
- private final int mPrimaryActionIcon;
- private final int mSecondaryActionIcon;
-
- private ImActions(Intent primaryIntent, Intent secondaryIntent, int primaryActionIcon,
- int secondaryActionIcon) {
- mPrimaryIntent = primaryIntent;
- mSecondaryIntent = secondaryIntent;
- mPrimaryActionIcon = primaryActionIcon;
- mSecondaryActionIcon = secondaryActionIcon;
- }
-
- public Intent getPrimaryIntent() {
- return mPrimaryIntent;
- }
-
- public Intent getSecondaryIntent() {
- return mSecondaryIntent;
- }
-
- public int getPrimaryActionIcon() {
- return mPrimaryActionIcon;
- }
-
- public int getSecondaryActionIcon() {
- return mSecondaryActionIcon;
- }
- }
-
- /**
- * Build {@link Intent} to launch an action for the given {@link Im} or
- * {@link Email} row. If the result is non-null, it either contains one or two Intents
- * (e.g. [Text, Videochat] or just [Text])
- * Returns null when missing protocol or data.
- */
- public static ImActions buildImActions(ContentValues values) {
- final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(values.getAsString(Data.MIMETYPE));
-
- if (!isEmail && !isProtocolValid(values)) {
- return null;
- }
-
- final String data = values.getAsString(isEmail ? Email.DATA : Im.DATA);
- if (TextUtils.isEmpty(data)) return null;
-
- final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : values.getAsInteger(Im.PROTOCOL);
-
- if (protocol == Im.PROTOCOL_GOOGLE_TALK) {
- final Integer chatCapabilityObj = values.getAsInteger(Im.CHAT_CAPABILITY);
- final int chatCapability = chatCapabilityObj == null ? 0 : chatCapabilityObj;
- if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
- // Allow Video chat and Texting
- return new ImActions(
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message")),
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call")),
- R.drawable.sym_action_talk_holo_light,
- R.drawable.sym_action_videochat
- );
- } else if ((chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
- // Allow Talking and Texting
- return new ImActions(
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message")),
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call")),
- R.drawable.sym_action_talk_holo_light,
- R.drawable.sym_action_audiochat
- );
- } else {
- return new ImActions(
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message")),
- null,
- R.drawable.sym_action_talk_holo_light,
- -1
- );
- }
- } else {
- // Build an IM Intent
- String host = values.getAsString(Im.CUSTOM_PROTOCOL);
-
- if (protocol != Im.PROTOCOL_CUSTOM) {
- // Try bringing in a well-known host for specific protocols
- host = ContactsUtils.lookupProviderNameFromId(protocol);
- }
-
- if (!TextUtils.isEmpty(host)) {
- final String authority = host.toLowerCase();
- final Uri imUri = new Uri.Builder().scheme(Constants.SCHEME_IMTO).authority(
- authority).appendPath(data).build();
- return new ImActions(
- new Intent(Intent.ACTION_SENDTO, imUri),
- null,
- R.drawable.sym_action_talk_holo_light,
- -1
- );
- } else {
- return null;
- }
- }
- }
-
- private static boolean isProtocolValid(ContentValues values) {
- String protocolString = values.getAsString(Im.PROTOCOL);
- if (protocolString == null) {
- return false;
- }
- try {
- Integer.valueOf(protocolString);
- } catch (NumberFormatException e) {
- return false;
- }
- return true;
- }
-
/**
* Test if the given {@link CharSequence} contains any graphic characters,
* first checking {@link TextUtils#isEmpty(CharSequence)} to handle null.
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index d0c1abc..7ff8acd 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -22,7 +22,6 @@
import com.android.contacts.ContactOptionsActivity;
import com.android.contacts.ContactPresenceIconUtil;
import com.android.contacts.ContactsUtils;
-import com.android.contacts.ContactsUtils.ImActions;
import com.android.contacts.GroupMetaData;
import com.android.contacts.R;
import com.android.contacts.TypePrecedence;
@@ -465,13 +464,7 @@
imMime, mContext);
final ViewEntry imEntry = ViewEntry.fromValues(mContext,
imMime, imKind, dataId, entryValues);
- final ImActions imActions = ContactsUtils.buildImActions(entryValues);
- if (imActions != null) {
- imEntry.actionIcon = imActions.getPrimaryActionIcon();
- imEntry.secondaryActionIcon = imActions.getSecondaryActionIcon();
- imEntry.intent = imActions.getPrimaryIntent();
- imEntry.secondaryIntent = imActions.getSecondaryIntent();
- }
+ buildImActions(imEntry, entryValues);
imEntry.applyStatus(status, false);
mImEntries.add(imEntry);
}
@@ -482,13 +475,7 @@
mPostalEntries.add(entry);
} else if (Im.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
// Build IM entries
- final ImActions imActions = ContactsUtils.buildImActions(entryValues);
- if (imActions != null) {
- entry.actionIcon = imActions.getPrimaryActionIcon();
- entry.secondaryActionIcon = imActions.getSecondaryActionIcon();
- entry.intent = imActions.getPrimaryIntent();
- entry.secondaryIntent = imActions.getSecondaryIntent();
- }
+ buildImActions(entry, entryValues);
// Apply presence and status details when available
final DataStatus status = mContactData.getStatuses().get(entry.id);
@@ -622,9 +609,82 @@
}
/**
+ * Build {@link Intent} to launch an action for the given {@link Im} or
+ * {@link Email} row. If the result is non-null, it either contains one or two Intents
+ * (e.g. [Text, Videochat] or just [Text])
+ */
+ public static void buildImActions(ViewEntry entry, ContentValues values) {
+ final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(values.getAsString(Data.MIMETYPE));
+
+ if (!isEmail && !isProtocolValid(values)) {
+ return;
+ }
+
+ final String data = values.getAsString(isEmail ? Email.DATA : Im.DATA);
+ if (TextUtils.isEmpty(data)) {
+ return;
+ }
+
+ final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : values.getAsInteger(Im.PROTOCOL);
+
+ if (protocol == Im.PROTOCOL_GOOGLE_TALK) {
+ final Integer chatCapabilityObj = values.getAsInteger(Im.CHAT_CAPABILITY);
+ final int chatCapability = chatCapabilityObj == null ? 0 : chatCapabilityObj;
+ entry.chatCapability = chatCapability;
+ if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
+ entry.actionIcon = R.drawable.sym_action_talk_holo_light;
+ entry.intent =
+ new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
+ entry.secondaryIntent =
+ new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
+ } else if ((chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
+ // Allow Talking and Texting
+ entry.actionIcon = R.drawable.sym_action_talk_holo_light;
+ entry.intent =
+ new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
+ entry.secondaryIntent =
+ new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
+ } else {
+ entry.actionIcon = R.drawable.sym_action_talk_holo_light;
+ entry.intent =
+ new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
+ }
+ } else {
+ // Build an IM Intent
+ String host = values.getAsString(Im.CUSTOM_PROTOCOL);
+
+ if (protocol != Im.PROTOCOL_CUSTOM) {
+ // Try bringing in a well-known host for specific protocols
+ host = ContactsUtils.lookupProviderNameFromId(protocol);
+ }
+
+ if (!TextUtils.isEmpty(host)) {
+ final String authority = host.toLowerCase();
+ final Uri imUri = new Uri.Builder().scheme(Constants.SCHEME_IMTO).authority(
+ authority).appendPath(data).build();
+ entry.actionIcon = R.drawable.sym_action_talk_holo_light;
+ entry.intent = new Intent(Intent.ACTION_SENDTO, imUri);
+ }
+ }
+ }
+
+ private static boolean isProtocolValid(ContentValues values) {
+ String protocolString = values.getAsString(Im.PROTOCOL);
+ if (protocolString == null) {
+ return false;
+ }
+ try {
+ Integer.valueOf(protocolString);
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
* A basic structure with the data for a contact entry in the list.
*/
- private static class ViewEntry implements Collapsible<ViewEntry> {
+ static class ViewEntry implements Collapsible<ViewEntry> {
public int type = -1;
public String kind;
public String typeString;
@@ -645,10 +705,11 @@
public int collapseCount = 0;
public int presence = -1;
+ public int chatCapability = 0;
public CharSequence footerLine = null;
- private ViewEntry() {
+ ViewEntry() {
}
/**
@@ -889,7 +950,11 @@
Drawable secondaryActionIcon = null;
if (entry.secondaryActionIcon != -1) {
secondaryActionIcon = resources.getDrawable(entry.secondaryActionIcon);
+ } else if (entry.chatCapability != 0) {
+ secondaryActionIcon = ContactPresenceIconUtil.getCapabilityIcon(
+ mContext, entry.presence, entry.chatCapability);
}
+
if (entry.secondaryIntent != null && secondaryActionIcon != null) {
secondaryActionView.setImageDrawable(secondaryActionIcon);
secondaryActionView.setTag(entry);