com.android.providers.calendar是删除已删除的事件还是仅将其标记为已删除



在Android KitKat中,com.android.providers.calendar是从日历存储数据库中删除已删除的日历事件,还是仅将其标记为已删除?

如果它只是在数据库中标记它们,那么它会向数据库中写入什么来反映删除?

我主要感兴趣的是这与本地(非同步)日历的关系,但欢迎对本地和同步日历做出技术回应。

如果这个问题属于Android SE而不是这里,请迁移它。我决定在这里发布它,因为(1)这里更技术的受众实际上可能能够回答这个问题,(2)Android SE可能会意识到这是一个与编程相关的问题,并将其迁移到StackOverflow

Event有一个DELETED列和一个DIRTY列。

根据我的经验,CalendarProvider对这些专栏没有做任何特殊的事情,工作由您决定。所以,若使用delete查询删除事件,它将从数据库中完全删除。

Google Calendar等日历应用程序是这样工作的:如果某个事件发生了任何类型的更新或删除,则DIRTY列将设置为true。如果用户删除了事件,则DELETED列也设置为true。

因此,当SyncAdapter开始同步时,它会在DIRTY列中找到未同步的事件,如果DELETED列也为true,则它会在同步后从数据库中完全删除该事件。

查看CalendarProvider2.java.的来源

正如您所看到的,只有两种情况下事件实际上是从数据库中删除的:

  1. 它已被同步适配器删除
  2. 它有一个空的SYNC_ID,这意味着它还没有被同步

如果事件已由同步适配器同步,并且已由普通应用程序删除,则该事件始终标记为已删除(通过将DELETED列设置为1)。这对于通知同步适配器删除是必要的。如果事件被完全删除,同步适配器找不到它,它只会假设事件尚未同步,并从服务器上还原它。

关于本地日历:如果同步适配器不支持本地日历,则会立即删除该事件,因为这些事件总是有一个空的SYNC_ID字段。

请注意,作为普通应用程序,不应尝试修改DELETEDDIRTY列。它们的值由日历提供程序设置,并由同步适配器清除。

更新以跟进您的评论

确实,如果某个重复事件没有SYNC_ID,则不能修改该事件的单个实例。因此,为了修改重复事件的单个实例,您需要分配一个伪SYNC_ID。非经常性事件不需要这样做。

如果您将此类事件作为非同步适配器应用程序删除,则该事件可能会永远保留在我们的日历数据库中,只需将已删除标志设置为1即可。

为了解决这个问题,我看到了两个选项:

简单但"粗暴"的方式

简单的方法是假装你是相应帐户的同步适配器。到目前为止,我还没有看到任何检查,所以我认为如果你不是同步适配器,日历提供商不会抱怨。然而,您需要确保只为本地帐户(没有真正的同步适配器)执行此操作,否则您将破坏一切。

干净的方式

对于干净的方式,你需要区分几种情况:

删除SYNC_ID为空的事件

在这种情况下,你可以像之前一样继续删除它

删除具有非空SYNC_ID的非定期事件

在这种情况下,您需要首先清除SYNC_ID字段,然后在第二步中删除事件(不过您可以在单个事务中执行此操作)。AFAIK,如果您将SYNC_ID更改为非同步适配器应用程序,日历提供商不会抱怨。尽管你应该测试一下。

删除重复事件的异常实例(如"取消"实例)

你有两个选择。

  1. 只需将事件状态设置为Events.STATUS_CANCELED,这将保留实例,但它将"显示"为已删除的实例。这就是在Android中通常删除事件实例的方式。

  2. 清除ORIGINAL_SYNC_ID字段,删除实例并向主事件添加一个EXDATE

删除具有非空SYNC_ID的整个重复事件(包括所有异常)

在这里,您唯一的选择是清除SYNC_ID字段,然后删除该事件。在这种情况下,您可能还必须删除所有具有相同ORIGINAL_SYNC_ID的异常(不确定Android是否会自动删除)。如果有多个异常,则必须首先清除ORIGINAL_SYNC_ID,否则它们可能不会被删除。

注意 :我没有测试任何这些。我的回答完全基于我使用CalendarProvider的经验,并通过查看以下来源得出:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/5.1.1_r1/com/android/providers/calendar/CalendarProvider2.java

最新更新