mordicchio
mordicchio

Reputation: 145

Android: cannot update or delete Contact with ContentProviderOperation

I'm trying to create simple operations of Insert/update/Delete of Contact in Android using the ContentProviderOperation. I've successfully inserted a new contact, but after that I'm not able to update or delete it.

After inserting the contact, I retrieve its id in this way:

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).withValue(...).build());
ContentProviderResult[] results = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
int idContact = Integer.parseInt(results[0].uri.getLastPathSegment());

And the id is like 557, then I try to update (or delete) with:

String selection = Data.CONTACT_ID + "=?";
String[] selectionArgs = new String[] { String.valueOf(idContact) };

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

ops.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
    .withValue(RawContacts.ACCOUNT_TYPE, null)
    .withValue(RawContacts.ACCOUNT_NAME, null).build());

if (firstName != null && surname != null) {
    ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
        .withSelection(selection, selectionArgs)
        .withValueBackReference(Data.RAW_CONTACT_ID, 0)
        .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
        .withValue(StructuredName.GIVEN_NAME, firstName)
        .withValue(StructuredName.FAMILY_NAME, surname).build());
}

if (phoneNumber != null) {
    ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
        .withSelection(selection, selectionArgs)
        .withValueBackReference(Data.RAW_CONTACT_ID, 0)
        .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
        .withValue(Phone.NUMBER, phoneNumber)
        .withValue(Phone.TYPE, Phone.TYPE_MOBILE).build());
}         

context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);   

No error is given, but the contact has not been modified and even the delete works. Am i doing something wrong?

Upvotes: 0

Views: 2134

Answers (2)

mordicchio
mordicchio

Reputation: 145

I finally managed to solve the problem, the mistakes were more than one.

1)

int idContact = Integer.parseInt(results[0].uri.getLastPathSegment());

returns the RAW ID (i.e. the autoincrement id of the table) and not the CONTACT_ID, useful to make other queries on that contact. So, after inserting the contact, I had to retrieve the new contact_id in some other way, for example I've made a query based on the display name, but I think you can use telephone number as well.

ContentProviderResult[] results = context.getContentResolver()
                .applyBatch(ContactsContract.AUTHORITY, ops);
int raw_id = Integer.parseInt(results[0].uri.getLastPathSegment());
Log.d(TAG, "Raw id: " + raw_id);   // not so useful
// search for the contact_id
int contact_id;
String displayName = firstName + " " + surName;
String selection = ContactsContract.Contacts.DISPLAY_NAME + "=?";
String[] selectionArgs = new String[] { displayName };
Cursor cur = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, selection, selectionArgs, null);
if (cur != null) {      
    if(cur.moveToFirst())
        contact_id = cur.getInt(cur.getColumnIndex(ContactsContract.Contacts._ID)); 
    cur.close();    
}
Log.d(TAG, "Insert complete for id: " + contact_id);

2) In my update function there were a lot of mistakes. First of all, as Kai said, the first newUpdate statement (the solitary one) is useless. Second, in the following updates, the withValue calls were wrong. Third, most important, I had to add some selection, in fact the simple contact_id selection has to be completed with specific selections for every type (name, telephone, ecc...)

Here it is the correct method:

String baseSelection = Data.CONTACT_ID + "=?";
String[] baseSelectionArgs = new String[] { String.valueOf(idContact) };

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

if (firstName != null && surname != null) {
    String selection = baseSelection + " AND " + Data.MIMETYPE + "=?";
    String[] selectionArgs = new String[] { baseSelectionArgs[0],
        StructuredName.CONTENT_ITEM_TYPE };
    ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
        .withSelection(selection, selectionArgs)
        .withValue(StructuredName.GIVEN_NAME, firstName)
        .withValue(StructuredName.FAMILY_NAME, surname).build());
}

if (phoneNumber != null) {
    String selection = baseSelection + " AND " + Data.MIMETYPE
        + "=? AND " + String.valueOf(Phone.TYPE) + " = ? ";
    String[] selectionArgs = new String[] { baseSelectionArgs[0],
        Phone.CONTENT_ITEM_TYPE, String.valueOf(Phone.TYPE_MOBILE) };
    ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
        .withSelection(selection, selectionArgs)
        .withValue(Phone.NUMBER, phoneNumber).build());
}

Upvotes: 2

Kai
Kai

Reputation: 15476

The 2nd and 3rd update looks right, but the first update

ops.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
    .withValue(RawContacts.ACCOUNT_TYPE, null) 
    .withValue(RawContacts.ACCOUNT_NAME, null).build()); 

looks like an insert and not an update, remove this code and try again.

Upvotes: 0

Related Questions