Android: actualiza un contacto

Intento actualizar un contacto de mi directorio telefónico directamente desde mi aplicación. ¡Puedo agregar y eliminar los contactos, pero la actualización simplemente no hace nada!

Después del inserto o cuando agarro los contactos, recojo el CONTACT_ID (Aka _ID).

Aquí está mi código para la actualización:

public void update(Relation r) { Log.e("", ""+r.getBook_id()); ArrayList ops = new ArrayList(); Builder builder = ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI); builder.withValue(RawContacts.ACCOUNT_TYPE, null); builder.withValue(RawContacts.ACCOUNT_NAME, null); ops.add(builder.build()); // Name builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, r.getFirstName()+ " " +r.getLastName()); ops.add(builder.build()); // Number builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, r.getNumber()); builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK); ops.add(builder.build()); // Picture try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(r.getPhoto())); ByteArrayOutputStream image = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG , 100, image); builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, image.toByteArray()); ops.add(builder.build()); } catch (Exception e) { e.printStackTrace(); } // Update try { context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { e.printStackTrace(); } } 

r.getBook_id() me da el valor _ID del contacto actual. r.getFirstName() y r.getLastName() me dan el nombre del contacto. r.getPhoto() me da su foto uri. Y finalmente r.getNumber() me da su número de teléfono.

La línea de registro me da un valor correcto de _ID, no creo que el problema provenga de aquí. ¿Hice algo mal?

Gracias.

Saludos.

V.


Código fuente completo:

 /** * Uses the Contacts API to load contacts from the phonebook. * */ public class ContactUtils { static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.STARRED, ContactsContract.Contacts.TIMES_CONTACTED, ContactsContract.Contacts.CONTACT_PRESENCE, ContactsContract.Contacts.PHOTO_ID, ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.Contacts.HAS_PHONE_NUMBER, }; private Activity context; static final int CARD_LIMIT = 50; /** * Constructor * * @version 1.0 * @since 2012-03-28 * @param context Context of the running activity */ public ContactUtils(Activity context) { super(); this.context = context; } /** * Returns a list of all the contacts in the phonebook * * @version 1.0 * @since 2012-03-28 * @return Returns a list of all the contacts in the phonebook */ public ArrayList loadContacts() { String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " == 1))"; Cursor c = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, CONTACTS_SUMMARY_PROJECTION, select, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); context.startManagingCursor(c); ArrayList cList = new ArrayList(); int a = 0; Relation relation; while (c.moveToNext() && a 1) relation.setLastName(name_splitted[1]); ArrayList numbers = getPhoneNumbers(c.getString(0)); relation.setNumber(numbers.size() > 0 ? numbers.get(0) : "" ); relation.setConcept("Any"); relation.setPhoto(loadContactPhoto(c) == null ? "android.resource://com.orange.rd.kramer/drawable/default_photo" : loadContactPhoto(c)); cList.add(relation); a++; } c.close(); return cList; } /** * Returns an uri pointing to the contact's photo * * @version 1.0 * @since 2012-03-28 * @param cursor Cursor on a specific contact * @return Returns an uri pointing to the contact's photo */ private String loadContactPhoto(Cursor cursor) { if (cursor.getString(5) != null) { Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, cursor.getInt(0)); return Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY).toString(); } return null; } /** * Returns a list of all phone numbers that belong to the given contact * * @version 1.0 * @since 2012-03-28 * @param id Id of the given contact * @return Returns a list of all phone numbers that belong to the given contact */ private ArrayList getPhoneNumbers(String id) { ArrayList phones = new ArrayList(); Cursor pCur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id}, null); while (pCur.moveToNext()) { phones.add(pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); } pCur.close(); return(phones); } /** * Inserts the given relation into the stock phone book * * @version 1.0 * @since 2012-03-28 * @param r Relation to be added into the stock phone book */ public void insert(Relation r) { ArrayList ops = new ArrayList(); int rawContactInsertIndex = ops.size(); Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI); builder.withValue(RawContacts.ACCOUNT_TYPE, null); builder.withValue(RawContacts.ACCOUNT_NAME, null); ops.add(builder.build()); // Name builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, r.getFirstName().replace(" ", "-")+ " " +r.getLastName().replace(" ", "-")); ops.add(builder.build()); // Number builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, r.getNumber()); builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK); ops.add(builder.build()); // Picture try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(r.getPhoto())); ByteArrayOutputStream image = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG , 100, image); builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex); builder.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, image.toByteArray()); ops.add(builder.build()); } catch (Exception e) { e.printStackTrace(); } // Add the new contact try { context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { e.printStackTrace(); } String select = "(" + ContactsContract.Contacts.DISPLAY_NAME + " == \"" +r.getFirstName().replace(" ", "-")+ " " +r.getLastName().replace(" ", "-")+ "\" )"; Cursor c = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, CONTACTS_SUMMARY_PROJECTION, select, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); context.startManagingCursor(c); if (c.moveToNext()) { r.setBook_id(new Integer(c.getString(0)).intValue()); } else { r.setBook_id(-1); } } /** * Updates the given relation in the stock phone book * * @version 1.0 * @since 2012-03-28 * @param r Relation to be updated in the stock phone book */ public void update(Relation r) { Log.e("", ""+r.getBook_id()); ArrayList ops = new ArrayList(); Builder builder = ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI); builder.withValue(RawContacts.ACCOUNT_TYPE, null); builder.withValue(RawContacts.ACCOUNT_NAME, null); ops.add(builder.build()); // Name builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, r.getFirstName().replace(" ", "-")+ " " +r.getLastName().replace(" ", "-")); ops.add(builder.build()); // Number builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, r.getNumber()); builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK); ops.add(builder.build()); // Picture try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(r.getPhoto())); ByteArrayOutputStream image = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG , 100, image); builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data._ID, new String[]{String.valueOf(r.getBook_id())}); builder.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, image.toByteArray()); ops.add(builder.build()); } catch (Exception e) { e.printStackTrace(); } // Update try { context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { e.printStackTrace(); } } /** * Deletes the given relation from the stock phone book * * @version 1.0 * @since 2012-03-28 * @param r Relation to be removed from the stock phone book */ public void delete(Relation r) { Cursor pCur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{""+r.getBook_id()}, null); while (pCur.moveToNext()) { String lookupKey = pCur.getString(pCur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey); context.getContentResolver().delete(uri, null, null); } } } 

Finalmente, encontré cómo actualizar un contacto, aquí está el código del método de actualización:

  public void update() { int id = 1; String firstname = "Contact's first name"; String lastname = "Last name"; String number = "000 000 000"; String photo_uri = "android.resource://com.my.package/drawable/default_photo"; ArrayList ops = new ArrayList(); // Name Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{String.valueOf(id), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}); builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastname); builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstname); ops.add(builder.build()); // Number builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?"+ " AND " + ContactsContract.CommonDataKinds.Organization.TYPE + "=?", new String[]{String.valueOf(id), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_HOME)}); builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, number); ops.add(builder.build()); // Picture try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.parse(photo_uri)); ByteArrayOutputStream image = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG , 100, image); builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); builder.withSelection(ContactsContract.Data.CONTACT_ID + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{String.valueOf(id), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE}); builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, image.toByteArray()); ops.add(builder.build()); } catch (Exception e) { e.printStackTrace(); } // Update try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { e.printStackTrace(); } } 

La id campo es la identificación de contacto sin procesar que se devuelve cuando inserta un nuevo contacto en la base de datos. Aquí está el código para obtener esta identificación:

  ContentProviderResult[] res; try { res = KramerApplication.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); if (res != null && res[0] != null) { String uri = res[0].uri.getPath().substring(14); r.setBook_id( new Integer(uri).intValue() ); } } catch (Exception e) { e.printStackTrace(); } 

Verifique mi primera pregunta si quiere saber más sobre cómo insertar / eliminar un contacto.

No estoy seguro si esto lo ayuda, sin embargo, encontré un blog sobre la diferencia entre contact_id y raw_contact_id:

http://android-contact-id-vs-raw-contact-id.blogspot.de/

En este blog, explica bien cómo funciona la API de contactos y si la entiendo correctamente, debe usar el raw_contact_id para cambiar su entrada. Así que olvide el contact_id para actualizar y cambie su actualización para que la entrada raw_contact_id se modifique. Casi diría que se vería algo como esto:

 ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI) .withSelection(RawContacts._ID + "=?", new String[]{entertheraw_contact_id}) .withValue(StructuredName.DISPLAY_NAME, "Lost Symbol Characters") .build()); getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 

Espero que esto te ayude un poco y gracias de nuevo por tu formulario de ayuda.

Para actualizar el contacto necesita tener ID de contacto y de contacto sin procesar … así que, al actualizar, agregue esto también como un valor en donde argumenta la cláusula / selección .

algo como esto..

 ArrayList ops = new ArrayList(); //------------------------------------------------------ Names ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX, data.getTitle()) .withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, data.getSuffix()) .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, data.getFirstName()) .withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, data.getMiddleName()) .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, data.getSuffix()) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, data.getFirstName()+" "+data.getMiddleName()).build());