📜 ⬆️ ⬇️

Android Calendar API


This article will focus on using the undocumented API to work with the standard Android calendar. I did not find any articles in Russian on this topic, and in English there are only a few posts with outdated data. Who is interested - under cat.

What for!?


I was faced with such a task when I wrote an application for drawing up my university timetable. It is convenient to have your schedule separately, and even the standard calendar does not support the repetition of events after one week, which is necessary for a two-week (even / odd) schedule.
The fix idea was a function of the application that will allow you to “fill in” the calendar entered by the Android schedule. The advantages are obvious: synchronization with Google Calendar from google (sorry for the tautology), built-in calendar widgets (this widget from HTC Sense is very good) and a mountain of third-party widgets that even show the next event, even the week load, etc. This is where you need to work with the Android calendar.

Using an undocumented API is BAD! Pnyatnenko?



Is it really necessary to use an undocumented API to solve this obvious problem? The answer is no. The most correct method is to use the Google Calendar API , which I advise you to do in your workings out.

But the “right” method imposes a number of restrictions:
• Do not use in the absence of an Internet connection;
• Synchronization is required after filling in the calendar;
• The data (and there are quite a few of them when filling in the whole year) go to the server and then go back in synchronization, which obviously increases traffic twice.
')
In my opinion, it is much more convenient to use the offline version of the calendar, which, at any opportunity, can be synchronized with Google Calendar. Unfortunately google did not take care of the developers for Android and did not publish the official API, but to our joy, the Android source codes are open and smart people have long found the magic URI content providers.

We ask the user for permission to work with the calendar.



Paradox. There is no API, but there are permissions in the documentation. All you have to do is add them to your AndroidManifest.xml .

<uses-permission android:name="android.permission.READ_CALENDAR"> </uses-permission> <uses-permission android:name="android.permission.WRITE_CALENDAR"> </uses-permission> 

Uniform Resource Identifier or in Russian - URI


To use the Android calendar, we must contact its content provider at a specific URI. To our chagrin, this URI is different in different versions of the OS and may well change in the following (the cost of using an undocumented API). But the problem is solved.
For Froyo [2.2] and most likely for the next versions - content: //com.android.calendar/calendars .
For versions <2.2 - content: // calendar / calendars .
As you can see, everything is not so bad. You can determine the system version and use the corresponding URI, but I went the other way. See if there is any URI for <2.2 and if there is no one there, then I use the rest.

 // Calendar URI before 2.2 Uri calendars = Uri.parse("content://calendar/calendars"); Cursor managedCursor = this.managedQuery(calendars, new String[] { "_id", "name" }, null, null, null); if(managedCursor == null || managedCursor.getCount() == 0) { // 2.2 (Froyo) } else { // < 2.2 } 

We assume that the received URI.

We receive the list of calendars


For users of Google Calendar is not necessary to explain, but for the rest I will explain. A shared calendar consists of one or more smaller calendars, which can vary in color markers. Usually it is something like “personal”, “work”, “study”, etc. You can create such calendars only on the Googlekalander website, in the Android itself, this cannot be done using standard tools.
To add events we need to know the calendar ID. To perform this task, we use the construction from the previous paragraph.

 String[] projection = new String[] { "_id", "name" }; Cursor managedCursor = this.managedQuery(URI, projection, null, null, null); if (managedCursor != null && managedCursor.moveToFirst()) { String calName; String calID; int nameColumn = managedCursor.getColumnIndex("name"); int idColumn = managedCursor.getColumnIndex("_id"); do { calName = managedCursor.getString(nameColumn); calID = managedCursor.getString(idColumn); if (calName != null) // … UI } while (managedCursor.moveToNext()); managedCursor.close(); } 

Now the resulting set of names can be displayed in the interface and allow the user to select.

Add an event


Here work with a calendar occurs, as well as with any other content provider. This can be read in the documentation .

 ContentValues event = new ContentValues(); event.put("calendar_id", calID); // ID     event.put("title", title); //   event.put("description", desc); //   event.put("eventLocation", loc); //   event.put("dtstart", start); //   event.put("dtend", end); //   eventsURI=Uri.parse(URI + “/events"); this.getContentResolver().insert(eventsURI, event); 

Let's talk about the event fields. I advise you to use the description field to indicate the event. Using this field, then it will be possible to delete in a crowd all events created by your program. Fields of the name, description and location are string. We should also mention the time fields. These fields have the type long, and the values ​​of these fields can be generated, for example, by the following function.

 public static long pickDate(int year, int month, int day, int hour, int minute) { Calendar rightNow = Calendar.getInstance(); int timeShift = rightNow.get(Calendar.ZONE_OFFSET); return Date.UTC(year - 1900, month, day, hour - (timeShift / 3600000), minute, 0); } 

With it, I think, you will understand yourself, I will only note that it takes into account the current time zone.

Remove event


To delete a message by ID, add it to the URI.

 //eventsURI = URI + events/ uri = ContentUris.withAppendedId(eventsURI, EVENT_ID); this.getContentResolver().delete(uri, null, null); 

To delete by other fields, you can use the cursor to pull out all the events, as we did with the calendars, and then selectively delete them by ID.

Conclusion


In conclusion, once again I remind you that you use it at your own peril and risk. During the development, I once wrote a wrong URI and my phone every time I started syncing started to generate an error (corrected deleting information from the calendar at all).
Another nuisance is that there is no calendar in the emulator, so the above cannot be repeated on it.
And quite in conclusion. I can not use the opportunity to promote my application, which was discussed in the article. You can find it in the market called uTimetable .




And absolutely at the end I would like to ask the habbeast students: What format do you have at the university (one / two weeks) and how are these weeks called if they are two - even / odd or otherwise? Also interested in foreign universities.

Source: https://habr.com/ru/post/108339/


All Articles