ContentObserver onChange() повторяется несколько раз

Я пытаюсь запросить данные из CallLog и вставить в БД. Для этого я создал COntentObserver как внутренний класс в службе, а внутри метода onChange() я вызываю свой метод, который переходит к указанному URI и запрашивает измененные данные.

Но, скажем, мне позвонили, значит, наблюдатель был уведомлен. Итак, мой метод обращается к провайдеру содержимого журнала вызовов, запрашивает и вставляет, но он вставляет два, три раза один и тот же регистр.

Вот код моего сервиса.

public class RatedCallsService extends Service 

private Handler handler = new Handler();
    private SQLiteDatabase db;
    private OpenHelper helper;
    private String theDate;
    private String theMonth_;
    private String theYear_;
    private String theDay_;
    public static boolean servReg = false;

    class RatedCallsContentObserver extends ContentObserver {

            public RatedCallsContentObserver(Handler h) {

                super(h);
                //helper = new OpenHelper(getApplicationContext());
                //db = helper.getWritableDatabase();

            }

            @Override
            public boolean deliverSelfNotifications() {

                return true;

            }

            @Override
            public void onChange(boolean selfChange) {

                super.onChange(selfChange);
                Log.i(LOG_TAG, "Inside on Change. selfChange " + selfChange);
                searchInsert();
            }
        }

        @Override
        public IBinder onBind(Intent arg0) {

            return null;

        }

        @Override

        public void onCreate() {
            servReg = true;
            db = DataHandlerDB.createDB(this);
            registerContentObserver();

        }

        @Override
        public void onDestroy() {

            super.onDestroy();
            db.close();
            this.getApplicationContext().getContentResolver().unregisterContentObserver(new RatedCallsContentObserver(handler));

        }

        private void searchInsert() { 

                    Cursor cursor = getContentResolver().query(
            android.provider.CallLog.Calls.CONTENT_URI, null, null, null,
            android.provider.CallLog.Calls.DATE + " DESC ");

    if (cursor.moveToFirst()) {

        int numberColumnId = cursor
                .getColumnIndex(android.provider.CallLog.Calls.NUMBER);
        int durationId = cursor
                .getColumnIndex(android.provider.CallLog.Calls.DURATION);
        int contactNameId = cursor
                .getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);
        int numTypeId = cursor
                .getColumnIndex(android.provider.CallLog.Calls.CACHED_NUMBER_TYPE);
        int callTypeId = cursor
                .getColumnIndex(android.provider.CallLog.Calls.TYPE);

        Date dt = new Date();
        int hours = dt.getHours();
        int minutes = dt.getMinutes();
        int seconds = dt.getSeconds();
        String currTime = hours + ":" + minutes + ":" + seconds;

        SimpleDateFormat dateFormat = new SimpleDateFormat("M/d/yyyy");

        Date date = new Date();

        cursor.moveToFirst();

        String contactNumber = cursor.getString(numberColumnId);
        String contactName = (null == cursor.getString(contactNameId) ? ""
                : cursor.getString(contactNameId));
        String duration = cursor.getString(durationId);
        String numType = cursor.getString(numTypeId);
        String callType = cursor.getString(callTypeId);

        seconds = Integer.parseInt(duration);

        theDate = dateFormat.format(date);

        if (theDate.length() == 9) {

            theMonth_ = theDate.substring(0, 1);
            theDay_ = theDate.substring(2, 4);
            theYear_ = theDate.substring(5, 9);

        } else if (theDate.length() == 10) {

            theMonth_ = theDate.substring(0, 2);
            theDay_ = theDate.substring(3, 4);
            theYear_ = theDate.substring(6, 10);

        } else if (theDate.length() == 8) {

            theMonth_ = theDate.substring(0, 1);
            theDay_ = theDate.substring(2, 3);
            theYear_ = theDate.substring(4, 8);

        }

        ContentValues values = new ContentValues();
        ContentValues values2 = new ContentValues();

        values.put("contact_id", 1);
        values.put("contact_name", contactName);
        values.put("number_type", numType);
        values.put("contact_number", contactNumber);
        values.put("duration", Utilities.convertTime(seconds));
        values.put("date", dateFormat.format(date));
        values.put("current_time", currTime);
        values.put("cont", 1);
        values.put("type", callType);

        values2.put("month",
                Utilities.monthName(Integer.parseInt(theMonth_)));
        values2.put("duration", Utilities.convertTime(seconds));
        values2.put("year", theYear_);
        values2.put("month_num", Integer.parseInt(theMonth_));

        if (!db.isOpen()) {
            db = getApplicationContext()
                    .openOrCreateDatabase(
                            "/data/data/com.project.myapp/databases/myDb.db",
                            SQLiteDatabase.OPEN_READWRITE, null);
        }           
        if (duration != "") {               
            if (Integer.parseInt(duration) != 0) {

                String existingMonthDuration = DataHandlerDB
                        .selectMonthsDuration(theMonth_, theYear_, this);
                Integer newMonthDuration;


                if (existingMonthDuration != "") {

                    newMonthDuration = Integer
                            .parseInt(existingMonthDuration)
                            + Integer.parseInt(duration);                       

                    values2.put("duration",
                            Utilities.convertTime(newMonthDuration));
                    db.update(DataHandlerDB.TABLE_NAME_3, values2,
                            "year = ?", new String[] { theYear_ });

                } else {

                    db.insert(DataHandlerDB.TABLE_NAME_3, null, values2);

                }

                db.insert(DataHandlerDB.TABLE_NAME_2, null, values);

            }
        }
        cursor.close();

    }

            }

    public void registerContentObserver() {

            this.getApplicationContext()
                    .getContentResolver()
                    .registerContentObserver(
                            android.provider.CallLog.Calls.CONTENT_URI, false,
                            new RatedCallsContentObserver(handler));

        }
    }

Я пробовал все. отмена регистрации наблюдателя и т. д., но ничего.


person rogcg    schedule 09.06.2011    source источник


Ответы (2)


Я выбрал временную метку вызова из android.provider.CallLog.Calls.DATE и перед вставкой проверяю, есть ли такая временная метка, если есть, я не вставляю, если нет, я вставляю данные. Эти значения уникальны, поэтому они никогда не будут похожи друг на друга.

person rogcg    schedule 16.06.2011

Это происходит со мной, когда я подписываюсь на поставщика SMS-контента. Я думаю, что Android обрабатывает сообщения и вызовы, которые вызывают такое поведение, я получаю вызов 2 раза всякий раз, когда отправляю SMS, поэтому я предполагаю, что это связано с тем, что сообщение помещается в таблицу исходящих сообщений? сначала, а затем перешли к отправленному столу. Возможно, что-то подобное происходит с провайдером звонков? Возможно, этот вызов помещается во временную таблицу внутри провайдера, а затем, как только вы его получаете или пропускаете, этот вызов переходит в соответствующую таблицу (получен/пропущен). Что я делаю, так это проверяю идентификатор сообщения каждый раз, когда вызывается мой наблюдатель, и сохраняю идентификатор предыдущего сообщения, чтобы я мог проверить, вызывается ли наблюдатель из-за того же идентификатора, который я только что обработал.

меняется ли selfChange?

Намекать. не полагайтесь на этого провайдера для отслеживания всех ваших звонков. Как только Android решит закрыть ваше приложение, вы заметите, что ваш провайдер больше не будет получать звонки. Попробуйте запланировать подключение наблюдателя контента время от времени с помощью AlarmManager.

person emmanuel.aquino    schedule 15.06.2011