Метод Content Observer onChange вызывается дважды после 1 изменения курсора

у меня есть приложение, в котором я надеюсь отправить детали в списке контактов android на удаленный сервер, чтобы пользователь мог видеть свои контакты в интернете. Для этого я хочу уведомить удаленный сервер о любых изменениях, внесенных по телефону в список контактов.

Я настроил ContentObserver на ' ContactsContract.Контакты.CONTENT_URI ' от службы, которая запускается при загрузке телефона.

у меня есть несколько quiestions, первые 2 являются случайными, третье-моя главная забота.

1: Как только я настроил службу, которая регистрирует ContentObserver на моем курсоре, этот наблюдатель существует только в службе? Я имею в виду, если служба убита, продолжает ли contentObserver наблюдать?

2: я подозреваю, что ответ нет, но все равно спрошу. Есть ли в любом случае знать, какой контакт обновляется, запускает метод onchange моего contentObserver? в настоящее время я должен составить список всех тех контактов телефон и отправить их на мой удаленный сервер, было бы намного проще просто отправить детали контактов обновляется.

3:это мой главный вопрос, когда я делаю изменение в моем списке контактов, метод onChange запускается дважды подряд. 1 Смена, 2 звонка. Есть ли способ справиться с этим?

    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);
        }
    }
}

результаты в 2 быстрых строках в моем logCat:

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

5 ответов


Я сделал аналогичную реализацию и установил за день URI. и я столкнулся со всеми проблемами, с которыми вы столкнулись сейчас. Так что ваш вопрос с моими решениями/предложениями сюда....

1) Как только я настроил службу, которая регистрирует ContentObserver на мой курсор, существует ли этот наблюдатель только внутри службы? Я имею в виду, если служба будет убита, продолжает ли contentObserver наблюдать?

нет, он не будет наблюдать за содержимым вашего содержимого над URI. но решение есть. можно создать всегда работающую службу. Эта служба будет создана снова, как только она будет уволена из-за какой-либо проблемы с памятью или другого неожиданного увольнения. Он всегда будет продолжать работать, если он явно не отклонен. Чтобы создать такой сервис override OnStartCommand(Intent intent, int flags, final int startId) в вашем классе обслуживания и return START_STICKY. Взгляните на код ниже.

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: я подозреваю, что ответ нет, но все равно спрошу. Есть ли вообще знать что обновляемый контакт запускает метод onchange моего contentObserver? в настоящее время я должен составить список всех тех контактов на телефоне и отправить их в мой удаленный сервер, было бы намного проще просто отправить данные контактов обновляется.

вы опять угадали.:). ответа нет.
Нет никакого способа узнать, какой конкретно контакт был обновлен. ContentObserver просто предоставляет событие, чтобы вы знали, что некоторые изменения были внесены в данные, указанные uri. Но я думаю, что вы справляетесь с ситуацией неэффективно, так как вы составляете список всех контактов и отправляете их обратно на сервер.
Я бы предложил вам вести список контактов, которые успешно отправляются на сервер, в локальном хранилище. И в следующий раз, когда вы получить вызов в onChange() метод contentObserver вы принести все contacts С content_URI, сравните их с ранее сохраненным списком и отправьте только обновленные контакты на сервер.

3: это мой главный вопрос, когда я делаю изменение в моем списке контактов метод onChange, после стреляют два раза подряд. 1 Смена, 2 звонка. Есть ли в любом случае управление это?

Да, это происходит, но я думаю, у вас сложилось неправильное впечатление. В моем случае это используется для стрельбы случайным образом дважды или трижды или даже больше раз. поэтому я установил интервал threshold_time. Интервал времени, в течение которого ContentObserver снова запускается, тогда я бы не обрабатывал его. Я сделал что-то вроде этого..

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();
        }

    }  

надеюсь, что эти предложения/решения поможет.


рассмотрим, как вы регистрируете своего наблюдателя. Второй аргумент registerContentObserver is boolean notifyForDescendents, установлен true. таким образом, вы будете уведомлены, когда либо ContactsContract.Контакты.CONTENT_URI или любой из его descandants Урис были изменены. Возможно, какая - то операция для контакта с данным идентификатором запускает уведомление как для конкретного uri контакта, так и для глобального uri контактов-со вторым аргументом true ваш наблюдатель наблюдает как.

другое дело, что вы можете Регистрация content observer для конкретного контакта id uri -ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId). Однако это не имеет ничего общего с вашей проблемой, но регистрация отдельного наблюдателя для каждого контакта выглядит довольно уродливо;)

другое предложение: возможно, сохранить observer в качестве конечного поля не воссоздавать его в onCreate (но только регистрировать его там).

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();
    }
}

чтобы прийти прямо к вашему nr. 3. Сколько времени проходит между двумя звонками вашему наблюдателю? Я думаю, что ваш наблюдатель вызывается дважды из-за синхронизации контактов, которая также обновляет базу данных. То есть. первый раз-это фактическое обновление, второй-когда синхронизация завершена и регистрирует ее значения в одной строке контакта.

не могли бы вы отключить синхронизацию и посмотреть, если он по-прежнему вызывается дважды?


У вас может быть два или более экземпляров ContactService, которые все из них регистрируются одинаковыми ContactsContract.Контакты.CONTENT_URI.


столкнулся с той же проблемой в моем собственном коде и узнал, что я дважды вызывал registerContentObserver (). Хотя это было для того же самого URI и в том же классе мой метод onChange(boolean selfChange) был вызван дважды в результате.