ContentObserver onChange () повторяется несколько раз - PullRequest
4 голосов
/ 09 июня 2011

Я пытаюсь запросить данные из CallLog и вставить в БД.Для этого я создал COntentObserver как внутренний класс в Service, а внутри метода 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));

        }
    }

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

Ответы [ 2 ]

2 голосов
/ 16 июня 2011

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

1 голос
/ 16 июня 2011

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

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

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

...