2011-06-09 153 views
4

我试图从CallLog中查询数据并插入到数据库中。为此,我创建了一个COntentObserver作为Service中的内部类,并在onChange()方法中调用了我的方法,该方法转到指定的URI并查询已更改的数据。ContentObserver onChange()重复多次

但是,让我们说,我接到一个电话,所以观察员被通知。所以,我的方法去通话记录内容提供商,查询和插入,但它插入两个,三个相同的寄存器。

这是我的服务代码。

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

我从android.provider.CallLog.Calls.DATE中选择了呼叫的时间戳,在插入之前我检查是否有像这样的时间戳,如果有我不插入,如果没有我插入数据。这个值是独一无二的,所以永远不会有彼此喜欢的东西。

1

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

自我更改是否有所不同?

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