2012-02-23 10 views
7

Vi this pregunta y respuesta, pero agregar la información del teléfono (e incluso el correo electrónico) aún no hace que la información de contacto se agregue correctamente (cuando consulto la aplicación Contactos, puedo ver varias entradas con el mismo nombre).¿Cómo se consigue que los contactos se agreguen correctamente cuando se los agrega programáticamente?

Aquí está el código que uso para probarlo.

//get the account 
Account acct = null; 
Account[] accounts = AccountManager.get(getContext()).getAccounts(); 
for (Account acc : accounts){ 
    acct = acc; 
}//assuming there's only one account in there (in my case I know there is) 

//loop a few times, creating a new contact each time. In theory, if they have the same name they should aggregate 
for(int i=0; i<3; i++){ 
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); 
    ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) 
       .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, acct.type) 
       .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, acct.name) 
       .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT) 
       .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, "ContactName") 
       .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, "1234567890") 
       .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 1) 
       .build()); 
    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.DATA, "[email protected]") 
       .withValue(ContactsContract.CommonDataKinds.Email.TYPE, 1) 
       .build()); 

    try{   
     getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 
    } 
    catch (Exception e) { 
     Log.e("Contacts", "Something went wrong during creation! " + e); 
     e.printStackTrace(); 
    } 
} 
+0

¿Has encontrado cómo vincular los contactos generados, incluso si sus nombres son diferentes? –

+0

@androiddeveloper, lo siento, dejé de trabajar en esto y nunca encontré una buena respuesta. – Matt

+0

OK, creo que lo hice funcionar con su muestra, así que he publicado una respuesta. La cosa es que me hizo pensar en más preguntas que no sé. –

Respuesta

8

Si no están recopilando datos en forma automática, puede agregar manualmente mediante la adición de una fila a la tabla AggregationExceptions. Asegúrese de notar en los documentos que la inserción no está permitida. Tienes que hacer una actualización en su lugar. Eso me atrapó dos veces ahora. El siguiente código debe agregar los dos contactos primas con el ID de 1 y 2:

ContentValues cv = new ContentValues(); 
cv.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER); 
cv.put(AggregationExceptions.RAW_CONTACT_ID1, 1); 
cv.put(AggregationExceptions.RAW_CONTACT_ID2, 2); 
getContentResolver().update(AggregationExceptions.CONTENT_URI, cv, null, null); 
+0

Entonces, ¿tendré que aplicar esto cada vez que agregue un contacto? El programa en el que estoy trabajando agregará una gran cantidad de contactos (algunos o todos pueden existir), entonces eso significaría que para cada contacto que agregue tendría que ir a buscar los ID de todos los contactos con el mismo nombrar y agregar esta excepción? – Matt

+0

Por lo que yo sé, es bastante sombrío. Creo que se agregan automáticamente o tienes que forzarlos. – Samuel

+0

Parece una tontería tener que dar la vuelta y hacer manualmente lo que se espera que el teléfono haga. Estoy pensando que tiene que haber algo mal con la forma en que estoy agregando contactos. – Matt

1

He aquí una muestra modificada que incluye la vinculación, y con diferentes datos de cada uno, para probar que funciona:

Account acct = null; 
    Account[] accounts = AccountManager.get(this).getAccounts(); 
    for (Account acc : accounts) { 
     acct = acc; 
    } 
    //loop a few times, creating a new contact each time. In theory, if they have the same name they should aggregate 
    final ArrayList<Uri> newlyCreatedContactsUris = new ArrayList<>(); 
    for (int i = 0; i < 2; i++) { 
     ArrayList<ContentProviderOperation> ops = new ArrayList<>(); 
     ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) 
       .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, acct == null ? null : acct.type) 
       .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, acct == null ? null : acct.name) 
       .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT) 
       .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, "ContactName" + i) 
       .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, Integer.toString(123456789 * (i + 1))) 
       .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 1) 
       .build()); 
     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.DATA, "email" + i + "@address.com") 
       .withValue(ContactsContract.CommonDataKinds.Email.TYPE, 1) 
       .build()); 

     try { 
      final ContentProviderResult[] contentProviderResults = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 
      newlyCreatedContactsUris.add(contentProviderResults[0].uri); 
      Log.d("AppLog", "done creating new contacts data"); 
     } catch (Exception e) { 
      Log.e("AppLog", "Something went wrong during creation! " + e); 
      e.printStackTrace(); 
     } 
    } 
    //Note: seems we can only link 2 contacts data together, not more 
    ArrayList<ContentProviderOperation> mergeOps = new ArrayList<>(); 
    mergeOps.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI) 
      .withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER) 
      .withValue(AggregationExceptions.RAW_CONTACT_ID1, newlyCreatedContactsUris.get(0).getLastPathSegment()) 
      .withValue(AggregationExceptions.RAW_CONTACT_ID2, newlyCreatedContactsUris.get(1).getLastPathSegment()) 
      .build()); 
    try { 
     final ContentProviderResult[] contentProviderResults2 = getApplicationContext().getContentResolver().applyBatch(ContactsContract.AUTHORITY, mergeOps); 
     Log.d("AppLog", "done merging"); 
    } catch (RemoteException e) { 
     e.printStackTrace(); 
    } catch (OperationApplicationException e) { 
     e.printStackTrace(); 
    } 

y el resultado:

enter image description here

lo que no estoy seguro es de:

  1. ¿Cómo obtener los datos de contactos existentes y luego decidir qué fusionar? Me he dado cuenta de que la aplicación de contactos integrada puede fusionar contactos, pero a veces no los fusiona cuando el contacto principal toma el nombre de la combinación. ¿Cómo lo haría?
  2. ¿Cómo es que en la aplicación de contactos, no hay ninguna opción para desvincular, en lugar de hacer lo mismo con la interfaz de usuario?
  3. ¿Cómo decide qué información reemplazar, qué agregar, etc ...?
  4. ¿Cuáles son las reglas para combinar contactos automáticamente? Parece que un nombre de contacto idéntico es suficiente, pero puede hacerlo en casos incorrectos (porque diferentes personas pueden tener el mismo nombre, incluso el apellido).
  5. ¿Es realmente la forma correcta de usar "getLastPathSegment" para la identificación de contacto sin procesar?
Cuestiones relacionadas