Ignore read-only raw contacts in picker modal pt. 1
Drop read-only contacts unless the SpringboardActivity is configured
not to.
Changed to using AsyncTaskLoader that returns a RawContactsMetadata
object which has all the information needed by the picker dialog.
Ignore legacy edit URIs and send silent feedback if they are given.
Test:
Manually checked the following scenarios has the correct behavior:
* Single writable raw contact
* Multiple writable raw contacts
* 1 read-only 1 writable
* 1 read-only
* 2 read-only
* Test app usage of legacy URI
Bug: 32640214
Bug: 32240763
Change-Id: Ia3542b927ea615a2b2d07f86cdc1ff8c91f99ba6
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b1e4762..41df84f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -726,7 +726,7 @@
<string name="contact_editor_title_read_only_contact">View only</string>
<!-- Dialog title when the user is selecting a raw contact to edit. [CHAR LIMIT=128] -->
- <string name="contact_editor_pick_raw_contact_dialog_title">Choose linked contact</string>
+ <string name="contact_editor_pick_raw_contact_to_edit_dialog_title">Choose contact to edit</string>
<!-- Button label to prompt the user to add an account (when there are 0 existing accounts on the device) [CHAR LIMIT=30] -->
<string name="add_account">Add account</string>
diff --git a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
index 69dccb5..3d47b8f 100644
--- a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
@@ -6,7 +6,6 @@
import android.content.ContentUris;
import android.content.Intent;
import android.content.Loader;
-import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
@@ -17,13 +16,14 @@
import com.android.contacts.R;
import com.android.contacts.common.activity.RequestPermissionsActivity;
import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.contacts.editor.ContactEditorFragment;
import com.android.contacts.editor.EditorIntents;
import com.android.contacts.editor.PickRawContactDialogFragment;
import com.android.contacts.editor.PickRawContactLoader;
+import com.android.contacts.editor.PickRawContactLoader.RawContactsMetadata;
+import com.android.contactsbind.FeedbackHelper;
/**
* Transparent springboard activity that hosts a dialog to select a raw contact to edit.
@@ -36,36 +36,36 @@
private static final String TAG_RAW_CONTACTS_DIALOG = "rawContactsDialog";
private static final int LOADER_RAW_CONTACTS = 1;
+ public static final String EXTRA_SHOW_READ_ONLY = "showReadOnly";
+
private Uri mUri;
- private Cursor mCursor;
+ private RawContactsMetadata mResult;
private MaterialPalette mMaterialPalette;
- private boolean mIsUserProfile;
private boolean mHasWritableAccount;
private int mWritableAccountPosition;
/**
* The contact data loader listener.
*/
- protected final LoaderManager.LoaderCallbacks<Cursor> mRawContactLoaderListener =
- new LoaderManager.LoaderCallbacks<Cursor>() {
+ protected final LoaderManager.LoaderCallbacks<RawContactsMetadata> mRawContactLoaderListener =
+ new LoaderManager.LoaderCallbacks<RawContactsMetadata>() {
@Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ public Loader<RawContactsMetadata> onCreateLoader(int id, Bundle args) {
return new PickRawContactLoader(ContactEditorSpringBoardActivity.this, mUri);
}
@Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
- if (cursor == null) {
- Toast.makeText(ContactEditorSpringBoardActivity.this,
- R.string.editor_failed_to_load, Toast.LENGTH_SHORT).show();
- finish();
+ public void onLoadFinished(Loader<RawContactsMetadata> loader,
+ RawContactsMetadata result) {
+ if (result == null) {
+ toastErrorAndFinish();
return;
}
- mCursor = cursor;
- mIsUserProfile = ((PickRawContactLoader) loader).isUserProfile();
+ mResult = result;
+ maybeTrimReadOnly();
setHasWritableAccount();
- if (mCursor.getCount() > 1 && mHasWritableAccount) {
+ if (mResult.rawContacts.size() > 1 && mHasWritableAccount) {
showDialog();
} else {
loadEditor();
@@ -73,8 +73,7 @@
}
@Override
- public void onLoaderReset(Loader<Cursor> loader) {
- mCursor = null;
+ public void onLoaderReset(Loader<RawContactsMetadata> loader) {
}
};
@@ -111,6 +110,11 @@
RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
final long rawContactId = ContentUris.parseId(mUri);
startEditorAndForwardExtras(getIntentForRawContact(rawContactId));
+ } else if (android.provider.Contacts.AUTHORITY.equals(authority)) {
+ // Fail if given a legacy URI.
+ FeedbackHelper.sendFeedback(this, TAG,
+ "Legacy Uri was passed to editor.", new IllegalArgumentException());
+ toastErrorAndFinish();
} else {
getLoaderManager().initLoader(LOADER_RAW_CONTACTS, null, mRawContactLoaderListener);
}
@@ -122,6 +126,19 @@
}
/**
+ * If not configured to show read only raw contact, trim them from the result.
+ */
+ private void maybeTrimReadOnly() {
+ final boolean showReadOnly = getIntent().getBooleanExtra(EXTRA_SHOW_READ_ONLY, false);
+ mResult.showReadOnly = showReadOnly;
+
+ if (showReadOnly) {
+ return;
+ }
+ mResult.trimReadOnly(AccountTypeManager.getInstance(this));
+ }
+
+ /**
* Start the dialog to pick the raw contact to edit.
*/
private void showDialog() {
@@ -130,8 +147,6 @@
fm.findFragmentByTag(TAG_RAW_CONTACTS_DIALOG);
if (oldFragment != null && oldFragment.getDialog() != null
&& oldFragment.getDialog().isShowing()) {
- // Just update the cursor without reshowing the dialog.
- oldFragment.setCursor(mCursor);
return;
}
final FragmentTransaction ft = fm.beginTransaction();
@@ -139,7 +154,7 @@
ft.remove(oldFragment);
}
final PickRawContactDialogFragment newFragment = PickRawContactDialogFragment.getInstance(
- mCursor, mIsUserProfile);
+ mResult);
ft.add(newFragment, TAG_RAW_CONTACTS_DIALOG);
// commitAllowingStateLoss is safe in this activity because the fragment entirely depends
// on the result of the loader. Even if we lose the fragment because the activity was
@@ -156,18 +171,13 @@
private void loadEditor() {
final Intent intent;
if (mHasWritableAccount) {
- mCursor.moveToPosition(mWritableAccountPosition);
- final long rawContactId = mCursor.getLong(PickRawContactLoader.RAW_CONTACT_ID);
- intent = getIntentForRawContact(rawContactId);
+ intent = getIntentForRawContact(mResult.rawContacts.get(mWritableAccountPosition).id);
} else {
// If the contact has only read-only raw contacts, we'll want to let the editor create
// the writable raw contact for it.
intent = EditorIntents.createEditContactIntent(this, mUri, mMaterialPalette, -1);
intent.setClass(this, ContactEditorActivity.class);
}
- // Destroy the loader to prevent multiple onLoadFinished calls in case CP2 is updating in
- // the background.
- getLoaderManager().destroyLoader(LOADER_RAW_CONTACTS);
startEditorAndForwardExtras(intent);
}
@@ -175,18 +185,9 @@
* Determines if this contact has a writable account.
*/
private void setHasWritableAccount() {
- mCursor.moveToPosition(-1);
- while (mCursor.moveToNext()) {
- final String accountType = mCursor.getString(PickRawContactLoader.ACCOUNT_TYPE);
- final String dataSet = mCursor.getString(PickRawContactLoader.DATA_SET);
- final AccountType account = AccountTypeManager.getInstance(this)
- .getAccountType(accountType, dataSet);
- if (account.areContactsWritable()) {
- mHasWritableAccount = true;
- mWritableAccountPosition = mCursor.getPosition();
- return;
- }
- }
+ mWritableAccountPosition = mResult.getIndexOfFirstWritableAccount(
+ AccountTypeManager.getInstance(this));
+ mHasWritableAccount = mWritableAccountPosition != -1;
}
/**
@@ -211,4 +212,11 @@
}
ImplicitIntentsUtil.startActivityInApp(this, intent);
}
+
+ private void toastErrorAndFinish() {
+ Toast.makeText(ContactEditorSpringBoardActivity.this,
+ R.string.editor_failed_to_load, Toast.LENGTH_SHORT).show();
+ setResult(RESULT_CANCELED, null);
+ finish();
+ }
}
diff --git a/src/com/android/contacts/editor/PickRawContactDialogFragment.java b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
index 6b0051e..aa3e015 100644
--- a/src/com/android/contacts/editor/PickRawContactDialogFragment.java
+++ b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
@@ -6,7 +6,6 @@
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
-import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.RawContacts;
@@ -14,8 +13,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CursorAdapter;
+import android.widget.BaseAdapter;
import android.widget.ImageView;
+import android.widget.ListAdapter;
import android.widget.TextView;
import com.android.contacts.R;
@@ -27,6 +27,8 @@
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.model.account.GoogleAccountType;
import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.editor.PickRawContactLoader.RawContact;
+import com.android.contacts.editor.PickRawContactLoader.RawContactsMetadata;
/**
* Should only be started from an activity that implements {@link PickRawContactListener}.
@@ -34,7 +36,7 @@
* for the chosen raw contact.
*/
public class PickRawContactDialogFragment extends DialogFragment {
- private static final String ARGS_IS_USER_PROFILE = "isUserProfile";
+ private static final String ARGS_RAW_CONTACTS_METADATA = "rawContactsMetadata";
public interface PickRawContactListener {
void onPickRawContact(long rawContactId);
@@ -43,69 +45,93 @@
/**
* Used to list the account info for the given raw contacts list.
*/
- private final class RawContactAccountListAdapter extends CursorAdapter {
+ private final class RawContactAccountListAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
private final Context mContext;
+ private final RawContactsMetadata mRawContactsMetadata;
private final AccountDisplayInfoFactory mAccountDisplayInfoFactory;
private final AccountTypeManager mAccountTypeManager;
private final ContactsPreferences mPreferences;
- public RawContactAccountListAdapter(Context context, Cursor cursor) {
- super(context, cursor, 0);
+ public RawContactAccountListAdapter(Context context,
+ RawContactsMetadata rawContactsMetadata) {
mContext = context;
mInflater = LayoutInflater.from(context);
mAccountDisplayInfoFactory = AccountDisplayInfoFactory.forWritableAccounts(context);
mAccountTypeManager = AccountTypeManager.getInstance(context);
mPreferences = new ContactsPreferences(context);
+ mRawContactsMetadata = rawContactsMetadata;
}
@Override
- public void bindView(View view, Context context, Cursor cursor) {
- final long rawContactId = cursor.getLong(PickRawContactLoader.RAW_CONTACT_ID);
- final String accountName = cursor.getString(PickRawContactLoader.ACCOUNT_NAME);
- final String accountType = cursor.getString(PickRawContactLoader.ACCOUNT_TYPE);
- final String dataSet = cursor.getString(PickRawContactLoader.DATA_SET);
- final AccountType account = mAccountTypeManager.getAccountType(accountType, dataSet);
+ public int getCount() {
+ return mRawContactsMetadata.rawContacts.size();
+ }
- final int displayNameColumn =
+ @Override
+ public Object getItem(int position) {
+ return mRawContactsMetadata.rawContacts.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mRawContactsMetadata.rawContacts.get(position).id;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View view;
+ final RawContactViewHolder holder;
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.raw_contact_list_item, parent, false);
+ holder = new RawContactViewHolder();
+ holder.displayName = (TextView) view.findViewById(R.id.display_name);
+ holder.accountName = (TextView) view.findViewById(R.id.account_name);
+ holder.accountIcon = (ImageView) view.findViewById(R.id.account_icon);
+ holder.photo = (ImageView) view.findViewById(R.id.photo);
+ view.setTag(holder);
+ } else {
+ view = convertView;
+ holder = (RawContactViewHolder) view.getTag();
+ }
+ final RawContact rawContact = mRawContactsMetadata.rawContacts.get(position);
+ final AccountType account = mAccountTypeManager.getAccountType(rawContact.accountType,
+ rawContact.accountDataSet);
+
+ String displayName =
mPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
- ? PickRawContactLoader.DISPLAY_NAME_PRIMARY
- : PickRawContactLoader.DISPLAY_NAME_ALTERNATIVE;
-
- String displayName = cursor.getString(displayNameColumn);
+ ? rawContact.displayName : rawContact.displayNameAlt;
if (TextUtils.isEmpty(displayName)) {
displayName = mContext.getString(R.string.missing_name);
}
- final RawContactViewHolder holder = (RawContactViewHolder) view.getTag();
holder.displayName.setText(displayName);
final String accountDisplayLabel;
// Use the same string as editor if it's an editable user profile raw contact.
- if (mIsUserProfile && account.areContactsWritable()) {
+ if (mRawContactsMetadata.isUserProfile && account.areContactsWritable()) {
final AccountDisplayInfo displayInfo =
mAccountDisplayInfoFactory.getAccountDisplayInfo(
- new AccountWithDataSet(accountName, accountType, dataSet));
+ new AccountWithDataSet(rawContact.accountName,
+ rawContact.accountType, rawContact.accountDataSet));
accountDisplayLabel = EditorUiUtils.getAccountHeaderLabelForMyProfile(mContext,
displayInfo);
- }
- else if (GoogleAccountType.ACCOUNT_TYPE.equals(accountType)
+ } else if (GoogleAccountType.ACCOUNT_TYPE.equals(rawContact.accountType)
&& account.dataSet == null) {
// Focus Google accounts have the account name shown
- accountDisplayLabel = accountName;
+ accountDisplayLabel = rawContact.accountName;
} else {
accountDisplayLabel = account.getDisplayLabel(mContext).toString();
}
holder.accountName.setText(accountDisplayLabel);
holder.accountIcon.setImageDrawable(account.getDisplayIcon(mContext));
-
final ContactPhotoManager.DefaultImageRequest
request = new ContactPhotoManager.DefaultImageRequest(
- displayName, String.valueOf(rawContactId), /* isCircular = */ true);
+ displayName, String.valueOf(rawContact.id), /* isCircular = */ true);
final Uri photoUri = Uri.withAppendedPath(
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContact.id),
RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
ContactPhotoManager.getInstance(mContext).loadDirectoryPhoto(holder.photo,
@@ -113,26 +139,10 @@
/* darkTheme = */ false,
/* isCircular = */ true,
request);
- }
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- final View view = mInflater.inflate(R.layout.raw_contact_list_item, parent, false);
- final RawContactViewHolder holder = new RawContactViewHolder();
- holder.displayName = (TextView) view.findViewById(R.id.display_name);
- holder.accountName = (TextView) view.findViewById(R.id.account_name);
- holder.accountIcon = (ImageView) view.findViewById(R.id.account_icon);
- holder.photo = (ImageView) view.findViewById(R.id.photo);
- view.setTag(holder);
return view;
}
- @Override
- public long getItemId(int position) {
- getCursor().moveToPosition(position);
- return getCursor().getLong(PickRawContactLoader.RAW_CONTACT_ID);
- }
-
class RawContactViewHolder {
TextView displayName;
TextView accountName;
@@ -141,17 +151,13 @@
}
}
- // Cursor holding all raw contact rows for the given Contact.
- private Cursor mCursor;
- private CursorAdapter mAdapter;
- private boolean mIsUserProfile;
+ private ListAdapter mAdapter;
- public static PickRawContactDialogFragment getInstance(Cursor cursor, boolean isUserProfile) {
+ public static PickRawContactDialogFragment getInstance(RawContactsMetadata metadata) {
final PickRawContactDialogFragment fragment = new PickRawContactDialogFragment();
final Bundle args = new Bundle();
- args.putBoolean(ARGS_IS_USER_PROFILE, isUserProfile);
+ args.putParcelable(ARGS_RAW_CONTACTS_METADATA, metadata);
fragment.setArguments(args);
- fragment.setCursor(cursor);
return fragment;
}
@@ -161,9 +167,19 @@
throw new IllegalArgumentException(
"Host activity doesn't implement PickRawContactListener");
}
+ final Bundle args = getArguments();
+ if (args == null) {
+ throw new IllegalArgumentException("Dialog created with no arguments");
+ }
+
+ final RawContactsMetadata metadata = args.getParcelable(ARGS_RAW_CONTACTS_METADATA);
+ if (metadata == null) {
+ throw new IllegalArgumentException("Dialog created with null RawContactsMetadata");
+ }
+
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- mAdapter = new RawContactAccountListAdapter(getContext(), mCursor);
- builder.setTitle(R.string.contact_editor_pick_raw_contact_dialog_title);
+ mAdapter = new RawContactAccountListAdapter(getContext(), metadata);
+ builder.setTitle(R.string.contact_editor_pick_raw_contact_to_edit_dialog_title);
builder.setAdapter(mAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -178,32 +194,14 @@
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
- mCursor = null;
finishActivity();
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Bundle args = getArguments();
- if (args != null) {
- mIsUserProfile = args.getBoolean(ARGS_IS_USER_PROFILE);
- }
- }
-
- @Override
public Context getContext() {
return getActivity();
}
- public void setCursor(Cursor cursor) {
- if (mAdapter != null) {
- mAdapter.swapCursor(cursor);
- }
- mCursor = cursor;
- }
-
private void finishActivity() {
if (getActivity() != null && !getActivity().isFinishing()) {
getActivity().finish();
diff --git a/src/com/android/contacts/editor/PickRawContactLoader.java b/src/com/android/contacts/editor/PickRawContactLoader.java
index ca44e21..1939666 100644
--- a/src/com/android/contacts/editor/PickRawContactLoader.java
+++ b/src/com/android/contacts/editor/PickRawContactLoader.java
@@ -1,22 +1,31 @@
package com.android.contacts.editor;
+import android.content.AsyncTaskLoader;
+import android.content.ContentResolver;
import android.content.Context;
-import android.content.CursorLoader;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.account.AccountType;
+
+import java.util.ArrayList;
+
/**
* Loader for the pick a raw contact to edit activity. Loads all raw contact metadata for the
* given Contact {@link Uri}.
*/
-public class PickRawContactLoader extends CursorLoader {
+public class PickRawContactLoader extends
+ AsyncTaskLoader<PickRawContactLoader.RawContactsMetadata> {
private Uri mContactUri;
- private boolean mIsUserProfile;
+ private RawContactsMetadata mCachedResult;
- public static final String[] COLUMNS = new String[] {
+ private static final String[] RAW_CONTACT_PROJECTION = new String[] {
RawContacts.ACCOUNT_NAME,
RawContacts.ACCOUNT_TYPE,
RawContacts.DATA_SET,
@@ -25,53 +34,97 @@
RawContacts.DISPLAY_NAME_ALTERNATIVE
};
- public static final String SELECTION = RawContacts.CONTACT_ID + "=?";
+ private static final String RAW_CONTACT_SELECTION = RawContacts.CONTACT_ID + "=?";
- public static final int ACCOUNT_NAME = 0;
- public static final int ACCOUNT_TYPE = 1;
- public static final int DATA_SET = 2;
- public static final int RAW_CONTACT_ID = 3;
- public static final int DISPLAY_NAME_PRIMARY = 4;
- public static final int DISPLAY_NAME_ALTERNATIVE = 5;
+ private static final int ACCOUNT_NAME = 0;
+ private static final int ACCOUNT_TYPE = 1;
+ private static final int DATA_SET = 2;
+ private static final int RAW_CONTACT_ID = 3;
+ private static final int DISPLAY_NAME_PRIMARY = 4;
+ private static final int DISPLAY_NAME_ALTERNATIVE = 5;
public PickRawContactLoader(Context context, Uri contactUri) {
- super(context, ensureIsContactUri(contactUri), COLUMNS, SELECTION, null, RawContacts._ID);
- mContactUri = contactUri;
+ super(context);
+ mContactUri = ensureIsContactUri(contactUri);
}
@Override
- public Cursor loadInBackground() {
+ public RawContactsMetadata loadInBackground() {
+ final ContentResolver resolver = getContext().getContentResolver();
// Get the id of the contact we're looking at.
- final Cursor cursor = getContext().getContentResolver()
- .query(mContactUri, new String[] { Contacts._ID, Contacts.IS_USER_PROFILE }, null,
+ final Cursor contactCursor = resolver.query(
+ mContactUri, new String[]{Contacts._ID, Contacts.IS_USER_PROFILE}, null,
null, null);
- if (cursor == null) {
+ if (contactCursor == null) {
return null;
}
- if (cursor.getCount() < 1) {
- cursor.close();
+ if (contactCursor.getCount() < 1) {
+ contactCursor.close();
return null;
}
- cursor.moveToFirst();
- final long contactId = cursor.getLong(/* Contacts._ID */ 0);
- mIsUserProfile = cursor.getInt(/* Contacts.IS_USER_PROFILE */ 1) == 1;
+ final RawContactsMetadata result = new RawContactsMetadata();
+ final long contactId;
+ try {
+ contactCursor.moveToFirst();
+ contactId = contactCursor.getLong(/* Contacts._ID */ 0);
+ result.isUserProfile = contactCursor.getInt(/* Contacts.IS_USER_PROFILE */ 1) == 1;
+ } finally {
+ contactCursor.close();
+ }
- cursor.close();
- // Update selection arguments and uri.
- setSelectionArgs(new String[]{ Long.toString(contactId) });
- if (mIsUserProfile) {
- setUri(ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI);
+ // Load RawContact data
+ final Uri rawContactUri;
+ if (result.isUserProfile) {
+ rawContactUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI;
} else {
- setUri(RawContacts.CONTENT_URI);
+ rawContactUri = RawContacts.CONTENT_URI;
}
- return super.loadInBackground();
+
+ final Cursor rawContactCursor = resolver.query(
+ rawContactUri, RAW_CONTACT_PROJECTION, RAW_CONTACT_SELECTION,
+ new String[] {Long.toString(contactId)}, null);
+
+ if (rawContactCursor == null) {
+ return null;
+ }
+
+ rawContactCursor.moveToPosition(-1);
+ try {
+ while (rawContactCursor.moveToNext()) {
+ RawContact rawContact = new RawContact();
+ rawContact.id = rawContactCursor.getLong(RAW_CONTACT_ID);
+ rawContact.displayName = rawContactCursor.getString(DISPLAY_NAME_PRIMARY);
+ rawContact.displayNameAlt = rawContactCursor.getString(DISPLAY_NAME_ALTERNATIVE);
+ rawContact.accountName = rawContactCursor.getString(ACCOUNT_NAME);
+ rawContact.accountType = rawContactCursor.getString(ACCOUNT_TYPE);
+ rawContact.accountDataSet = rawContactCursor.getString(DATA_SET);
+ result.rawContacts.add(rawContact);
+ }
+ } finally {
+ rawContactCursor.close();
+ }
+ return result;
}
- public boolean isUserProfile() {
- return mIsUserProfile;
+ @Override
+ public void deliverResult(RawContactsMetadata data) {
+ mCachedResult = data;
+ if (isStarted()) {
+ super.deliverResult(data);
+ }
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ if (mCachedResult == null) {
+ forceLoad();
+ } else {
+ deliverResult(mCachedResult);
+ }
}
/**
@@ -87,4 +140,121 @@
}
return uri;
}
+
+ public static class RawContactsMetadata implements Parcelable {
+ public static final Parcelable.Creator<RawContactsMetadata> CREATOR =
+ new Parcelable.Creator<RawContactsMetadata>() {
+ @Override
+ public RawContactsMetadata createFromParcel(Parcel source) {
+ return new RawContactsMetadata(source);
+ }
+
+ @Override
+ public RawContactsMetadata[] newArray(int size) {
+ return new RawContactsMetadata[size];
+ }
+ };
+
+ public boolean isUserProfile;
+ public boolean showReadOnly = false;
+ public ArrayList<RawContact> rawContacts = new ArrayList<>();
+
+ public RawContactsMetadata() {}
+
+ private RawContactsMetadata(Parcel in) {
+ isUserProfile = in.readInt() == 1;
+ showReadOnly = in.readInt() == 1;
+ in.readTypedList(rawContacts, RawContact.CREATOR);
+ }
+
+ /**
+ * Removes all read-only raw contacts.
+ */
+ public void trimReadOnly(AccountTypeManager accountManager) {
+ for (int i = rawContacts.size() - 1; i >= 0 ; i--) {
+ final RawContact rawContact = rawContacts.get(i);
+ final AccountType account = accountManager.getAccountType(
+ rawContact.accountType, rawContact.accountDataSet);
+ if (!account.areContactsWritable()) {
+ rawContacts.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Returns the index of the first writable account in this contact or -1 if none exist.
+ */
+ public int getIndexOfFirstWritableAccount(AccountTypeManager accountManager) {
+ for (int i = 0; i < rawContacts.size(); i++) {
+ final RawContact rawContact = rawContacts.get(i);
+ final AccountType account = accountManager.getAccountType(
+ rawContact.accountType, rawContact.accountDataSet);
+ if (account.areContactsWritable()) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(isUserProfile ? 1 : 0);
+ dest.writeInt(showReadOnly ? 1 : 0);
+ dest.writeTypedList(rawContacts);
+ }
+ }
+
+ public static class RawContact implements Parcelable {
+ public static final Parcelable.Creator<RawContact> CREATOR =
+ new Parcelable.Creator<RawContact>() {
+ @Override
+ public RawContact createFromParcel(Parcel source) {
+ return new RawContact(source);
+ }
+
+ @Override
+ public RawContact[] newArray(int size) {
+ return new RawContact[size];
+ }
+ };
+
+ public long id;
+ public String displayName;
+ public String displayNameAlt;
+ public String accountName;
+ public String accountType;
+ public String accountDataSet;
+
+ public RawContact() {}
+
+ private RawContact(Parcel in) {
+ id = in.readLong();
+ displayName = in.readString();
+ displayNameAlt = in.readString();
+ accountName = in.readString();
+ accountType = in.readString();
+ accountDataSet = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(id);
+ dest.writeString(displayName);
+ dest.writeString(displayNameAlt);
+ dest.writeString(accountName);
+ dest.writeString(accountType);
+ dest.writeString(accountDataSet);
+ }
+ }
}