I'm trying to implement my first android Program. It should write calendar entries (I know, not the best task to begin programming Andorid).
I've tried:
Uri CALENDAR_URI = Uri.parse("content://calendar/events");
ContentResolver cr = getContentResolver();
cr.delete(CALENDAR_URI, null, null); // Delete all
cr.delete(CALENDAR_URI, "calendar_id=1", null); // Delete all in default calendar
cr.delete(CALENDAR_URI, "_id=1", null); // Delete specific entry
Nothing worked. I allays get a "cannot delete that URL".
Inserting an Calendar Entry was simple:
ContentValues values = new ContentValues();
values.put("calendar_id", 1);
values.put("title", this.title);
values.put("allDay", this.allDay);
values.put("dtstart", this.dtstart.toMillis(false));
values.put("dtend", this.dtend.toMillis(false));
values.put("description", this.description);
values.put("eventLocation", this.eventLocation);
values.put("visibility", this.visibility);
values.put("hasAlarm", this.hasAlarm);
cr.insert(CALENDAR_URI, values);
According to my insert method accessing the calendar worked.
Thanks, Arthur!
OK, one thing I didn't try:
Uri CALENDAR_URI = Uri.parse("content://calendar/events");
int id = 1; // calendar entry ID
Uri uri = ContentUris.withAppendedId(CALENDAR_URI, id);
cr.delete(uri, null, null);
This is what I was missing:
Uri uri = ContentUris.withAppendedId(CALENDAR_URI, id);
should lead to content://calendar/events/1
Now my Calendar is empty :-)
The right way to delete things out of a user's calendar is to use the appropriate GData APIs and delete it from their Google Calendar. Manipulating the Calendar application's content provider -- as you are trying to do -- is not part of the public API.
Related
Hello I am a beginner in android.
I want to add an event in google calendar from my android application.
Please help me with complete source code. I have looked, but haven't found a solution with complete source code.
You can use ContentValues like local db,
String eventUriString = "content://com.android.calendar/events";
ContentResolver cr = this.getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Reminders.CALENDAR_ID, 1);
values.put(CalendarContract.Reminders.TITLE, "YOUR_TITLE");
values.put(CalendarContract.Reminders.DTSTART, TIMES IN MILLISECOND);
values.put(CalendarContract.Reminders.DESCRIPTION,YOUR_TEXT);
values.put(CalendarContract.Reminders.DTEND, TIMES IN MILLISECOND);
values.put(CalendarContract.Reminders.HAS_ALARM, true);
values.put(CalendarContract.Reminders.EVENT_TIMEZONE, TimeZone.getDefault().getID());
Uri uriEvents = cr.insert(CalendarContract.Events.CONTENT_URI, values);
eventID = Long.parseLong(uriEvents.getLastPathSegment());
I'm trying to update calendar events programmatically but I have some issues.
I'm using updating code from Google Android Documentation: https://developer.android.com/guide/topics/providers/calendar-provider.html#update-event
So here's my code :
ContentValues values = new ContentValues();
Uri updateUri = null;
// New end for event
values.put(CalendarContract.Events.DTEND, endMillis);
updateUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID);
int rows = c.getContentResolver().update(updateUri, values, null, null);
Log.i("DEBUG_TAG", "Rows updated: " + rows);
But rows variable always returns 0 except when I go into apps settings, remove calendar storage, add a new calendar and a new event and then when I try to update it, it works only once. If I try to add another event and update it afterward, rows return 0 again.
Any idea?
Thanks
Please note that my app is min API level 17 (on which it doesn't work) but I tried on API level 25 and it works, so do you have any idea how to add support to my code for previous Android versions? I've also found that after some tests, it works from API level 21. Under, it doesn't.
EDIT :
I've found a solution, check my answer below.
Here's the solution that worked for me :
The eventID that I used was the result of the query with column CalendarContract.Events._ID but I had to used the ID provided by CalendarContract.Instances.EVENT_ID.
Indeed if I create a new event (the first one) it has _id = 1 and event_id = 1, and if I delete it from Android Calendar App and I create a new one with my app, it has also _id = 1 but event_id = 2.
So the update query failed if I use _id instead of event_id with withAppendedID().
Here's the code that worked for me. startMillis and endMillis are respectively your meeting start time and end time in milliseconds.
Uri.Builder eventsUriBuilder = CalendarContract.Instances.CONTENT_URI
.buildUpon();
ContentUris.appendId(eventsUriBuilder, startMillis);
ContentUris.appendId(eventsUriBuilder, endMillis);
Uri eventsUri = eventsUriBuilder.build();
String[] column = {CalendarContract.Instances.EVENT_ID, CalendarContract.Events.DTSTART, CalendarContract.Events.DTEND, CalendarContract.Events.TITLE};
Cursor cursor;
cursor = c.getContentResolver().query(eventsUri, column, CalendarContract.Events.CALENDAR_ID+"="+Constant.ID_CALENDAR, null, CalendarContract.Instances.DTSTART + " ASC");
if (cursor.moveToFirst()) {
do {
uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI,cursor.getLong(0));
} while (cursor.moveToNext());
}
cursor.close();
c.getContentResolver().delete(uri, null, null);
I have created some events and stored the data in sqlite table but not the system calendar. However, i would like to have an alert/reminder for these events, which is similar to other events that stored in the system.
With reference to the code below, the details of the event are put in the "CalendarAlerts" table and in the broadcast receiver, the alertCursor is used to find the event data with start time close to the current time.
The code worked well if the event is stored in the system with a "long" eventID. But when i try to put data of my sqlite event in "CalendarAlerts" with a "string" eventID. It shows that the data is inserted into the table successfully but i would not query back the result in the "Alert Receiver" class.
Searched google for a while and it seems that not many people are talking on the topic of "CalendarAlerts". Great if anyone would share the experience on this issue.
Setting the AlarmManager
Uri alertUri = CalendarAlerts.CONTENT_URI;
long alarmMillis = (long) mStart - (long)(min*60*1000);
ContentValues alertValues =AlertUtils.makeContentValues(eventIdentifier,mStart, mEnd,alarmMillis, 0);
context.getContentResolver().insert(alertUri, alertValues);
public static ContentValues makeContentValues(String eventId, long begin, long end,
long alarmTime, int minutes) {
ContentValues values = new ContentValues();
values.put(CalendarAlerts.EVENT_ID, eventId);
values.put(CalendarAlerts.BEGIN, begin);
values.put(CalendarAlerts.END, end);
values.put(CalendarAlerts.ALARM_TIME, alarmTime);
long currentTime = System.currentTimeMillis();
values.put(CalendarAlerts.CREATION_TIME, currentTime);
values.put(CalendarAlerts.RECEIVED_TIME, 0);
values.put(CalendarAlerts.NOTIFY_TIME, 0);
values.put(CalendarAlerts.STATE, CalendarAlerts.STATE_SCHEDULED);
values.put(CalendarAlerts.MINUTES, minutes);
return values;
}
AlertReceiver.java
Cursor alertCursor = cr.query(CalendarAlerts.CONTENT_URI, ALERT_PROJECTION,
(ACTIVE_ALERTS_SELECTION + currentMillis), ACTIVE_ALERTS_SELECTION_ARGS,
ACTIVE_ALERTS_SORT);
You can use this code which works for me :
ContentResolver cr = getActivity().getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.DTSTART, startMillis);
values.put(CalendarContract.Events.TITLE, title);
values.put(CalendarContract.Events.DESCRIPTION, "description");
TimeZone timeZone = TimeZone.getDefault();
values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone.getID());
// default calendar
values.put(CalendarContract.Events.CALENDAR_ID, 1);
//for one hour
values.put(CalendarContract.Events.DURATION, "+P1H");
values.put(CalendarContract.Events.HAS_ALARM, 1);
// cr.delete(CalendarContract.Events.CONTENT_URI, null,null);
// insert event to calendar
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
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?
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
You can use ContentProviderOperation with applyBatch to perform multiple deletes/inserts in a single transaction.
Check this SO answer for code sample.
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)
Actually i am get stuck in a big problem..I have created an app from which i can save event in my device calendar..Now when i save new events from my app in my device calendar it will always delete the events save previously by my app and save a new event and so on..so all works fine..now the big problem is that while deleting it will delete all the events of the calendar that are present in the device calendar including the events that are save by my app..so what i want is to delete only that event that are put by my app while inserting new event from my app not that are already present or which are directly assigned by me in device calendar..so can anyone please help me out to resolve this problem..the code i have use for inserting and deleting are..
Resources res = c.getResources();
Uri EVENTS_URI = Uri.parse("content://com.android.calendar/" + "events");
Uri REMINDERS_URI = Uri.parse("content://com.android.calendar/" + "reminders");
ContentResolver cr = c.getContentResolver();
Uri uri= ContentUris.withAppendedId(EVENTS_URI, 1);
deleteEvent(cr, Resources res = c.getResources();
Uri EVENTS_URI = Uri.parse("content://com.android.calendar/" + "events");
Uri REMINDERS_URI = Uri.parse("content://com.android.calendar/" + "reminders");
ContentResolver cr = c.getContentResolver();
//Deleting event from device calendar before saving new event
deleteEvent(cr, EVENTS_URI, 1);
//saving new data to calendar
ContentValues values = new ContentValues();
values.put("calendar_id", 1);
values.put("title", str);
values.put("description", m_strDescription);
values.put("dtstart", cal.getTimeInMillis());
values.put("dtend", cal.getTimeInMillis());
values.put("hasAlarm", 1);
Uri event = cr.insert(EVENTS_URI, values);
values = new ContentValues();
values.put("event_id", Long.parseLong(event.getLastPathSegment()));
values.put("method", 1);
values.put("minutes", 10);
cr.insert(REMINDERS_URI, values);
Functions for deleting event
private void deleteEvent(ContentResolver resolver, Uri eventsUri, int calendarId)
{
Cursor cursor;
if (android.os.Build.VERSION.SDK_INT <= 7)
{
cursor = resolver.query(eventsUri, new String[]{ "_id" }, "Calendars_id=" + calendarId, null, null);
}
else
{
cursor = resolver.query(eventsUri, new String[]{ "_id" }, "calendar_id=" + calendarId, null, null);
}
while(cursor.moveToNext())
{
long eventId = cursor.getLong(cursor.getColumnIndex("_id"));
resolver.delete(ContentUris.withAppendedId(eventsUri, eventId), null, null);
}
cursor.close();
}
The code you are using is deleting EVERY event: you need to save the ID of the event you create and only delete that one event. When you do this:
cr.insert(REMINDERS_URI, values);
change that to this:
Uri u = cr.insert(REMINDERS_URI, values);
This will save the URI of the event you create. You can then pass that URI into your deleteEvent method to only delete that one event, rather than all events.