Showing directory meta-data in contact view
Also, adding "Make personal copy" to the menu
(for now unimplemented)
Change-Id: I779ff81370eaf8021e0e740a7c70f3d8c3caee6b
diff --git a/res/drawable-hdpi/ic_menu_copy_contact.png b/res/drawable-hdpi/ic_menu_copy_contact.png
new file mode 100644
index 0000000..e6be48b
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_copy_contact.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_copy_contact.png b/res/drawable-mdpi/ic_menu_copy_contact.png
new file mode 100644
index 0000000..750db62
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_copy_contact.png
Binary files differ
diff --git a/res/layout/contact_detail_header_view.xml b/res/layout/contact_detail_header_view.xml
index c201bf4..b7c7988 100644
--- a/res/layout/contact_detail_header_view.xml
+++ b/res/layout/contact_detail_header_view.xml
@@ -57,6 +57,17 @@
android:visibility="gone"
/>
+ <TextView android:id="@+id/directory_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_marginTop="-2dip"
+ android:visibility="gone"
+ />
+
<TextView android:id="@+id/status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/menu/view.xml b/res/menu/view.xml
index 7a1c26c..ea8fe7f 100644
--- a/res/menu/view.xml
+++ b/res/menu/view.xml
@@ -38,4 +38,8 @@
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/menu_deleteContact" />
+ <item
+ android:id="@+id/menu_copy"
+ android:icon="@drawable/ic_menu_copy_contact"
+ android:title="@string/menu_copyContact" />
</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f7eaebb..c8ae433 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1295,4 +1295,13 @@
only be empty.
Translations require extensive QA! -->
<string name="visualScrollerAlphabet">A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z</string>
+
+ <!-- The menu item (or button) that creates a local copy of a corporate contact. [CHAR LIMIT=40]-->
+ <string name="menu_copyContact">Make personal copy</string>
+
+ <!-- The description of the directory where the contact was found [CHAR LIMIT=100]-->
+ <string name="contact_directory_description">from <xliff:g id="type" example="Corporate Directory">%1$s</xliff:g></string>
+
+ <!-- The description of the directory where the contact was found [CHAR LIMIT=100]-->
+ <string name="contact_directory_account_description">from <xliff:g id="type" example="Corporate Directory">%1$s</xliff:g> (<xliff:g id="name" example="me@acme.com">%2$s</xliff:g>)</string>
</resources>
diff --git a/src/com/android/contacts/views/ContactLoader.java b/src/com/android/contacts/views/ContactLoader.java
index 1cb003e..12d98b5 100644
--- a/src/com/android/contacts/views/ContactLoader.java
+++ b/src/com/android/contacts/views/ContactLoader.java
@@ -17,6 +17,7 @@
package com.android.contacts.views;
import com.android.contacts.util.DataStatus;
+import com.android.contacts.views.ContactLoader.Result;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -24,6 +25,10 @@
import android.content.Context;
import android.content.Entity;
import android.content.Loader;
+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.net.Uri;
import android.os.AsyncTask;
@@ -31,8 +36,10 @@
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.DisplayNameSources;
import android.provider.ContactsContract.RawContacts;
+import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
@@ -70,8 +77,9 @@
public static final Result ERROR = new Result();
private final Uri mLookupUri;
- private final String mLookupKey;
private final Uri mUri;
+ private final long mDirectoryId;
+ private final String mLookupKey;
private final long mId;
private final long mNameRawContactId;
private final int mDisplayNameSource;
@@ -87,14 +95,20 @@
private final Integer mStatusLabel;
private final String mStatusResPackage;
+ private String mDirectoryDisplayName;
+ private String mDirectoryType;
+ private String mDirectoryAccountName;
+ private int mDirectoryExportSupport;
+
/**
* Constructor for case "no contact found". This must only be used for the
* final {@link Result#NOT_FOUND} singleton
*/
private Result() {
mLookupUri = null;
- mLookupKey = null;
mUri = null;
+ mDirectoryId = -1;
+ mLookupKey = null;
mId = -1;
mEntities = null;
mStatuses = null;
@@ -114,13 +128,14 @@
/**
* Constructor to call when contact was found
*/
- private Result(Uri lookupUri, String lookupKey, Uri uri, long id, long nameRawContactId,
- int displayNameSource, long photoId, String displayName, String phoneticName,
- boolean starred, Integer presence, String status, Long statusTimestamp,
- Integer statusLabel, String statusResPackage) {
+ private Result(Uri uri, Uri lookupUri, long directoryId, String lookupKey, long id,
+ long nameRawContactId, int displayNameSource, long photoId, String displayName,
+ String phoneticName, boolean starred, Integer presence, String status,
+ Long statusTimestamp, Integer statusLabel, String statusResPackage) {
mLookupUri = lookupUri;
- mLookupKey = lookupKey;
mUri = uri;
+ mDirectoryId = directoryId;
+ mLookupKey = lookupKey;
mId = id;
mEntities = new ArrayList<Entity>();
mStatuses = new HashMap<Long, DataStatus>();
@@ -137,6 +152,17 @@
mStatusResPackage = statusResPackage;
}
+ /**
+ * @param exportSupport See {@link Directory#EXPORT_SUPPORT}.
+ */
+ public void setDirectoryMetaData(String displayName, String directoryType,
+ String accountName, int exportSupport) {
+ mDirectoryDisplayName = displayName;
+ mDirectoryType = directoryType;
+ mDirectoryAccountName = accountName;
+ mDirectoryExportSupport = exportSupport;
+ }
+
public Uri getLookupUri() {
return mLookupUri;
}
@@ -188,6 +214,31 @@
public HashMap<Long, DataStatus> getStatuses() {
return mStatuses;
}
+
+ public long getDirectoryId() {
+ return mDirectoryId;
+ }
+
+ public boolean isDirectoryEntry() {
+ return mDirectoryId != Directory.DEFAULT && mDirectoryId != Directory.LOCAL_INVISIBLE;
+ }
+
+ public int getDirectoryExportSupport() {
+ return mDirectoryExportSupport;
+ }
+
+ public String getDirectoryDisplayName() {
+ return mDirectoryDisplayName;
+ }
+
+ public String getDirectoryType() {
+ return mDirectoryType;
+ }
+
+ public String getDirectoryAccountName() {
+ return mDirectoryAccountName;
+ }
+
}
private static class ContactQuery {
@@ -319,6 +370,23 @@
public final static int STATUS = 54;
}
+ private static class DirectoryQuery {
+ // Projection used for the query that loads all data for the entire contact.
+ final static String[] COLUMNS = new String[] {
+ Directory.DISPLAY_NAME,
+ Directory.PACKAGE_NAME,
+ Directory.TYPE_RESOURCE_ID,
+ Directory.ACCOUNT_NAME,
+ Directory.EXPORT_SUPPORT,
+ };
+
+ public final static int DISPLAY_NAME = 0;
+ public final static int PACKAGE_NAME = 1;
+ public final static int TYPE_RESOURCE_ID = 2;
+ public final static int ACCOUNT_NAME = 3;
+ public final static int EXPORT_SUPPORT = 4;
+ }
+
private final class LoadContactTask extends AsyncTask<Void, Void, Result> {
@Override
@@ -326,7 +394,11 @@
try {
final ContentResolver resolver = getContext().getContentResolver();
final Uri uriCurrentFormat = ensureIsContactUri(resolver, mLookupUri);
- return loadContactEntity(resolver, uriCurrentFormat);
+ Result result = loadContactEntity(resolver, uriCurrentFormat);
+ if (result.isDirectoryEntry()) {
+ loadDirectoryMetaData(result);
+ }
+ return result;
} catch (Exception e) {
Log.e(TAG, "Error loading the contact: " + mLookupUri, e);
return Result.ERROR;
@@ -424,6 +496,11 @@
* Extracts Contact level columns from the cursor.
*/
private Result loadContactHeaderData(final Cursor cursor, Uri contactUri) {
+ final String directoryParameter =
+ contactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
+ final long directoryId = directoryParameter == null
+ ? Directory.DEFAULT
+ : Long.parseLong(directoryParameter);
final long contactId = cursor.getLong(ContactQuery.CONTACT_ID);
final String lookupKey = cursor.getString(ContactQuery.LOOKUP_KEY);
final long nameRawContactId = cursor.getLong(ContactQuery.NAME_RAW_CONTACT_ID);
@@ -447,9 +524,9 @@
Uri lookupUri = ContentUris.withAppendedId(
Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey), contactId);
- return new Result(lookupUri, lookupKey, contactUri, contactId, nameRawContactId,
- displayNameSource, photoId, displayName, phoneticName, starred, presence,
- status, statusTimestamp, statusLabel, statusResPackage);
+ return new Result(contactUri, lookupUri, directoryId, lookupKey, contactId,
+ nameRawContactId, displayNameSource, photoId, displayName, phoneticName,
+ starred, presence, status, statusTimestamp, statusLabel, statusResPackage);
}
/**
@@ -536,6 +613,42 @@
}
}
+ private void loadDirectoryMetaData(Result result) {
+ long directoryId = result.getDirectoryId();
+
+ Cursor cursor = getContext().getContentResolver().query(
+ ContentUris.withAppendedId(Directory.CONTENT_URI, directoryId),
+ DirectoryQuery.COLUMNS, null, null, null);
+ if (cursor == null) {
+ return;
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ final String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME);
+ final String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME);
+ final int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID);
+ final String accountName = cursor.getString(DirectoryQuery.ACCOUNT_NAME);
+ final int exportSupport = cursor.getInt(DirectoryQuery.EXPORT_SUPPORT);
+ String directoryType = null;
+ if (!TextUtils.isEmpty(packageName)) {
+ PackageManager pm = getContext().getPackageManager();
+ try {
+ Resources resources = pm.getResourcesForApplication(packageName);
+ directoryType = resources.getString(typeResourceId);
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Contact directory resource not found: "
+ + packageName + "." + typeResourceId);
+ }
+ }
+
+ result.setDirectoryMetaData(
+ displayName, directoryType, accountName, exportSupport);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
@Override
protected void onPostExecute(Result result) {
// The creator isn't interested in any further updates
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index af194db..436e9b0 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -56,6 +56,7 @@
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.DisplayNameSources;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.StatusUpdates;
@@ -237,6 +238,8 @@
mAdapter.notifyDataSetChanged();
}
mListView.setEmptyView(mEmptyView);
+
+ getActivity().invalidateOptionsMenu();
}
/**
@@ -810,11 +813,35 @@
@Override
public void onPrepareOptionsMenu(Menu menu) {
+ if (mContactData == null) {
+ return;
+ }
+
+ boolean isDirectoryEntry = mContactData.isDirectoryEntry();
+
// Options only shows telephony-related settings (ringtone, send to voicemail).
// ==> Hide if we don't have a telephone
final MenuItem optionsMenu = menu.findItem(R.id.menu_options);
final boolean deviceHasPhone = PhoneCapabilityTester.isPhone(mContext);
- optionsMenu.setVisible(deviceHasPhone);
+ optionsMenu.setVisible(!isDirectoryEntry && deviceHasPhone);
+
+ final MenuItem editMenu = menu.findItem(R.id.menu_edit);
+ editMenu.setVisible(!isDirectoryEntry);
+
+ final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
+ deleteMenu.setVisible(!isDirectoryEntry);
+
+ final MenuItem shareMenu = menu.findItem(R.id.menu_share);
+ shareMenu.setVisible(!isDirectoryEntry && !mAllRestricted);
+
+ final MenuItem copyMenu = menu.findItem(R.id.menu_copy);
+ if (isDirectoryEntry) {
+ int exportSupport = mContactData.getDirectoryExportSupport();
+ copyMenu.setVisible(exportSupport == Directory.EXPORT_SUPPORT_ANY_ACCOUNT
+ || exportSupport == Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY);
+ } else {
+ copyMenu.setVisible(false);
+ }
}
@Override
@@ -855,6 +882,10 @@
}
return true;
}
+ case R.id.menu_copy: {
+ Toast.makeText(mContext, "Not implemented yet", Toast.LENGTH_SHORT).show();
+ return true;
+ }
}
return false;
}
diff --git a/src/com/android/contacts/views/detail/ContactDetailHeaderView.java b/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
index 00203da..553637d 100644
--- a/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
+++ b/src/com/android/contacts/views/detail/ContactDetailHeaderView.java
@@ -64,6 +64,7 @@
private ImageView mPresenceView;
private TextView mStatusView;
private TextView mStatusAttributionView;
+ private TextView mDirectoryNameView;
private Uri mContactUri;
private Listener mListener;
@@ -101,9 +102,10 @@
mPhotoView = (QuickContactBadge) findViewById(R.id.photo);
mPresenceView = (ImageView) findViewById(R.id.presence);
-
mStatusView = (TextView)findViewById(R.id.status);
mStatusAttributionView = (TextView)findViewById(R.id.status_date);
+
+ mDirectoryNameView = (TextView) findViewById(R.id.directory_name);
}
/**
@@ -121,6 +123,8 @@
setStatus(
contactData.getStatus(), contactData.getStatusTimestamp(),
contactData.getStatusLabel(), contactData.getStatusResPackage());
+ setDirectoryName(contactData.isDirectoryEntry(), contactData.getDirectoryDisplayName(),
+ contactData.getDirectoryType(), contactData.getDirectoryAccountName());
}
/**
@@ -323,6 +327,27 @@
setStatusAttribution(attribution);
}
+ private void setDirectoryName(boolean isDirectoryEntry, String directoryDisplayName,
+ String directoryType, String directoryAccountName) {
+ if (isDirectoryEntry) {
+ String name = TextUtils.isEmpty(directoryDisplayName)
+ ? directoryAccountName
+ : directoryDisplayName;
+ String text;
+ if (TextUtils.isEmpty(name)) {
+ text = getContext().getString(
+ R.string.contact_directory_description, directoryType);
+ } else {
+ text = getContext().getString(
+ R.string.contact_directory_account_description, directoryType, name);
+ }
+ mDirectoryNameView.setText(text);
+ mDirectoryNameView.setVisibility(View.VISIBLE);
+ } else {
+ mDirectoryNameView.setVisibility(View.GONE);
+ }
+ }
+
public void onClick(View view) {
switch (view.getId()) {
case R.id.star: {