如何通过应用程序 ID 而不是事件 ID 数组从设备日历中批量删除事件

How to bulk delete events from the Device calendar by app id, and not by an array of event ids

这是我在我的应用程序中创建日历事件的方式:

for(CalendarEventDescriptor calendarEventDescriptor : calendarEventDescriptors.values()) {
                if(calendarEventDescriptor.startMilliseconds>now){

                    values = new ContentValues();
                    values.put(CalendarContract.Events.DTSTART, calendarEventDescriptor.startMilliseconds);
                    values.put(CalendarContract.Events.DTEND, calendarEventDescriptor.endMilliseconds);
                    values.put(CalendarContract.Events.TITLE, calendarEventDescriptor.title);
                    values.put(CalendarContract.Events.DESCRIPTION, calendarEventDescriptor.description);

                    values.put(CalendarContract.Events.CALENDAR_ID, 1);
                    values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone);
                    uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
                    calendarEventDescriptor.eventId = Long.parseLong(uri.getLastPathSegment());
                }
            }

在写作的时候,我存储了我创建的所有事件 ID 的数组,这样当用户轻按一个开关时,我循环遍历它们并将它们从日历中删除。

for(long eventId : eventIds) {
                if(eventId>0){
                    Uri deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId);
                    rowsDeleted += application.getContentResolver().delete(deleteUri, null, null);
                }
            }

我想到可以为 CalendarContract.Events. 列之一设置自定义值,这样我就可以一次删除所有事件,但我没有这样做必须记住他们的id(我总是把它们全部删除,从不删除某些)

这可能吗?我应该使用哪个 CalendarContract.Events. 列,然后我该如何删除?

好问题!我同意,在这种情况下,ContentValues 中的 extra-属性 是可行的方法。 我通过重新使用 CalendarContract.Events.CUSTOM_APP_PACKAGE 来完成它,作为对用户不可见的东西,到目前为止,没有发现副作用:

所以我正在像您一样创建活动:

        ContentResolver cr = getContentResolver();
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Events.CALENDAR_ID, 1);
        values.put(CalendarContract.Events.DTSTART, ...);
        values.put(CalendarContract.Events.DTEND, ...);
        values.put(CalendarContract.Events.TITLE, ...);
        values.put(CalendarContract.Events.DESCRIPTION, ....);
        values.put(CalendarContract.Events.CUSTOM_APP_PACKAGE, getApplicationContext().getPackageName());
        values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
        cr.insert(CalendarContract.Events.CONTENT_URI, values);

然后一旦我需要删除所有这些,我调用:

    Cursor cursor = cr
            .query(CalendarContract.Events.CONTENT_URI,
                   new String[] { CalendarContract.Events._ID, CalendarContract.Events.CUSTOM_APP_PACKAGE },
                   null, null, null);
    cursor.moveToFirst();

    String idsToDelete = "";
    for (int i = 0; i < cursor.getCount(); i++) {
        // it might be also smart to check CALENDAR_ID here
        if (getApplicationContext().getPackageName().equals(cursor.getString(1))) {
            idsToDelete += String.format("_ID = %s OR ", cursor.getString(0));
        }

        cursor.moveToNext();
    }

    if (idsToDelete.endsWith(" OR ")) {
        idsToDelete = idsToDelete.substring(0, idsToDelete.length()-4);
    }

    cr.delete(CalendarContract.Events.CONTENT_URI, idsToDelete, null);

希望对你有所帮助

您可以使用 ContentProviderOperation with applyBatch 在单个事务中执行多个 deletes/inserts。

检查 this SO answer 代码示例。

经过长时间的研究,我得到了一种新的 google 日历文档 您可以将多个参数添加到一个选择中,这样您就可以找到所有需要的行并一次性删除它们

val operationList = ArrayList<ContentProviderOperation>()
var contentProviderOperation: ContentProviderOperation

appointments.forEach {
   contentProviderOperation = ContentProviderOperation
  .newDelete(CalendarContract.Events.CONTENT_URI)
  .withSelection(CalendarContract.Events.ORIGINAL_SYNC_ID + " =?", arrayOf(it.id))
  .build()

  operationList.add(contentProviderOperation)
}

contentResolver.applyBatch(CalendarContract.AUTHORITY, operationList)