如何避免Android日历中的重复事件?

时间:2017-03-28 02:15:56

标签: android android-calendar android-contentresolver

我通过API调用从服务器获取事件列表(一周),我的应用程序需要将它们同步到设备中的日历。可以在服务器上更新或删除事件,而无需与应用程序进行任何交互。我需要在每次刷新屏幕时将它们同步到日历。

要使我的服务器在日历上更新我的事件,我正在刷新时执行以下操作:

  1. 从日历中删除给定周的所有事件。
  2. 然后插入我从服务器获取的事件。

    <p:outputLabel value="Pessoa" />
    <p:autoComplete id="inptNomeID" value="#{usuarioBean.usuario.pessoa}" completeMethod="#{usuarioBean.autoCompletePessoa}"
                    var="pessoa" itemLabel="#{pessoa.nome}" itemValue="#{pessoa}" converter="omnifaces.SelectItemsConverter" forceSelection="true"/>
    
  3. 以下是我将所有事件插入日历的代码:

    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();
    }
    }
    

    问题:有时事件在日历上重复。我该如何避免重复?我哪里错了?请建议。

1 个答案:

答案 0 :(得分:0)

我假设您正在使用同步适配器与日历进行交互。

同步适配器有两个重要方法:

onPerformSync(...),和 onSyncCanceled(...)

每当您进行onPerformSync通话或自动同步设为真时,都会调用

ContentResolver.requestSync

执行时,onPerformSync可以被Android中断。如果设备的资源不足,如果您的应用不再处于前台,则可能会发生这种情况。

当中断时,同步适配器将在其所在位置停止执行并将调用onSyncCanceled。同步适配器的默认行为是在第一次获得失败的同步消息时重试失败的同步消息。因此,如果您的应用程序设法再次获取操作系统资源,它将重播中断的同步消息。

您的某些邮件可能已完全处理,并且在onPerformSync即将完成之前,同步适配器将被中断。此时您设法保存事件,但是,同步适配器认为同步失败,因此下次尝试同步时将再次重播相同的消息。

我不确定您是否同时同步一个事件,因此我无法提供明确的解决方案。但是,您可以做的是更改同步适配器的默认行为以阻止它重放&#34;失败&#34;消息。

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

OnSyncCanceled中,您可以进行一些轻微检查以确保消息成功,即出现在日历的事件表中。如果没有,则手动重播。如果它存在,SyncAdapter将只是转到下一条消息,你不会得到任何重复。

或者,您可以确保onPerformSync内的所有操作都是原子的。