2

This is how I create calendar events from within my app:

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

At the time or writing, I store an array of all the event Ids that I've created, so that when the user flicks a switch, I loop through them and delete them from the Calendar.

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

It occurred to me that it might be possible to put a custom value for one of the CalendarContract.Events. columns so that I can do the deletion for all of the events at once, and that I don't have to remember their ids (I always delete them all, never delete certain ones)

Is that possible and which CalendarContract.Events. column should I use and how do I do the deletion then?

Kaloyan Roussev
  • 14,515
  • 21
  • 98
  • 180

3 Answers3

3

Nice question! I agree, that extra-property in ContentValues is the way to go in this case. I've done it by re-using CalendarContract.Events.CUSTOM_APP_PACKAGE, as something invisible for the user and, so far, no side effects found:

So I'm creating Events, like you do:

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

And then once I need to delete all of them, I call:

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

I hope, it helps

Konstantin Loginov
  • 15,802
  • 5
  • 58
  • 95
  • So there is no way to actually delete events without using a loop, just by saying "hey, delete all events corresponding to this app package at once"? I really want to prevent looping, because it takes forever deleting 300 events for example – Kaloyan Roussev Dec 28 '15 at 14:22
  • And the good side of this is that I do not have to save the event ids in the app storage and I can delete previous events from an uninstalled app, whenever I please, right? – Kaloyan Roussev Dec 28 '15 at 14:23
  • @J.K. That's right, once Events have the property set, you can delete it any time and, actually, even from the different app. I'll think if it's possible to bulk it and reach out – Konstantin Loginov Dec 28 '15 at 14:27
  • @J.K. I've updated code, now it's without loop for deleting. Check it out! – Konstantin Loginov Dec 28 '15 at 14:41
  • Thank you a lot! I will be able to award the bounty in 20 hours – Kaloyan Roussev Dec 28 '15 at 14:46
1

You can use ContentProviderOperation with applyBatch to perform multiple deletes/inserts in a single transaction.

Check this SO answer for code sample.

Community
  • 1
  • 1
LordRaydenMK
  • 13,074
  • 5
  • 50
  • 56
0

after a long long research, I've got a sort of new doc of google calendar you can add multiple args to a selection allowing you to find all desired rows and delete them all at once

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)
ravid rinek
  • 89
  • 1
  • 6