proveedor nativos framework definicion contentresolver content contenido contactos java android android-contentprovider

java - nativos - contentresolver



El método de Content Observer onChange se llama dos veces después de 1 cambio en el cursor (5)

Tengo una aplicación en la que espero enviar los detalles de la lista de contactos de Android a un servidor remoto para que el usuario pueda ver sus contactos en línea. Para hacer esto, quiero notificar al servidor remoto cualquier cambio realizado en el teléfono a la lista de contactos.

He configurado un ContentObserver en el ''ContactsContract.Contacts.CONTENT_URI'' desde un servicio que se inicia cuando se inicia el teléfono.

Tengo varias preguntas, las 2 primeras son incidentales y la tercera es mi mayor preocupación.

1: Una vez que haya configurado un servicio que registra un ContentObserver en mi cursor, ¿ese observador solo existe dentro del servicio? Quiero decir, si se mata el servicio, ¿continúa observando contentObserver?

2: Sospecho que la respuesta es no, pero preguntaré de todos modos. ¿Hay alguna forma de saber qué contacto que se está actualizando está activando el método onchange de mi contentObserver? Actualmente tengo que compilar la lista de todos los contactos del teléfono y enviarlos a mi servidor remoto, sería mucho más fácil simplemente enviar los detalles de los contactos que se están actualizando.

3: Esta es mi pregunta principal, cuando realizo un cambio en mi Lista de contactos, el método onChange se dispara dos veces en rápida sucesión. 1 cambio, 2 llamadas. ¿Hay alguna forma de gestionar esto?

public class ContactService extends Service { JSONArray contactList; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { Log.i("C2DM","content observers initialised"); super.onCreate(); //Call Log Content Provider observer MyContentContactsObserver contactsObserver = new MyContentContactsObserver(); ContactService.this.getContentResolver().registerContentObserver (ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); } private class MyContentContactsObserver extends ContentObserver { public MyContentContactsObserver() { super(null); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.i("LOG","detected change in contacts: "+selfChange); } } }

Resultados en 2 líneas rápidas en mi logCat:

detected change in contacts: false detected change in contacts: false


Considere cómo registra su observador. El segundo argumento de registerContentObserver es boolean notifyForDescendents , lo has establecido en true . por lo que se le notificará cuando se hayan cambiado ContactsContract.Contacts.CONTENT_URI o cualquiera de sus descendientes. Puede ser que alguna operación de contacto con un id dado active la notificación tanto del uri de contacto específico como del uri de los contactos globales; si el segundo argumento es true su observador observa ambos.

Otra cosa es que puede registrar el observador de contenido para el ID de contacto específico uri - ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId) . Sin embargo, esto no tiene nada que ver con su problema, pero el registro del observador por separado para cada contacto parece bastante feo;)

Otra sugerencia: tal vez mantener el observador como campo final no volver a crearlo en onCreate (pero solo registrarlo allí).

public class ContactService extends Service { private final ContentObserver contactsObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.i("LOG","detected change in contacts: "+selfChange); //your code here } }; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { super.onCreate(); getContentResolver().registerContentObserver( ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); } @Override public void onDestroy() { getContentResolver().unregisterContentObserver(contactsObserver); super.onDestroy(); } }


Enfrenté el mismo problema en mi propio código y descubrí que estaba llamando a registerContentObserver () dos veces. Aunque fue para el mismo URI exacto y dentro de la misma clase, mi método onChange (boolean selfChange) fue llamado dos veces como resultado.


Para venir directo a tu nr. 3: ¿Cuánto tiempo hay entre las dos llamadas a su observador? Creo que se llama dos veces a su observador debido a la sincronización de contactos, que también actualiza la base de datos. Es decir. la primera vez es su actualización real, la segunda es cuando la sincronización finaliza y registra sus valores de sincronización en la misma fila de contactos.

¿Podrías desactivar la sincronización y ver si todavía se llama dos veces?


puede tener dos o más instancias de ContactService en las que todos ellos están registrados en el mismo ContactsContract.Contacts.CONTENT_URI.


ContentObserver una implementación similar y configuré un ContentObserver sobre el URI eventos del calendario. Y me enfrenté a todos los problemas, ustedes se enfrentan ahora. Así que su pregunta con mis soluciones / sugerencias va aquí ...

1) Una vez que haya configurado un servicio que registra un ContentObserver en mi cursor, ¿ese observador solo existe dentro del servicio? Quiero decir, si se mata el servicio, ¿continúa observando contentObserver?

No, no observará el contenido de su contenido sobre URI. Pero hay solución a esto. Puedes crear un servicio siempre en ejecución. Este servicio se creará de nuevo tan pronto como se despida debido a algún problema de memoria u otro despido inesperado. Siempre continuará ejecutándose a menos que se descarte explícitamente. Para crear dicho servicio, OnStartCommand(Intent intent, int flags, final int startId) en su clase de servicio y devuelva START_STICKY . Echa un vistazo al código de abajo.

public int onStartCommand(Intent intent, int flags, final int startId) { String authenticationKey = ((MainApplication) getApplicationContext()).getDbConnector().getUserAuthDefault() ; // if user is not registered yet, stop this service, it may be called from boot reciever. if(authenticationKey == null){ stopSelf(); } // restart, if we get killed. return START_STICKY; }

.

2: Sospecho que la respuesta es no, pero preguntaré de todos modos. ¿Hay alguna forma de saber qué contacto que se está actualizando está activando el método onchange de mi contentObserver? Actualmente tengo que compilar la lista de todos los contactos del teléfono y enviarlos a mi servidor remoto, sería mucho más fácil simplemente enviar los detalles de los contactos que se están actualizando.

Otra vez lo adivinaste bien :). la respuesta es no.
No hay manera de saber específicamente qué contacto se ha actualizado. ContentObserver simplemente proporciona un evento para hacerle saber que se ha realizado algún cambio en los datos señalados por el uri. Pero creo que estás manejando la situación de manera ineficiente, ya que estás compilando la lista de todos los contactos y enviándolos de vuelta al servidor.
Le sugiero que mantenga una lista de contactos, que se envían con éxito al servidor, en el almacenamiento local. Y la próxima vez que reciba una llamada en el método onChange() de contentObserver obtendrá todos los contacts de content_URI , los comparará con la lista almacenada anteriormente y enviará solo los contactos actualizados al servidor.

3: Esta es mi pregunta principal, cuando realizo un cambio en mi Lista de contactos, el método onChange se dispara dos veces en rápida sucesión. 1 cambio, 2 llamadas. ¿Hay alguna forma de gestionar esto?

Sí, esto sucede, pero supongo que estás en una impresión equivocada. En mi caso solía disparar al azar dos veces o tres veces o incluso más veces. así que había establecido un intervalo de umbral_tiempo. Un intervalo de tiempo dentro del cual si ContentObserver se ContentObserver nuevo, entonces no lo procesaría. Hice algo como esto ..

long lastTimeofCall = 0L; long lastTimeofUpdate = 0L; long threshold_time = 10000; /* (non-Javadoc) * @see android.database.ContentObserver#onChange(boolean) */ @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.d("content service", "on change called"); lastTimeofCall = System.currentTimeMillis(); if(lastTimeofCall - lastTimeofUpdate > threshold_time){ //write your code to find updated contacts here lastTimeofUpdate = System.currentTimeMillis(); } }

Espero que estas sugerencias / soluciones ayuden.