Fixed up intent MIME-types, add Accounts menu, clean unused.
Cleaned up <intent-filter> entries for INSERT_OR_EDIT and
EDIT to watch for more MIME-types after legacy change-over.
Finished clean-up from display groups by removing deprecated
edit sync groups UI, and unused menu. Changed
ContactsListActivity to use XML-based menus and added an
"Accounts" link that replaces the edit sync groups.
Finally, hooked up the INSERT case to read extras from any
incoming intents to help with SHOW_OR_CREATE intent testing.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f77a7bb..24becae 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -201,8 +201,9 @@
<intent-filter>
<action android:name="android.intent.action.INSERT_OR_EDIT" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.item/contact" />
<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>
@@ -311,6 +312,7 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/person" android:host="contacts" />
<data android:mimeType="vnd.android.cursor.item/contact" android:host="com.android.contacts" />
+ <data android:mimeType="vnd.android.cursor.item/raw_contact" android:host="com.android.contacts" />
</intent-filter>
</activity>
@@ -324,13 +326,16 @@
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/person" android:host="contacts" />
+ <data android:mimeType="vnd.android.cursor.item/contact" android:host="com.android.contacts" />
<data android:mimeType="vnd.android.cursor.item/raw_contact" android:host="com.android.contacts" />
</intent-filter>
+
<intent-filter android:label="@string/insertContactDescription">
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.dir/person" android:host="contacts" />
- <data android:mimeType="vnd.android.cursor.dir/contact" android:host="com.android.contacts" />
+ <data android:mimeType="vnd.android.cursor.dir/person" />
+ <data android:mimeType="vnd.android.cursor.dir/contact" />
+ <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
</intent-filter>
</activity>
@@ -362,11 +367,6 @@
/>
</activity>
- <!-- Activity used to select the groups that should be synced -->
- <activity android:name="ContactsGroupSyncSelector"
- android:label="@string/seclectSyncGroups_title"
- />
-
<!-- Makes .ContactsListActivity the search target for any activity in Contacts -->
<meta-data android:name="android.app.default_searchable"
android:value=".ContactsListActivity" />
diff --git a/res/menu/display_groups.xml b/res/menu/display_groups.xml
deleted file mode 100644
index 3d1a6b0..0000000
--- a/res/menu/display_groups.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_add"
- android:icon="@android:drawable/ic_menu_add"
- android:title="@string/menu_sync_add" />
-
-</menu>
diff --git a/res/menu/list.xml b/res/menu/list.xml
new file mode 100644
index 0000000..12cd28a
--- /dev/null
+++ b/res/menu/list.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/menu_search"
+ android:icon="@android:drawable/ic_menu_search"
+ android:title="@string/menu_search" />
+
+ <item
+ android:id="@+id/menu_add"
+ android:icon="@android:drawable/ic_menu_add"
+ android:title="@string/menu_newContact"
+ android:alphabeticShortcut="n" />
+
+ <item
+ android:id="@+id/menu_display_groups"
+ android:icon="@*android:drawable/ic_menu_allfriends"
+ android:title="@string/menu_displayGroup" />
+
+ <item
+ android:id="@+id/menu_accounts"
+ android:title="@string/menu_accounts" />
+
+ <item
+ android:id="@+id/menu_import"
+ android:icon="@drawable/ic_menu_import_contact"
+ android:title="@string/importFromSim" />
+
+ <item
+ android:id="@+id/menu_export"
+ android:icon="@drawable/ic_menu_export_contact"
+ android:title="@string/export_contact_list" />
+
+</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2278761..050abf9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -816,6 +816,9 @@
<!-- Shown as the social status snippet for a person when no social updates exist. -->
<string name="fasttrack_missing_status">No recent updates</string>
+ <!-- The menu item to open the list of accounts -->
+ <string name="menu_accounts">Accounts</string>
+
<!-- TODO: add comments to each of these strings to prepare for translation -->
<string name="nameLabelsGroup">Name</string>
<string name="nicknameLabelsGroup">Nickname</string>
diff --git a/src/com/android/contacts/ContactsGroupSyncSelector.java b/src/com/android/contacts/ContactsGroupSyncSelector.java
deleted file mode 100644
index 0384516..0000000
--- a/src/com/android/contacts/ContactsGroupSyncSelector.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2008 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.accounts.AccountManager;
-import android.accounts.AuthenticatorException;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AccountManagerCallback;
-import android.accounts.OperationCanceledException;
-import android.app.ListActivity;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.provider.Contacts;
-import android.provider.Gmail;
-import android.provider.Contacts.Groups;
-import android.provider.Contacts.Settings;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.io.IOException;
-
-import com.google.android.googlelogin.GoogleLoginServiceConstants;
-
-@Deprecated
-public final class ContactsGroupSyncSelector extends ListActivity implements View.OnClickListener {
-
- private static final String[] PROJECTION = new String[] {
- Groups._ID, // 0
- Groups.NAME, // 1
- Groups.SHOULD_SYNC, // 2
- Groups.SYSTEM_ID, // 3
- };
- private static final int COLUMN_INDEX_ID = 0;
- private static final int COLUMN_INDEX_NAME = 1;
- private static final int COLUMN_INDEX_SHOULD_SYNC = 2;
- private static final int COLUMN_INDEX_SYSTEM_ID = 3;
-
- ArrayList<Boolean> mChecked;
- ArrayList<Long> mGroupIds;
- boolean mSyncAllGroups;
-
- private final class GroupsAdapter extends ArrayAdapter<CharSequence> {
- public GroupsAdapter(ArrayList<CharSequence> items) {
- super(ContactsGroupSyncSelector.this,
- android.R.layout.simple_list_item_checked,
- android.R.id.text1, items);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return mSyncAllGroups;
- }
-
- @Override
- public boolean isEnabled(int pos) {
- if (mSyncAllGroups && pos != 0) {
- return false;
- } else {
- return true;
- }
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View v = super.getView(position, convertView, parent);
- if (mSyncAllGroups && position != 0) {
- v.setEnabled(false);
- } else {
- v.setEnabled(true);
- }
- return v;
- }
- }
-
- /**
- * Handles clicks on the list items
- */
- @Override
- protected void onListItemClick(ListView list, View view, int position, long id) {
- boolean isChecked = list.isItemChecked(position);
- mChecked.set(position, isChecked);
- if (position == 0) {
- mSyncAllGroups = isChecked;
- adjustChecks();
- }
- }
-
- /**
- * Handles clicks on the OK and cancel buttons
- */
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.cancel: {
- finish();
- break;
- }
-
- case R.id.ok: {
- // The list isn't setup yet, so just return without doing anything.
- if (mChecked == null) {
- finish();
- return;
- }
-
- final ContentResolver resolver = getContentResolver();
- if (mSyncAllGroups) {
- // For now we only support a single account and the UI doesn't know what
- // the account name is, so we're using a global setting for SYNC_EVERYTHING.
- // Some day when we add multiple accounts to the UI this should use the per
- // account setting.
- Settings.setSetting(resolver, null, Settings.SYNC_EVERYTHING, "1");
- } else {
- ContentValues values = new ContentValues();
- int count = mChecked.size();
- for (int i = 1; i < count; i++) {
- values.clear();
- values.put(Groups.SHOULD_SYNC, mChecked.get(i));
- resolver.update(
- ContentUris.withAppendedId(Groups.CONTENT_URI, mGroupIds.get(i)),
- values, null, null);
- }
- // For now we only support a single account and the UI doesn't know what
- // the account name is, so we're using a global setting for SYNC_EVERYTHING.
- // Some day when we add multiple accounts to the UI this should use the per
- // account setting.
- Settings.setSetting(resolver, null, Settings.SYNC_EVERYTHING, "0");
- }
- finish();
- break;
- }
- }
- }
-
- @Override
- protected void onCreate(Bundle savedState) {
- super.onCreate(savedState);
-
- // Only look for an account on first run.
- if (savedState == null) {
- // This will request a Gmail account and if none are present, it will
- // invoke SetupWizard to login or create one. The result is returned
- // through onActivityResult().
- Bundle bundle = new Bundle();
- bundle.putCharSequence("optional_message", getText(R.string.contactsSyncPlug));
- AccountManager.get(this).getAuthTokenByFeatures(
- GoogleLoginServiceConstants.ACCOUNT_TYPE, Gmail.GMAIL_AUTH_SERVICE,
- new String[]{GoogleLoginServiceConstants.FEATURE_HOSTED_OR_GOOGLE}, this,
- bundle, null /* loginOptions */, new AccountManagerCallback<Bundle>() {
- public void run(AccountManagerFuture<Bundle> future) {
- try {
- // do this to check if this request succeeded or not
- future.getResult();
- // There is an account setup, build the group list
- buildItems();
- adjustChecks();
- } catch (OperationCanceledException e) {
- finish();
- } catch (IOException e) {
- finish();
- } catch (AuthenticatorException e) {
- finish();
- }
- }
- }, null /* handler */);
- }
-
- setContentView(R.layout.sync_settings);
-
- findViewById(R.id.ok).setOnClickListener(this);
- findViewById(R.id.cancel).setOnClickListener(this);
-
- getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- }
-
- private void buildItems() {
- final ContentResolver resolver = getContentResolver();
- Cursor cursor = resolver.query(Groups.CONTENT_URI, PROJECTION, null, null, Groups.NAME);
- if (cursor != null) {
- try {
- int count = cursor.getCount() + 1; // add 1 for "sync all"
- ArrayList<CharSequence> items = new ArrayList<CharSequence>(count);
- ArrayList<Boolean> checked = new ArrayList<Boolean>(count);
- ArrayList<Long> groupIds = new ArrayList<Long>(count);
-
- // The first item in the list is always "sync all"
- items.add(getString(R.string.syncAllGroups));
- checked.add(mSyncAllGroups);
- groupIds.add(Long.valueOf(0)); // dummy entry
-
- while (cursor.moveToNext()) {
- String name = cursor.getString(COLUMN_INDEX_NAME);
- String systemId = cursor.isNull(COLUMN_INDEX_SYSTEM_ID) ?
- null : cursor.getString(COLUMN_INDEX_SYSTEM_ID);
- if (systemId == null || !Groups.GROUP_MY_CONTACTS.equals(systemId)) {
- // Localize the "Starred in Android" string which we get from the server
- // side.
- if (Groups.GROUP_ANDROID_STARRED.equals(name)) {
- name = getString(R.string.starredInAndroid);
- }
- items.add(name);
- checked.add(cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
- groupIds.add(cursor.getLong(COLUMN_INDEX_ID));
- } else {
- // If My Contacts is around it wants to be the second list entry
- items.add(1, getString(R.string.groupNameMyContacts));
- checked.add(1, cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
- groupIds.add(1, cursor.getLong(COLUMN_INDEX_ID));
- }
- }
- mChecked = checked;
- mGroupIds = groupIds;
- mSyncAllGroups = getShouldSyncEverything(resolver);
-
- // Setup the adapter
- setListAdapter(new GroupsAdapter(items));
- } finally {
- cursor.close();
- }
- }
- }
-
- private void adjustChecks() {
- final ListView list = getListView();
- if (mSyncAllGroups) {
- int count = list.getCount();
- for (int i = 0; i < count; i++) {
- list.setItemChecked(i, true);
- }
- } else {
- ArrayList<Boolean> checked = mChecked;
- int count = list.getCount();
- for (int i = 0; i < count; i++) {
- list.setItemChecked(i, checked.get(i));
- }
- }
- }
-
- private static boolean getShouldSyncEverything(ContentResolver cr) {
- // For now we only support a single account and the UI doesn't know what
- // the account name is, so we're using a global setting for SYNC_EVERYTHING.
- // Some day when we add multiple accounts to the UI this should use the per
- // account setting.
- String value = Contacts.Settings.getSetting(cr, null, Contacts.Settings.SYNC_EVERYTHING);
- if (value == null) {
- // If nothing is set yet we default to syncing everything
- return true;
- }
- return !TextUtils.isEmpty(value) && !"0".equals(value);
- }
-}
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 8718b10..936396d 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -50,6 +50,7 @@
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
+import android.provider.Settings;
import android.provider.Contacts.ContactMethods;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
@@ -71,6 +72,7 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -118,13 +120,6 @@
static final int MENU_ITEM_DELETE = 7;
static final int MENU_ITEM_TOGGLE_STAR = 8;
- public static final int MENU_SEARCH = 1;
- public static final int MENU_DIALER = 9;
- public static final int MENU_NEW_CONTACT = 10;
- public static final int MENU_DISPLAY_GROUP = 11;
- public static final int MENU_IMPORT_CONTACTS = 12;
- public static final int MENU_EXPORT_CONTACTS = 13;
-
private static final int SUBACTIVITY_NEW_CONTACT = 1;
private static final int SUBACTIVITY_VIEW_CONTACT = 2;
private static final int SUBACTIVITY_DISPLAY_GROUP = 3;
@@ -147,6 +142,8 @@
public static final String EXTRA_AGGREGATE_ID =
"com.android.contacts.action.AGGREGATE_ID";
+ public static final String AUTHORITIES_FILTER_KEY = "authorities";
+
/** Mask for picker mode */
static final int MODE_MASK_PICKER = 0x80000000;
/** Mask for no presence mode */
@@ -281,7 +278,7 @@
private String mShortcutAction;
private boolean mDefaultMode = false;
-
+
private boolean mCreateShortcut;
/**
@@ -298,7 +295,7 @@
* provided by scheme-specific part of incoming {@link Intent#getData()}.
*/
private String mQueryData;
-
+
private Handler mHandler = new Handler();
private class ImportTypeSelectedListener implements DialogInterface.OnClickListener {
@@ -502,7 +499,7 @@
list.setOnCreateContextMenuListener(this);
if ((mMode & MODE_MASK_NO_FILTER) != MODE_MASK_NO_FILTER) {
list.setTextFilterEnabled(true);
- }
+ }
if ((mMode & MODE_MASK_CREATE_NEW) != 0) {
// Add the header for creating a new contact
@@ -697,63 +694,48 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
// If Contacts was invoked by another Activity simply as a way of
// picking a contact, don't show the options menu
if ((mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER) {
return false;
}
- // TODO: move this into a resource-based menu
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.list, menu);
+ return true;
+ }
- // Search
- menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
- .setIcon(android.R.drawable.ic_menu_search);
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ final boolean defaultMode = (mMode == MODE_DEFAULT);
+ menu.findItem(R.id.menu_display_groups).setVisible(defaultMode);
- // New contact
- menu.add(0, MENU_NEW_CONTACT, 0, R.string.menu_newContact).setIcon(
- android.R.drawable.ic_menu_add).setIntent(
- new Intent(Intents.Insert.ACTION, Contacts.CONTENT_URI)).setAlphabeticShortcut('n');
+ final boolean allowExport = getResources().getBoolean(R.bool.config_allow_export_to_sdcard);
+ menu.findItem(R.id.menu_export).setVisible(allowExport);
- // Display group
- if (mMode == MODE_DEFAULT) {
- menu.add(0, MENU_DISPLAY_GROUP, 0, R.string.menu_displayGroup)
- .setIcon(com.android.internal.R.drawable.ic_menu_allfriends);
- }
-
- // Sync settings
- if (mSyncEnabled) {
- Intent syncIntent = new Intent(Intent.ACTION_VIEW);
- syncIntent.setClass(this, ContactsGroupSyncSelector.class);
- menu.add(0, 0, 0, R.string.syncGroupPreference)
- .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
- .setIntent(syncIntent);
- }
-
- // Contacts import (SIM/SDCard)
- menu.add(0, MENU_IMPORT_CONTACTS, 0, R.string.importFromSim)
- .setIcon(R.drawable.ic_menu_import_contact);
-
- if (getResources().getBoolean(R.bool.config_allow_export_to_sdcard)) {
- menu.add(0, MENU_EXPORT_CONTACTS, 0, R.string.export_contact_list)
- .setIcon(R.drawable.ic_menu_export_contact);
- }
-
- return super.onCreateOptionsMenu(menu);
+ return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case MENU_DISPLAY_GROUP:
+ case R.id.menu_display_groups: {
final Intent intent = new Intent(this, DisplayGroupsActivity.class);
startActivityForResult(intent, SUBACTIVITY_DISPLAY_GROUP);
return true;
-
- case MENU_SEARCH:
+ }
+ case R.id.menu_search: {
startSearch(null, false, null, false);
return true;
-
- case MENU_IMPORT_CONTACTS:
+ }
+ case R.id.menu_add: {
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ startActivity(intent);
+ return true;
+ }
+ case R.id.menu_import: {
if (getResources().getBoolean(R.bool.config_allow_import_from_sdcard)) {
ImportTypeSelectedListener listener =
new ImportTypeSelectedListener();
@@ -770,9 +752,19 @@
doImportFromSim();
}
return true;
-
- case MENU_EXPORT_CONTACTS:
+ }
+ case R.id.menu_export: {
handleExportContacts();
+ return true;
+ }
+ case R.id.menu_accounts: {
+ final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+ intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
+ ContactsContract.AUTHORITY
+ });
+ startActivity(intent);
+ return true;
+ }
}
return false;
}
@@ -793,7 +785,7 @@
VCardExporter exporter = new VCardExporter(ContactsListActivity.this, mHandler);
exporter.startExportVCardToSdCard();
}
-
+
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
@@ -1050,7 +1042,7 @@
private void returnPickerResult(Cursor c, String name, Uri uri, long id) {
final Intent intent = new Intent();
-
+
if (mShortcutAction != null) {
Intent shortcutIntent;
if (Intent.ACTION_VIEW.equals(mShortcutAction)) {
@@ -1080,7 +1072,7 @@
// Make the URI a direct tel: URI so that it will always continue to work
Uri phoneUri = Uri.fromParts(scheme, number, null);
shortcutIntent = new Intent(mShortcutAction, phoneUri);
-
+
// Find the People._ID for this phone number
/* TODO bring back the better icon handling
final long personId = c.getLong(PHONES_PERSON_ID_INDEX);
@@ -1207,7 +1199,7 @@
return null;
}
}
-
+
String[] getProjection() {
switch (mMode) {
case MODE_PICK_PHONE:
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/EntityDelta.java
index 116300f..427cf33 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/EntityDelta.java
@@ -437,7 +437,8 @@
}
public boolean isPrimary() {
- return (getAsLong(Data.IS_PRIMARY) != 0);
+ final Long isPrimary = getAsLong(Data.IS_PRIMARY);
+ return isPrimary == null ? false : isPrimary != 0;
}
public boolean beforeExists() {
diff --git a/src/com/android/contacts/model/EntityModifier.java b/src/com/android/contacts/model/EntityModifier.java
index 29f4d1c..9da140e 100644
--- a/src/com/android/contacts/model/EntityModifier.java
+++ b/src/com/android/contacts/model/EntityModifier.java
@@ -298,6 +298,11 @@
* assuming the extras defined through {@link Intents}.
*/
public static void parseExtras(Context context, ContactsSource source, EntityDelta state, Bundle extras) {
+ if (extras == null || extras.size() == 0) {
+ // Bail early if no useful data
+ return;
+ }
+
{
// StructuredName
final DataKind kind = source.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
@@ -332,7 +337,7 @@
{
// Email
final DataKind kind = source.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
- parseExtras(state, kind, extras, Insert.EMAIL_TYPE, Insert.PHONE, Email.DATA);
+ parseExtras(state, kind, extras, Insert.EMAIL_TYPE, Insert.EMAIL, Email.DATA);
parseExtras(state, kind, extras, Insert.SECONDARY_EMAIL_TYPE, Insert.SECONDARY_EMAIL,
Email.DATA);
parseExtras(state, kind, extras, Insert.TERTIARY_EMAIL_TYPE, Insert.TERTIARY_EMAIL,
@@ -363,7 +368,7 @@
// Bail when can't insert type, or value missing
final boolean canInsert = EntityModifier.canInsert(state, kind);
- final boolean validValue = TextUtils.isGraphic(value);
+ final boolean validValue = (value != null && TextUtils.isGraphic(value));
if (!validValue || !canInsert) return;
// Find exact type, or otherwise best type
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index 4fa6f01..03ef79a 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -23,6 +23,7 @@
import com.android.contacts.ViewContactActivity;
import com.android.contacts.model.ContactsSource;
import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
import com.android.contacts.model.HardCodedSources;
import com.android.contacts.model.Sources;
import com.android.contacts.model.EntityDelta.ValuesDelta;
@@ -690,10 +691,10 @@
dialog.dismiss();
// Create new contact based on selected source
- final Account source = accountAdapter.getItem(which);
+ final Account account = accountAdapter.getItem(which);
final ContentValues values = new ContentValues();
- values.put(RawContacts.ACCOUNT_NAME, source.name);
- values.put(RawContacts.ACCOUNT_TYPE, source.type);
+ values.put(RawContacts.ACCOUNT_NAME, account.name);
+ values.put(RawContacts.ACCOUNT_TYPE, account.type);
// Tie this directly to existing aggregate
// TODO: this may need to use aggregation exception rules
@@ -702,7 +703,13 @@
values.put(RawContacts.CONTACT_ID, aggregateId);
}
+ // Parse any values from incoming intent
final EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
+ final ContactsSource source = sources.getInflatedSource(account.type,
+ ContactsSource.LEVEL_CONSTRAINTS);
+ final Bundle extras = target.getIntent().getExtras();
+ EntityModifier.parseExtras(target, source, insert, extras);
+
target.mState.add(insert);
target.bindTabs();