ContentObserver onChange()重复多次

时间:2011-06-09 19:49:11

标签: android android-contentprovider

我正在尝试从CallLog查询数据并插入数据库。为此,我在Service中创建了一个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));

        }
    }

我已经尝试了一切。取消注册观察者等但没有注销。

2 个答案:

答案 0 :(得分:2)

我选择了来自android.provider.CallLog.Calls.DATE的调用的时间戳,在插入之前,我检查是否有一个类似于那个的时间戳,如果有我不插入,如果没有我插入数据。这个值是独一无二的,所以永远不会有彼此相似。

答案 1 :(得分:1)

当我怀疑短信内容提供商时,这种情况发生在我身上。我认为他们是Android处理消息和调用这种行为的方式,每当我发送短信时我都会接到2次呼叫,所以我猜是因为消息被放在发件箱表中了?首先,然后移动到发送表。呼叫提供商可能会发生类似的事情吗?也许这个调用被放置在提供者内部的临时表中,然后一旦你收到它或错过它,这个调用将转到正确的表(收到/错过)。我所做的是,每当我的观察者被调用时,我都会检查消息的ID,并保留上一条消息的Id,以便我可以检查观察者是否由于我刚刚处理的ID而被calld。

selfChange有变化吗?

提示。不要依赖此提供商来监控您的所有通话。一旦android决定终止您的应用程序,您将注意到您的提供商将不再接收任何电话。尝试使用AlarmManager每隔一段时间安排内容观察者的附件。