auto import from //branches/cupcake_rel/...@140373
diff --git a/src/com/android/contacts/ShowOrCreateActivity.java b/src/com/android/contacts/ShowOrCreateActivity.java
new file mode 100755
index 0000000..8d3cf0b
--- /dev/null
+++ b/src/com/android/contacts/ShowOrCreateActivity.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.contacts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.AsyncQueryHandler;
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts;
+import android.provider.Contacts.ContactMethods;
+import android.provider.Contacts.ContactMethodsColumns;
+import android.provider.Contacts.Intents;
+import android.provider.Contacts.People;
+import android.provider.Contacts.Phones;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Handle several edge cases around showing or possibly creating contacts in
+ * connected with a specific E-mail address or phone number. Will search based
+ * on incoming {@link Intent#getData()} as described by
+ * {@link Intents#SHOW_OR_CREATE_CONTACT}.
+ * <ul>
+ * <li>If no matching contacts found, will prompt user with dialog to add to a
+ * contact, then will use {@link Intent#ACTION_INSERT_OR_EDIT} to let create new
+ * contact or edit new data into an existing one.
+ * <li>If one matching contact found, directly show {@link Intent#ACTION_VIEW}
+ * that specific contact.
+ * <li>If more than one matching found, show list of matching contacts using
+ * {@link Intent#ACTION_SEARCH}.
+ * </ul>
+ */
+public final class ShowOrCreateActivity extends Activity {
+ static final String TAG = "ShowOrCreateActivity";
+ static final boolean LOGD = false;
+
+ static final String[] PHONES_PROJECTION = new String[] {
+ Phones._ID,
+ Phones.PERSON_ID,
+ };
+
+ static final String[] CONTACT_METHODS_PROJECTION = new String[] {
+ ContactMethods._ID,
+ ContactMethods.PERSON_ID,
+ };
+
+ static final String SCHEME_MAILTO = "mailto";
+ static final String SCHEME_TEL = "tel";
+
+ static final int ID_INDEX = 0;
+ static final int PERSON_ID_INDEX = 1;
+
+ /**
+ * Query clause to filter {@link ContactMethods#CONTENT_URI} to only search
+ * {@link Contacts#KIND_EMAIL} or {@link Contacts#KIND_IM}.
+ */
+ static final String QUERY_KIND_EMAIL_OR_IM = ContactMethodsColumns.KIND +
+ " IN (" + Contacts.KIND_EMAIL + "," + Contacts.KIND_IM + ")";
+
+ static final int QUERY_TOKEN = 42;
+
+ private QueryHandler mQueryHandler;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Create handler if doesn't exist, otherwise cancel any running
+ if (mQueryHandler == null) {
+ mQueryHandler = new QueryHandler(this);
+ } else {
+ mQueryHandler.cancelOperation(QUERY_TOKEN);
+ }
+
+ final Intent intent = getIntent();
+ final Uri data = intent.getData();
+
+ // Unpack scheme and target data from intent
+ String scheme = null;
+ String ssp = null;
+ if (data != null) {
+ scheme = data.getScheme();
+ ssp = data.getSchemeSpecificPart();
+ }
+
+ // Build set of extras for possible use when creating contact
+ Bundle createExtras = new Bundle();
+ Bundle originalExtras = intent.getExtras();
+ if (originalExtras != null) {
+ createExtras.putAll(originalExtras);
+ }
+ mQueryHandler.setCreateExtras(createExtras);
+
+ // Read possible extra with specific title
+ String createDescrip = intent.getStringExtra(Intents.EXTRA_CREATE_DESCRIPTION);
+ if (createDescrip == null) {
+ createDescrip = ssp;
+ }
+ mQueryHandler.setCreateDescription(createDescrip);
+
+ // Allow caller to bypass dialog prompt
+ boolean createForce = intent.getBooleanExtra(Intents.EXTRA_FORCE_CREATE, false);
+ mQueryHandler.setCreateForce(createForce);
+
+ // Handle specific query request
+ if (SCHEME_MAILTO.equals(scheme)) {
+ createExtras.putString(Intents.Insert.EMAIL, ssp);
+ mQueryHandler.startQuery(QUERY_TOKEN, null,
+ ContactMethods.CONTENT_URI, CONTACT_METHODS_PROJECTION,
+ QUERY_KIND_EMAIL_OR_IM + " AND " + ContactMethods.DATA + "=?",
+ new String[] { ssp }, null);
+
+ } else if (SCHEME_TEL.equals(scheme)) {
+ createExtras.putString(Intents.Insert.PHONE, ssp);
+ mQueryHandler.startQuery(QUERY_TOKEN, null,
+ Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, ssp),
+ PHONES_PROJECTION, null, null, null);
+
+ } else {
+ Log.w(TAG, "Invalid intent:" + getIntent());
+ finish();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mQueryHandler != null) {
+ mQueryHandler.cancelOperation(QUERY_TOKEN);
+ }
+ }
+
+ /**
+ * Listener for {@link DialogInterface} that launches a given {@link Intent}
+ * when clicked. When clicked, this also closes the parent using
+ * {@link Activity#finish()}.
+ */
+ private static class IntentClickListener implements DialogInterface.OnClickListener {
+ private Activity mParent;
+ private Intent mIntent;
+
+ /**
+ * @param parent {@link Activity} to use for launching target.
+ * @param intent Target {@link Intent} to launch when clicked.
+ */
+ public IntentClickListener(Activity parent, Intent intent) {
+ mParent = parent;
+ mIntent = intent;
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (mIntent != null) {
+ mParent.startActivity(mIntent);
+ }
+ mParent.finish();
+ }
+ }
+
+ /**
+ * Handle asynchronous query to find matching contacts. When query finishes,
+ * will handle based on number of matching contacts found.
+ */
+ private static final class QueryHandler extends AsyncQueryHandler {
+ private final WeakReference<Activity> mActivity;
+ private Bundle mCreateExtras;
+ private String mCreateDescrip;
+ private boolean mCreateForce;
+
+ public QueryHandler(Activity activity) {
+ super(activity.getContentResolver());
+ mActivity = new WeakReference<Activity>(activity);
+ }
+
+ public void setCreateExtras(Bundle createExtras) {
+ mCreateExtras = createExtras;
+ }
+
+ public void setCreateDescription(String createDescrip) {
+ mCreateDescrip = createDescrip;
+ }
+
+ public void setCreateForce(boolean createForce) {
+ mCreateForce = createForce;
+ }
+
+ @Override
+ protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ Activity activity = mActivity.get();
+ if (activity == null) {
+ return;
+ }
+
+ // Count contacts found by query
+ int count = 0;
+ long personId = -1;
+ if (cursor != null) {
+ try {
+ count = cursor.getCount();
+ if (count == 1 && cursor.moveToFirst()) {
+ // Try reading ID if only one contact returned
+ personId = cursor.getLong(PERSON_ID_INDEX);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ if (LOGD) Log.d(TAG, "onQueryComplete count=" + count);
+
+ if (count == 1) {
+ // If we only found one item, jump right to viewing it
+ Intent viewIntent = new Intent(Intent.ACTION_VIEW,
+ ContentUris.withAppendedId(People.CONTENT_URI, personId));
+ activity.startActivity(viewIntent);
+ activity.finish();
+
+ } else if (count > 1) {
+ // If more than one, show pick list
+ Intent listIntent = new Intent(Intent.ACTION_SEARCH);
+ listIntent.setComponent(new ComponentName(activity, ContactsListActivity.class));
+ listIntent.putExtras(mCreateExtras);
+ activity.startActivity(listIntent);
+ activity.finish();
+
+ } else {
+ // No matching contacts found
+ if (mCreateForce) {
+ // Forced to create new contact
+ Intent createIntent = new Intent(Intent.ACTION_INSERT, People.CONTENT_URI);
+ createIntent.putExtras(mCreateExtras);
+ createIntent.setType(People.CONTENT_TYPE);
+
+ activity.startActivity(createIntent);
+ activity.finish();
+
+ } else {
+ // Prompt user to insert or edit contact
+ Intent createIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ createIntent.putExtras(mCreateExtras);
+ createIntent.setType(People.CONTENT_ITEM_TYPE);
+
+ CharSequence message = activity.getResources().getString(
+ R.string.add_contact_dlg_message_fmt, mCreateDescrip);
+
+ new AlertDialog.Builder(activity)
+ .setTitle(R.string.add_contact_dlg_title)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok,
+ new IntentClickListener(activity, createIntent))
+ .setNegativeButton(android.R.string.cancel,
+ new IntentClickListener(activity, null))
+ .show();
+ }
+ }
+ }
+ }
+}