Updating Contact causing wrong values to be written - android

I am trying to display the name, phone number and email of a contact and letting the user update any of the values. For some reason, the value of email is overwritten on all three fields when my code is executed. There's got to be a glitch in the logic here, but I cannot figure it out.
Here's my method which updates the Contacts URI.
private void updateContact() {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, name)
.build());
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.build());
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.build());
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
// Display update
Context ctx = getApplicationContext();
CharSequence txt = "Contact Updated";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(ctx, txt, duration);
toast.show();
} catch (Exception e) {
// Display warning
Context ctx = getApplicationContext();
CharSequence txt = "Update Failed";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(ctx, txt, duration);
toast.show();
}
}

see this link:
http://comments.gmane.org/gmane.comp.handhelds.android.devel/92848
" you shouldn't specify the mime type in an update statement - it is not updatable."
"Your query says: "update all data rows for this contact, setting one of the fields to "John" and another to "Abraham". Data rows include phone numbers, emails, photos, you-name-it. What you need to do is find a specific data row you want to update and then use its _id in the selection (or, more commonly, in the URI itself)."
"The data structure for contacts is based on three separate tables: Contacts, RawContacts and Data. A Contact can have multiple RawContacts, which can have multiple Data rows. Each data row has a mime type that specifies what kind of data is stored in that row. Contact name is stored in a row with the mime type StructuredName.CONTENT_TYPE.
So, in order to change the contact name you first need to find the Data row that contains the name and then update that Data row. The provider will take care of the rest (e.g. promoting the name to the level of RawContact and then Contact)."

Also see
http://www.eoeandroid.com/sdk/api/reference/android/provider/ContactsContract.Data.html
must get the dataId first :
ArrayList ops = Lists.newArrayList();
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
.withValue(Email.DATA, "somebody#android.com")
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

Related

After adding contacts from code, phoneBook appends the space after period(.) in android

I don't know what I am doing wrong while inserting contact into phonebook.
here is the code to insert.
public static void AddMultipleContact(Context context, String name , String numbers, String Data4){
ContentResolver resolver = context.getContentResolver();
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.RawContacts.CONTENT_URI, true))
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.withValue(ContactsContract.RawContacts.SOURCE_ID, sourceId)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers) // Number of the person
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build()); // Type of mobile number
android.util.Log.e(TAG, "AddMultipleContact:-------------- NAME = " + name);
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.RawContacts.Data.MIMETYPE,MIMETYPE)
.withValue(Data.DATA1, sourceId)
.withValue(Data.DATA3, Data4)
.build());
try {
ContentProviderResult[] results = resolver.applyBatch(ContactsContract.AUTHORITY, ops);
}
catch (Exception e) {
e.printStackTrace();
}
}
As you can see i am also printing log for name.
android.util.Log.e(TAG, "AddMultipleContact:-------------- NAME = " + name);
Here i am sending contactName and contactNumber to this method.
the name what I am passing is suppose ex: "A.Bcdef"
but the name what I am seeing in the phonebook is "A. Bcdef"
It is adding extra space after period(.).
Please help me. I am not getting any solution on google, or not able to search exactly what I want to search.
Thanks in advance.
I SOLVED THIS BY Changing this line
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
to
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name)
GIVEN_NAME is taking the same name what we passed as value
There are other parameters like
DISPLAY_NAME, GIVEN_NAME, FAMILY_NAME, PREFIX, MIDDLE_NAME, SUFFIX, PHONETIC_GIVEN_NAME, PHONETIC_MIDDLE_NAME, PHONETIC_FAMILY_NAME, FULL_NAME_STYLE, PHONETIC_NAME_STYLE
I really don't know what actually these all means.
But when i added name as 'Testing,123' while creating a contact, then the name appears to be like '123 Testing'.
So I thought it is automatically thinking like what is 'middleName' and 'lastName' based on SpecialCharacters.

Save data for contacts adds a new one

I developing an app in which I need to store data related to a contact.
I list the contacts in a recycleView using a cursor and each itemView has a star button to set the contact as favorite (not the same as the system).
I managed to store the data in ContactsContract.Data, doing this:
private void addContactData(long contactId, String displayName, boolean favorite) {
// displayName same as the value for Contacts.DISPLAY_NAME_PRIMARY
ArrayList<ContentProviderOperation> ops =
new ArrayList<>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, CUSTOM_ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, CUSTOM_ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.CONTACT_ID, contactId)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, CustomData.CONTENT_ITEM_TYPE)
.withValue(CustomData.IS_FAVORITE, favorite)
.build());
try {
ContentProviderResult[] contentProviderResults = cr.applyBatch(ContactsContract.AUTHORITY, ops);
return contactUri;
} catch (RemoteException | OperationApplicationException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
return null;
}
}
The problem I have is when two contacts have the exact same name ej. "Tom" and "Tom" if I press the fav button, is adding a third contact that is even listed in the device contacts app.
Some search guied me to add more data to distinguish the contacts using:
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.build());
// OR
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email)
.build());
And it worked just fine, except if the fields are equals in both contacts. What do I need to avoid this behavior, and Why the CONTACT_ID isn't enough to do this kind of operations?
You need to tell Android to merge the new RawContact you've just created with some (one or more) existing RawContacts.
You do that using the AggregationException table, adding a row for each such "link".
See: https://stackoverflow.com/a/40869351/819355
Code snippet:
Builder builder = ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, yourNewRawContact);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, someExistingRawContact);
ContentProviderOperation op = builder.build();

Add one contact with multiple numbers Android programmatically

How to add one contact with multiple numbers on android phone programmatically?
This is how we can do this
pass Name and Array of numbers to this method.
public static void addToContactList(Context context, String strDisplayName, String[] strNumber) throws Exception {
ArrayList<ContentProviderOperation> cntProOper = new ArrayList<>();
int contactIndex = cntProOper.size();//ContactSize
ContentResolver contactHelper = context.getContentResolver();
cntProOper.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)//Step1
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());
//Display name will be inserted in ContactsContract.Data table
cntProOper.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)//Step2
.withValueBackReference(android.provider.ContactsContract.Data.RAW_CONTACT_ID, contactIndex)
.withValue(android.provider.ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, strDisplayName) // Name of the contact
.build());
for (String s : strNumber) {
//Mobile number will be inserted in ContactsContract.Data table
cntProOper.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_URI)//Step 3
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactIndex)
.withValue(android.provider.ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, s) // Number to be added
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).build()); //Type like HOME, MOBILE etc
}
ContentProviderResult[] s = context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, cntProOper); //apply above data insertion into contacts list
for (ContentProviderResult r : s) {
Log.i(TAG, "addToContactList: " + r.uri);
}
}

How can I programmatically add a contact?

I am trying to programmatically add a contact in Android. Here is my code:
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,"Google")
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME,"user1#gmail.com") .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract
.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType)
.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Context ctx = getApplicationContext();
CharSequence txt = "Contact " + name +" added successfully";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(ctx, txt, duration);
toast.show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"error",Toast.LENGTH_LONG).show();
}
Am I doing this correctly? How can I add an account name and account type?
NOTE: I don't have any account created. Is it mandatory to have account in order to add a contact?
Contact API storing contact as an invisible contact: How to make it visible? check this i hope it will be useful!
there is no need of creating any account in the phone!... i think their is some default account to do that!

New contacts created using ContactsContract do not appear in Contacts app

I'm using the following piece of codes to create a new contact. It follow closely the ContactManager example provided by Android.
The problem is, the created contacts do not appear in the Contacts app that shipped with Android. Nevertheless, when I load all the contacts from the phonebook, I can see the newly created contacts.
private void insertPBEntry()
throws RemoteException, OperationApplicationException
{
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "Account type")
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, "Account name")
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "TOTAL_NEW")
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "9090")
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,Phone.TYPE_MOBILE)
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
}
I've searched hard but have yet to find the answer. I found one answer suggesting that the problem might have (sth) to do with my strings "Account type" and "Account name". For my case, I do not need to create any account whatsoever. All I want is to add a new contact with a name, email/mail address, phones.
Thanks, guys!
The sample codes provided by Google work. Just that when it's run on the emulator, no account or group can be found to attach the created contact to. And by default, this newly created contact is not visible.
Using the actual phone (for my case, HTC Dream), after detecting the account name and type to feed in the codes, it works. Alternatively, we can get the visible group ids available and attach the new contact to one of those groups.
To get the available accounts:
//accounts
Account[] accounts = AccountManager.get(act).getAccounts();
for (Account acc : accounts){
Log.d(TAG, "account name = " + acc.name + ", type = " + acc.type);
}
To get the list of groups:
//group membership info
String[] tempFields = new String[] {
GroupMembership.GROUP_ROW_ID, GroupMembership.GROUP_SOURCE_ID};
Cursor tempCur = act.managedQuery(Data.CONTENT_URI, tempFields,
Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "'",
null, null);
Now, if we want to associate the new contact to a group instead of an account:
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE)
.withValue(GroupMembership.GROUP_SOURCE_ID, *<THE_IDENTIFIED_GROUP_ID>*)
.build());
Hope it helps.
To add an account in emulator that has no groups or accounts, just put "null" as your account or group id, replace the line of code like this
ops.add(ContentProviderOperation
.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
Did you try to set the visibility of your group to true?
In Contacts Tab press the menu button, than "Display options" > your Account and than check the boxes and "Done".
HTC Sense and MOTOBLUR can be problematic with contacts. I don't know if any of the information here (http://stackoverflow.com/questions/4431101/created-contacts-not-showing-up-on-htc-evo) is useful.

Categories

Resources