Merge "Implement editor springboard activity" into ub-contactsdialer-h-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4e00b5f..6144e55 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -357,13 +357,6 @@
android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter>
- <action android:name="android.intent.action.EDIT" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.item/person" />
- <data android:mimeType="vnd.android.cursor.item/contact" />
- <data android:mimeType="vnd.android.cursor.item/raw_contact" />
- </intent-filter>
- <intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/person" />
@@ -372,6 +365,22 @@
</intent-filter>
</activity>
+ <activity
+ android:name=".activities.ContactEditorSpringBoardActivity"
+ android:noHistory="true"
+ android:theme="@style/TransparentThemeAppCompat">
+
+ <intent-filter>
+ <action android:name="android.intent.action.EDIT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/person" />
+ <data android:mimeType="vnd.android.cursor.item/contact" />
+ <data android:mimeType="vnd.android.cursor.item/raw_contact" />
+ </intent-filter>
+
+ </activity>
+
+
<activity android:name=".common.test.FragmentTestActivity">
<intent-filter>
<category android:name="android.intent.category.TEST" />
diff --git a/res/layout/raw_contact_list_item.xml b/res/layout/raw_contact_list_item.xml
new file mode 100644
index 0000000..ec5de0c
--- /dev/null
+++ b/res/layout/raw_contact_list_item.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/photo"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginEnd="16dp"
+ android:scaleType="fitCenter"/>
+
+ <LinearLayout
+ android:id="@+id/text_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/display_name"
+ android:textSize="16sp"
+ android:textColor="@color/quantum_black_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"/>
+
+ <LinearLayout
+ android:id="@+id/account_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical">
+
+ <ImageView
+ android:id="@+id/account_icon"
+ android:layout_width="14dp"
+ android:layout_height="14dp"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="4dp"
+ android:scaleType="fitCenter"/>
+
+ <TextView
+ android:id="@+id/account_name"
+ android:textSize="13sp"
+ android:textColor="@color/quantum_black_secondary_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"/>
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index d62f0f8..98c522d 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -14,6 +14,9 @@
limitations under the License.
-->
<resources>
+ <!-- 87% black -->
+ <color name="quantum_black_text">#dd000000</color>
+
<!-- 54% black -->
<color name="quantum_black_secondary_text">#89000000</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 566bd75..454777e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -693,6 +693,12 @@
at a pre-determined text size. [CHAR LIMIT=20] -->
<string name="contact_editor_title_existing_contact">Edit contact</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>
+
+ <!-- Text next to a contact's name that lets the user know it is a read only contact. [CHAR LIMIT=128] -->
+ <string name="contact_editor_pick_raw_contact_read_only"><xliff:g id="display_name">%s</xliff:g> (read only)</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/res/values/styles.xml b/res/values/styles.xml
index e7b6582..d51392a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -498,4 +498,14 @@
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowElevation">0dp</item>
</style>
+
+ <!-- Transparent/blank activity -->
+ <style name="TransparentThemeAppCompat" parent="@style/PeopleActivityTheme">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ </style>
</resources>
diff --git a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
new file mode 100644
index 0000000..f32ee5b
--- /dev/null
+++ b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
@@ -0,0 +1,182 @@
+package com.android.contacts.activities;
+
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.app.LoaderManager;
+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;
+import android.provider.ContactsContract.RawContacts;
+import android.widget.Toast;
+
+import com.android.contacts.AppCompatContactsActivity;
+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;
+
+/**
+ * Transparent springboard activity that hosts a dialog to select a raw contact to edit.
+ * This activity has noHistory set to true, and all intents coming out from it have
+ * {@code FLAG_ACTIVITY_FORWARD_RESULT} set.
+ */
+public class ContactEditorSpringBoardActivity extends AppCompatContactsActivity {
+ private static final String TAG = "EditorSpringBoard";
+ private static final String TAG_RAW_CONTACTS_DIALOG = "rawContactsDialog";
+ private static final int LOADER_RAW_CONTACTS = 1;
+
+ private Uri mUri;
+ private Cursor mCursor;
+ private MaterialPalette mMaterialPalette;
+
+ /**
+ * The contact data loader listener.
+ */
+ protected final LoaderManager.LoaderCallbacks<Cursor> mRawContactLoaderListener =
+ new LoaderManager.LoaderCallbacks<Cursor>() {
+
+ @Override
+ public Loader<Cursor> 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();
+ return;
+ }
+ mCursor = cursor;
+ if (mCursor.getCount() == 1) {
+ loadEditor();
+ } else {
+ showDialog();
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ mCursor = null;
+ }
+ };
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (RequestPermissionsActivity.startPermissionActivity(this)) {
+ return;
+ }
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+
+ if (!Intent.ACTION_EDIT.equals(action)) {
+ finish();
+ return;
+ }
+ // Just for shorter variable names.
+ final String primary = ContactEditorFragment.INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR;
+ final String secondary =
+ ContactEditorFragment.INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR;
+ if (intent.hasExtra(primary) && intent.hasExtra(secondary)) {
+ mMaterialPalette = new MaterialPalette(intent.getIntExtra(primary, -1),
+ intent.getIntExtra(secondary, -1));
+ }
+
+ mUri = intent.getData();
+ final String authority = mUri.getAuthority();
+ final String type = getContentResolver().getType(mUri);
+ // Go straight to editor if we're passed a raw contact Uri.
+ if (ContactsContract.AUTHORITY.equals(authority) &&
+ RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
+ final long rawContactId = ContentUris.parseId(mUri);
+ final Intent editorIntent = getIntentForRawContact(rawContactId);
+ ImplicitIntentsUtil.startActivityInApp(this, editorIntent);
+ } else {
+ getLoaderManager().initLoader(LOADER_RAW_CONTACTS, null, mRawContactLoaderListener);
+ }
+ }
+
+ /**
+ * Start the dialog to pick the raw contact to edit.
+ */
+ private void showDialog() {
+ final FragmentManager fm = getFragmentManager();
+ final PickRawContactDialogFragment oldFragment = (PickRawContactDialogFragment)
+ fm.findFragmentByTag(TAG_RAW_CONTACTS_DIALOG);
+ final FragmentTransaction ft = fm.beginTransaction();
+ if (oldFragment != null) {
+ ft.remove(oldFragment);
+ }
+ final PickRawContactDialogFragment newFragment =
+ PickRawContactDialogFragment.getInstance(mUri, mCursor, mMaterialPalette);
+ 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
+ // in the background, when it comes back onLoadFinished will be called again which will
+ // have all the state the picker needs. This situation should be very rare, since the load
+ // should be quick.
+ ft.commitAllowingStateLoss();
+ }
+
+ /**
+ * Starts the editor for the first (only) raw contact in the cursor.
+ */
+ private void loadEditor() {
+ final Intent intent;
+ if (isSingleWritableAccount()) {
+ mCursor.moveToFirst();
+ final long rawContactId = mCursor.getLong(PickRawContactLoader.RAW_CONTACT_ID);
+ intent = getIntentForRawContact(rawContactId);
+
+ } else {
+ // If it's a single read-only raw contact, 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);
+ }
+ ImplicitIntentsUtil.startActivityInApp(this, intent);
+ }
+
+ /**
+ * @return true if there is only one raw contact in the contact and it is from a writable
+ * account.
+ */
+ private boolean isSingleWritableAccount() {
+ if (mCursor.getCount() != 1) {
+ return false;
+ }
+ mCursor.moveToFirst();
+ 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);
+ return account.areContactsWritable();
+ }
+
+ /**
+ * Returns an intent to load the editor for the given raw contact. Sets
+ * {@code FLAG_ACTIVITY_FORWARD_RESULT} in case the activity that started us expects a result.
+ * @param rawContactId Raw contact to edit
+ */
+ private Intent getIntentForRawContact(long rawContactId) {
+ final Intent intent = EditorIntents.createEditContactIntentForRawContact(
+ this, mUri, rawContactId, mMaterialPalette);
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ return intent;
+ }
+}
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 80e1b82..0542436 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -203,6 +203,13 @@
public static final String INTENT_EXTRA_PHOTO_ID = "photo_id";
/**
+ * Intent key to pass the ID of the raw contact id that should be displayed in the full editor
+ * by itself.
+ */
+ public static final String INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE =
+ "raw_contact_id_to_display_alone";
+
+ /**
* Intent extra to specify a {@link ContactEditor.SaveMode}.
*/
public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
@@ -1478,6 +1485,8 @@
mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR),
mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR));
}
+ mRawContactIdToDisplayAlone = mIntentExtras
+ .getLong(INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE);
}
}
diff --git a/src/com/android/contacts/editor/EditorIntents.java b/src/com/android/contacts/editor/EditorIntents.java
index c4f48e6..c903b84 100644
--- a/src/com/android/contacts/editor/EditorIntents.java
+++ b/src/com/android/contacts/editor/EditorIntents.java
@@ -24,6 +24,7 @@
import android.text.TextUtils;
import com.android.contacts.activities.ContactEditorActivity;
+import com.android.contacts.activities.ContactEditorSpringBoardActivity;
import com.android.contacts.common.model.RawContactDeltaList;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
@@ -38,19 +39,32 @@
}
/**
- * Returns an Intent to start the {@link ContactEditorActivity} for an
+ * Returns an Intent to start the {@link ContactEditorSpringBoardActivity} for an
* existing contact.
*/
- public static Intent createEditContactIntent(Context context, Uri contactLookupUri,
+ public static Intent createEditContactIntent(Context context, Uri uri,
MaterialPalette materialPalette, long photoId) {
- final Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri, context,
- ContactEditorActivity.class);
+ final Intent intent = new Intent(Intent.ACTION_EDIT, uri, context,
+ ContactEditorSpringBoardActivity.class);
putMaterialPalette(intent, materialPalette);
putPhotoId(intent, photoId);
return intent;
}
/**
+ * Returns an Intent to start the {@link ContactEditorActivity} for the given raw contact.
+ */
+ public static Intent createEditContactIntentForRawContact(Context context,
+ Uri uri, long rawContactId, MaterialPalette materialPalette) {
+ final Intent intent = new Intent(Intent.ACTION_EDIT, uri, context,
+ ContactEditorActivity.class);
+ intent.putExtra(ContactEditorFragment.INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE,
+ rawContactId);
+ putMaterialPalette(intent, materialPalette);
+ return intent;
+ }
+
+ /**
* Returns an Intent to start the {@link ContactEditorActivity} for a new contact with
* the field values specified by rawContactDeltaList pre-populate in the form.
*/
@@ -71,9 +85,9 @@
* Returns an Intent to edit a different contact in the editor with whatever
* values were already entered on the current editor.
*/
- public static Intent createEditOtherContactIntent(Context context, Uri contactLookupUri,
+ public static Intent createEditOtherContactIntent(Context context, Uri uri,
ArrayList<ContentValues> contentValues) {
- final Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri, context,
+ final Intent intent = new Intent(Intent.ACTION_EDIT, uri, context,
ContactEditorActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_FORWARD_RESULT);
diff --git a/src/com/android/contacts/editor/PickRawContactDialogFragment.java b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
new file mode 100644
index 0000000..20e8f35
--- /dev/null
+++ b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
@@ -0,0 +1,162 @@
+package com.android.contacts.editor;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.contacts.R;
+import com.android.contacts.common.ContactPhotoManager;
+import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
+
+/**
+ * Dialog containing the raw contacts that make up a contact. On selection the editor is loaded
+ * for the chosen raw contact.
+ */
+public class PickRawContactDialogFragment extends DialogFragment {
+ /**
+ * Used to list the account info for the given raw contacts list.
+ */
+ private static final class RawContactAccountListAdapter extends CursorAdapter {
+ private final LayoutInflater mInflater;
+ private final Context mContext;
+
+ public RawContactAccountListAdapter(Context context, Cursor cursor) {
+ super(context, cursor, 0);
+ mContext = context;
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @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 = AccountTypeManager.getInstance(mContext)
+ .getAccountType(accountType, dataSet);
+
+ final ContactsPreferences prefs = new ContactsPreferences(mContext);
+ final int displayNameColumn =
+ prefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
+ ? PickRawContactLoader.DISPLAY_NAME_PRIMARY
+ : PickRawContactLoader.DISPLAY_NAME_ALTERNATIVE;
+ String displayName = cursor.getString(displayNameColumn);
+
+ final TextView nameView = (TextView) view.findViewById(
+ R.id.display_name);
+ final TextView accountTextView = (TextView) view.findViewById(
+ R.id.account_name);
+ final ImageView accountIconView = (ImageView) view.findViewById(
+ R.id.account_icon);
+
+ if (!account.areContactsWritable()) {
+ displayName = mContext
+ .getString(R.string.contact_editor_pick_raw_contact_read_only, displayName);
+ view.setAlpha(.38f);
+ } else {
+ view.setAlpha(1f);
+ }
+
+ nameView.setText(displayName);
+ accountTextView.setText(accountName);
+ accountIconView.setImageDrawable(account.getDisplayIcon(mContext));
+
+ final ContactPhotoManager.DefaultImageRequest
+ request = new ContactPhotoManager.DefaultImageRequest(
+ displayName, String.valueOf(rawContactId), /* isCircular = */ true);
+ final ImageView photoView = (ImageView) view.findViewById(
+ R.id.photo);
+ ContactPhotoManager.getInstance(mContext).loadDirectoryPhoto(photoView,
+ ContactPhotoManager.getDefaultAvatarUriForContact(request),
+ /* darkTheme = */ false,
+ /* isCircular = */ true,
+ request);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.raw_contact_list_item, parent, false);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ getCursor().moveToPosition(position);
+ return getCursor().getLong(PickRawContactLoader.RAW_CONTACT_ID);
+ }
+ }
+
+ // Cursor holding all raw contact rows for the given Contact.
+ private Cursor mCursor;
+ // Uri for the whole Contact.
+ private Uri mUri;
+ private MaterialPalette mMaterialPalette;
+
+ public static PickRawContactDialogFragment getInstance(Uri uri, Cursor cursor,
+ MaterialPalette materialPalette) {
+ final PickRawContactDialogFragment fragment = new PickRawContactDialogFragment();
+ fragment.setUri(uri);
+ fragment.setCursor(cursor);
+ fragment.setMaterialPalette(materialPalette);
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ final CursorAdapter adapter = new RawContactAccountListAdapter(getContext(), mCursor);
+ builder.setTitle(R.string.contact_editor_pick_raw_contact_dialog_title);
+ builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final long rawContactId = adapter.getItemId(which);
+ final Intent intent = EditorIntents.createEditContactIntentForRawContact(
+ getActivity(), mUri, rawContactId, mMaterialPalette);
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ ImplicitIntentsUtil.startActivityInApp(getActivity(), intent);
+ }
+ });
+ builder.setCancelable(true);
+ return builder.create();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ mCursor = null;
+ finishActivity();
+ }
+
+ private void setUri(Uri uri) {
+ mUri = uri;
+ }
+
+ private void setCursor(Cursor cursor) {
+ mCursor = cursor;
+ }
+
+ private void setMaterialPalette(MaterialPalette materialPalette) {
+ mMaterialPalette = materialPalette;
+ }
+
+ 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
new file mode 100644
index 0000000..62be517
--- /dev/null
+++ b/src/com/android/contacts/editor/PickRawContactLoader.java
@@ -0,0 +1,78 @@
+package com.android.contacts.editor;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+
+/**
+ * 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 {
+ private Uri mContactUri;
+
+ public static final String[] COLUMNS = new String[] {
+ RawContacts.ACCOUNT_NAME,
+ RawContacts.ACCOUNT_TYPE,
+ RawContacts.DATA_SET,
+ RawContacts._ID,
+ RawContacts.DISPLAY_NAME_PRIMARY,
+ RawContacts.DISPLAY_NAME_ALTERNATIVE
+ };
+
+ public static final String 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;
+
+ public PickRawContactLoader(Context context, Uri contactUri) {
+ super(context, ensureIsContactUri(contactUri), COLUMNS, SELECTION, null, RawContacts._ID);
+ mContactUri = contactUri;
+ }
+
+ @Override
+ public Cursor loadInBackground() {
+ // Get the id of the contact we're looking at.
+ final Cursor cursor = getContext().getContentResolver()
+ .query(mContactUri, new String[] { Contacts._ID }, null,
+ null, null);
+
+ if (cursor == null) {
+ return null;
+ }
+
+ if (cursor.getCount() < 1) {
+ cursor.close();
+ return null;
+ }
+
+ cursor.moveToFirst();
+ final long contactId = cursor.getLong(0);
+ cursor.close();
+ // Update selection arguments and uri.
+ setSelectionArgs(new String[]{ Long.toString(contactId) });
+ setUri(RawContacts.CONTENT_URI);
+ return super.loadInBackground();
+ }
+
+ /**
+ * Ensures that this is a valid contact URI. If invalid, then an exception is
+ * thrown. Otherwise, the original URI is returned.
+ */
+ private static Uri ensureIsContactUri(final Uri uri) {
+ if (uri == null) {
+ throw new IllegalArgumentException("Uri must not be null");
+ }
+ if (!uri.toString().startsWith(Contacts.CONTENT_URI.toString())) {
+ throw new IllegalArgumentException("Invalid contact Uri: " + uri);
+ }
+ return uri;
+ }
+}