2017-03-28 21 views
0

サーバーからAPI呼び出しまでの(週の)イベントのリストを取得し、私のアプリケーションはそれらをデバイスのカレンダーに同期させる必要があります。イベントは、アプリケーションからのインタラクションなしで、サーバー上で更新または削除することができます。そして、画面の更新時にカレンダーに同期する必要があります。私のサーバーを最新の状態にカレンダー上の私のイベントを作るためにAndroidカレンダーでイベントが重複しないようにするにはどうすればよいですか?

、私はリフレッシュに次の操作を実行している:

  1. はカレンダーから特定の週のすべてのイベントを削除します。
  2. 次に、サーバーから取得したイベントを挿入します。

    public static void deleteAllEventsInWeekOfCalendar(Activity activity, int calId, long weekStartTimeMillis, long weekEndTimeMillis) { 
        try { 
        Uri eventUri = Uri.parse("content://com.android.calendar/events"); 
        String[] projection = new String[]{Events._ID, Events.TITLE, Events.DTSTART, Events.DESCRIPTION}; 
        String whereClause = Events.CALENDAR_ID + "=" + calId + 
          " AND " + Events.DTSTART + " >= " + weekStartTimeMillis + 
          " AND " + Events.DTSTART + " <= " + weekEndTimeMillis + 
          " AND " + Events.DESCRIPTION + " LIKE '% Added by MyApp'"; 
    
        Cursor cursor = activity.getContentResolver().query(eventUri, projection, whereClause, null, Events.DTSTART); 
        if (cursor != null && cursor.moveToFirst()) { 
         Log.v("HowMany", cursor.getCount() + " matching events Found"); 
         int numOfDeleted = 0; 
         do { 
          try { 
           String event_id = cursor.getString(cursor.getColumnIndexOrThrow(projection[0])); 
           int numOfRowsDeleted = activity.getContentResolver().delete(ContentUris.withAppendedId(eventUri, Long.parseLong(event_id)), null, null); 
           if (numOfRowsDeleted == 1) { 
            ++numOfDeleted; 
           } 
          } catch (Exception e) { 
           e.printStackTrace(); 
          } 
         } while (cursor.moveToNext()); 
         cursor.close(); 
         Log.v("HowMany", numOfDeleted + " deleted"); 
        } 
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
    } 
    

そして、ここに私のコードは、カレンダーにすべてのイベントを挿入することです:

public static void doAddCalendarEvent(MyEvent myEvent, Activity activity, int calendarId) { 
    try { 
     if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) { 
      return; 
     } 
     String desc = myEvent.getDesc(); 
     desc += "\n\n Added by MyApp"; 

     ContentResolver cr = activity.getContentResolver(); 
     ContentValues values = new ContentValues(); 
     values.put(Events.DTSTART, myEvent.getEventStartTime()); 
     values.put(Events.DTEND, myEvent.getEventEndTime()); 
     values.put(Events.TITLE, myEvent.getTitle()); 
     values.put(Events.DESCRIPTION, desc); 
     values.put(Events.CALENDAR_ID, calendarId); 
     values.put(Events.EVENT_LOCATION, myEvent.getLocation()); 
     values.put(Events.STATUS, Events.STATUS_CONFIRMED); 
     values.put(Events.AVAILABILITY, Events.AVAILABILITY_BUSY); 
     if (hasAlarm) { 
      values.put(Events.HAS_ALARM, true); 
     } 
     values.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getID()); 
     long eventId = 0; 
     Uri uri = cr.insert(Events.CONTENT_URI, values); 
     if (uri != null) { 
      eventId = Long.parseLong(uri.getLastPathSegment()); 
      Log.v(TAG, "INSERTED EVENT ID=>" + eventId + "--->" + startDate); 
     } 
     if (hasAlarm) { 
      setReminder(cr, reminderValue, eventId); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

問題:時々イベントがカレンダーに複製されています。重複を避けるにはどうすればいいですか?どこが間違っているの?提案してください。

答えて

0

私はあなたがカレンダーとのインターフェイスに同期アダプタを使用していると仮定しています。

同期アダプタは、2つの重要なメソッドがあります。

onPerformSync(...)を、自動同期がtrueに設定されている場合は、ContentResolver.requestSync電話をかけるか、いつでも onSyncCanceled(...)

onPerformSyncが呼び出されます。

実行中、onPerformSyncはAndroidによって中断することができます。これは、あなたのアプリがフォアグラウンドにもう存在しない場合、デバイスのリソースが不足している場合に発生します。

インターアダプターを使用すると、同期アダプターの実行が停止し、onSyncCanceledが呼び出されます。同期アダプタのデフォルトの動作は、失敗した同期メッセージが最初に受信されたときに再試行することです。したがって、あなたのアプリケーションが再びOSリソースを取得しようとすると、中断された同期メッセージが再生されます。

メッセージの一部が完全に処理されており、onPerformSyncが完了する直前に、同期アダプタが中断されている可能性があります。この時点でイベントを保存することができましたが、同期アダプターは同期が失敗したと考え、次回同期しようとしたときに再び同じメッセージを再生します。

一度に1つのイベントを同期しているかどうかはわかりません。そのため、決定的な解決策はありません。ただし、同期アダプタのデフォルトの動作を変更して、「失敗した」メッセージを再生しないようにすることができます。 OnSyncCanceled

Bundle extras = new Bundle(); ... extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); CalendarConstants.AUTHORITY, true); ContentResolver.requestSync(mAccount, CalendarConstants.AUTHORITY, extras);

、あなたは、メッセージが成功したことを確認するためにいくつかの光のチェックを行うことができ、すなわち、カレンダーのイベントテーブルに存在しています。そうでない場合は、手動で再生してください。存在する場合、SyncAdapterは次のメッセージに進むだけで、重複はありません。

onPerformSync内のすべての操作がアトミックであることを確認することもできます。

関連する問題