Allows usage of iCalendar files with the Android calendar provider

Overview

Development tests Documentation

ical4android

ical4android is a library for Android that brings together iCalendar and Android. It's a framework for

  • parsing and generating iCalendar resources (using ical4j) from/into data classes that are compatible with the Android Calendar Provider and third-party task providers,
  • accessing the Android Calendar Provider (and third-party task providers) over a unified API.

It has been primarily developed for:

and is currently used as git submodule.

Generated KDoc: https://bitfireat.github.io/ical4android/

For questions, suggestions etc. use Github discussions. We're happy about contributions! In case of bigger changes, please let us know in the discussions before. Then make the changes in your own repository and send a pull request.

This software is not affiliated to, nor has it been authorized, sponsored or otherwise approved by Google LLC. Android is a trademark of Google LLC.

How to use

You can use ical4android as a git submodule or using jitpack.io:

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
dependencies {
    implementation 'com.github.bitfireAT:ical4android:
   
    '        // see tags for latest version, like 1.0, or use the latest commit ID from main branch
    //implementation 'com.github.bitfireAT:ical4android:main-SNAPSHOT'  // use it only for testing because it doesn't generate reproducible builds
}

   

Contact

bitfire web engineering GmbH
Florastraße 27
2540 Bad Vöslau, AUSTRIA

License

Copyright (C) Ricki Hirner and contributors.

This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GPL v3.

Comments
  • CI tests fail at testLargeTransactionManyRows

    CI tests fail at testLargeTransactionManyRows

    See https://github.com/bitfireAT/ical4android/runs/6677616922

    > Task :packageDebugAndroidTest
    > Task :createDebugAndroidTestApkListingFileRedirect
    [EmulatorConsole]: Failed to start Emulator console for 5554
    
    > Task :connectedDebugAndroidTest
    additionalTestOutput is not supported on this device running API level 28 because the additional test output directory could not be found
    Starting 400 tests on emulator-5554 - 9
    
    at.bitfire.ical4android.AndroidEventTest > testLargeTransactionManyRows[emulator-5554 - 9] FAILED 
    
    Tests on emulator-5554 - 9 failed: There was 1 failure(s).
    
    Test results saved as file:/__w/ical4android/ical4android/build/outputs/androidTest-results/connected/test-result.pb. Inspect these results in Android Studio by selecting Run > Import Tests From File from the menu bar and importing test-result.pb.
    

    Since the commit on 26 May 2022: https://github.com/bitfireAT/ical4android/commits/main

    Maybe this is not even related to the changes of the commit.

    bug 
    opened by rfc2822 8
  • Not syncing VTODO with Tasks application

    Not syncing VTODO with Tasks application

    Hi there. I'm currently facing a problem in which the tasks are not being synced with server and local application (Tasks). The platforms I'm using are:

    1. NextCloud server (I've tested The Good Cloud & Qloud providers),
    2. DAVx5 for synchronizing tasks,
    3. Tasks application as a client to see the tasks. All the synchronization works fine when I log in to my account for the first time using DAVx5. It syncs the task data, and Tasks would show them with the latest changes. But when I make any changes in the web service, then clicking on sync button inside DAVx5, and navigating to Tasks application, nothing is updated. The problem persists vise versa. Like, if I make any changes using Tasks and clicking on DAVx5's sync button , nothing would change in web service.

    I tried changing service provider but the problem was still existing, so it is NOT the server. I tried using Jtx Board to see if the problem exists. Surprisingly, the tasks were updating after any changes. So I am not completely sure if it's Tasks application's bug or DAVx5's. But I'm sure the synchronization between these two, are working fine for the first time and are not working perfectly for the afterward changes.

    opened by MohammadFakhraee 5
  • Ignore empty X-APPLE-CALENDAR-COLOR

    Ignore empty X-APPLE-CALENDAR-COLOR

    Hi,

    using ICSx⁵ I got the following exception

    length=0; index=0
    
    java.lang.StringIndexOutOfBoundsException: length=0; index=0
    	at java.lang.String.charAt(Native Method)
    	at android.graphics.Color.parseColor(Color.java:1384)
    	at at.bitfire.ical4android.Css3Color$Companion.colorFromString(Css3Color.kt:178)
    	at at.bitfire.icsdroid.ui.AddCalendarValidationFragment$ValidationModel$initialize$downloader$1.onSuccess(AddCalendarValidationFragment.kt:126)
    	at at.bitfire.icsdroid.CalendarFetcher.fetchNetwork$icsx5_62_2_0_2_standardRelease(CalendarFetcher.kt:155)
    	at at.bitfire.icsdroid.CalendarFetcher.run(CalendarFetcher.kt:46)
    	at java.lang.Thread.run(Thread.java:784)
    

    which I think might come from the line X-APPLE-CALENDAR-COLOR: (value is empty) in my ics-file.

    I suspect that Color.parseColor(…) not only throws IllegalArgumentException as caught in Css3Color line 189, but also StringIndexOutOfBoundsException for empty strings.

    If necessary I will try to assemble a minimum working example.

    Greetings Nmxcgeo

    enhancement 
    opened by nmxcgeo 4
  • reduce number of rows in testLargeTransactionManyRows (closes bitfireAT/ical4android#42)

    reduce number of rows in testLargeTransactionManyRows (closes bitfireAT/ical4android#42)

    In accumulation with all other tests testLargeTransactionManyRows exceeds the threshold of android binders we may send to the system ~(running the test solely on its own is not a problem)~.

    Without diving deeper into Android Binders and said threshold, reducing the amount of rows (attendees in testLargeTransactionManyRows) by a thousand seems to let the sending of bindings to the system stay below unknown threshold, ensuring all tests pass.

    opened by sunkup 4
  • Accept tasks with DUE=DTSTART

    Accept tasks with DUE=DTSTART

    See bitfireAT/davx5-ose#243. Proposed solution:

    As the DUE>DTSTART constraint is enforced by OpenTasks (which is not recommended anymore), we could drop DTSTARTs that are >= DUE only when OpenTasks is the tasks backend. So if jtx Board and tasks.org accept tasks with DTSTART=DUE, we could sync such tasks to those backends as they are. Then everything including the alarms should be retained. For OpenTasks, we keep everything as it is because it's legacy code and will be removed sooner or later anyway.

    Also relevant for @TechbeeAT @patrickunterwegs (jtx Board UI changes for DTSTART=DUE as discussed in chat).

    opened by rfc2822 3
  • Fix color parsing for empty strings

    Fix color parsing for empty strings

    This fixes an ICSx⁵ crash which I and some friends observed on a publicly shared Nextcloud calendar.

    Stack trace of the crash (provided in-app):

    length=0; index=0
    
    java.lang.StringIndexOutOfBoundsException: length=0; index=0
    	at java.lang.String.charAt(Native Method)
    	at android.graphics.Color.parseColor(Color.java:1384)
    	at at.bitfire.ical4android.Css3Color$Companion.colorFromString(Css3Color.kt:178)
    	at at.bitfire.icsdroid.ui.AddCalendarValidationFragment$ValidationModel$initialize$downloader$1.onSuccess(AddCalendarValidationFragment.kt:126)
    	at at.bitfire.icsdroid.CalendarFetcher.fetchNetwork$icsx5_62_2_0_2_standardRelease(CalendarFetcher.kt:155)
    	at at.bitfire.icsdroid.CalendarFetcher.run(CalendarFetcher.kt:46)
    	at java.lang.Thread.run(Thread.java:764)
    

    The problem seems to be an empty string for the color in the ICS file:

    BEGIN:VCALENDAR
    VERSION:2.0
    CALSCALE:GREGORIAN
    PRODID:-//SabreDAV//SabreDAV//EN
    X-WR-CALNAME:Nextcloudcalendarname (nextcloudusername)
    X-APPLE-CALENDAR-COLOR:
    REFRESH-INTERVAL;VALUE=DURATION:PT4H
    X-PUBLISHED-TTL:PT4H
    BEGIN:VTIMEZONE
    TZID:Europe/Berlin
    

    Disclaimer: I am not a kotlin or java programmer. Please let me know if the double catch clause is bad style, so that I can do it differently.

    opened by jomority 2
  • Drop RULES with UNTIL before DTSTART

    Drop RULES with UNTIL before DTSTART

    From time to time, events with an RRULE whose UNTIL is before the DTSTART of the event appear, like:

    DTSTART: 2022/05/31 13:00 RRULE: … UNTIL 2022/05/31 12:59

    Such events are invalid and sometimes cause problems when they're uploaded again to the server (because the server reject them, which is OK).

    Thus such RRULEs should be dropped, both when they're received from the server and when they're found in the calendar provider.

    enhancement 
    opened by rfc2822 2
  • Couldn't parse iCalendar / Unparseable date:

    Couldn't parse iCalendar / Unparseable date: ":20220331T084614Z"

    Caused by: java.text.ParseException: Unparseable date: ":20220331T084614Z"

    • All my events are unable to be parsed.
    • My calendar provider is posteo.de
    • Happend in ICSx5 app
    • Side note: My calendar URL does not end on .ics (unlike the example URL). Dunno if this could be a problem.

    Event example:

    BEGIN:VEVENT
    EXDATE;VALUE=DATE:20220101
    EXDATE;VALUE=DATE:20211001
    CREATED;VALUE=DATE-TIME:20211003T130823Z
    DTEND;VALUE=DATE:20211011
    DTSTART;VALUE=DATE:20211001
    TRANSP:TRANSPARENT
    DTSTAMP;VALUE=DATE-TIME:20220331T084614Z
    LAST-MODIFIED;VALUE=DATE-TIME:20220104T115808Z
    UID:3979A421-7245-4F51-9E72-F8DF0A1BD2BE
    URL;VALUE=URI:
    SUMMARY:<redacted>
    RRULE:FREQ=MONTHLY;INTERVAL=3;BYMONTHDAY=1
    SEQUENCE:0
    X-APPLE-TRAVEL-ADVISORY-BEHAVIOR::AUTOMATIC
    BEGIN:VALARM
    TRIGGER:-PT15H
    ATTACH;ENCODING=BASE64;FILENAME=attachment-not-shared.txt;VALUE=BINARY:<redacted>
    ACTION:AUDIO
    X-WR-ALARMUID::D8F053D3-C614-4FDB-A217-EE607C5750EC
    UID::D8F053D3-C614-4FDB-A217-EE607C5750EC
    X-APPLE-DEFAULT-ALARM::TRUE
    ACKNOWLEDGED::20220331T084614Z
    END:VALARM
    END:VEVENT
    

    Full stack trace:

    at.bitfire.ical4android.InvalidCalendarException: Couldn't parse iCalendar
     at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:81)
     at at.bitfire.ical4android.Event$Companion.eventsFromReader(Event.kt:81)
     at at.bitfire.icsdroid.ui.AddCalendarValidationFragment$ValidationModel$initialize$downloader$1.onSuccess(AddCalendarValidationFragment.kt:115)
     at at.bitfire.icsdroid.CalendarFetcher.fetchLocal$icsx5_62_2_0_2_standardRelease(CalendarFetcher.kt:114)
     at at.bitfire.icsdroid.CalendarFetcher.run(CalendarFetcher.kt:48)
     at java.lang.Thread.run(Thread.java:919)
    Caused by: net.fortuna.ical4j.data.ParserException: Error at line 63:Unparseable date: ":20220331T084614Z"
     at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:172)
     at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:197)
     at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:185)
     at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:79)
     ... 5 more
    Caused by: java.text.ParseException: Unparseable date: ":20220331T084614Z"
     at java.text.DateFormat.parse(DateFormat.java:362)
     at net.fortuna.ical4j.model.DateTime.setTime(DateTime.java:418)
     at net.fortuna.ical4j.model.DateTime.<init>(DateTime.java:349)
     at net.fortuna.ical4j.model.property.DateProperty.setValue(DateProperty.java:139)
     at net.fortuna.ical4j.model.property.Acknowledged.<init>(Acknowledged.java:124)
     at net.fortuna.ical4j.model.property.Acknowledged$Factory.createProperty(Acknowledged.java:158)
     at net.fortuna.ical4j.model.PropertyBuilder.build(PropertyBuilder.java:76)
     at net.fortuna.ical4j.data.DefaultContentHandler.endProperty(DefaultContentHandler.java:159)
     at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.parse(CalendarParserImpl.java:309)
     at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.access$1100(CalendarParserImpl.java:241)
     at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:226)
     at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.parse(CalendarParserImpl.java:446)
     at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.access$900(CalendarParserImpl.java:422)
     at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:224)
     at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.parse(CalendarParserImpl.java:446)
     at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.access$900(CalendarParserImpl.java:422)
     at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:224)
     at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendar(CalendarParserImpl.java:128)
     at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendarList(CalendarParserImpl.java:194)
     at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:163)
     ... 8 more
    

    Any help appreciated :)

    opened by paulHempel 2
  • Tasks: add tasks app package to PRODID

    Tasks: add tasks app package to PRODID

    Currently, we're adding the mutators (the calendar apps that edited an event) to the PRODID like this:

    # VEVENT
    PRODID:DAVx5/4.2.3.4-ose ical4j/3.2.5 (org.withouthat.acalendarplus)
    

    There's no equivalent for tasks and journals. I suggest to add the package name of the used tasks backend to the PRODID like this:

    # VTODO
    PRODID:DAVx5/4.2.3.4-ose ical4j/3.2.5 (tasks.app.here)
    
    enhancement 
    opened by rfc2822 0
  • Better separation of AndroidEvent <-> (iCalendar) Event

    Better separation of AndroidEvent <-> (iCalendar) Event

    ical4j comes with a time zone database that is used for its calculations and for instance to generate VTIMEZONEs which are then exported.

    However, Java/Android has its own database (which is used by the calendar provider and the ZoneId, java.util.TimeZone classes). We always need to know which times with time zone are in the "ical4j namespace" and which ones are in "Android namespace".

    There should be a proper separation and it should be documented and enforced.

    refactoring 
    opened by rfc2822 3
  • Android always expects RRULE UNTIL to be in UTC format

    Android always expects RRULE UNTIL to be in UTC format

    Currently, we insert RRULE with UNTIL as it comes from the event (as defined in RFC 5445).

    However, some code parts of the Android calendar provider seem to always expect UNTIL to be in UTC format, as specified in the obsolete RFC 2445.

    So RRULE UNTIL should always be converted to UTC before inserting it into the calendar provider. Not doing so might result in losing the last occurrence.

    Side note: ical4j parses UNTIL in the system default timezone and not in the DTSTART timezone. This may cause further problems…

    bug 
    opened by rfc2822 1
  • Tests should work under every system time zone

    Tests should work under every system time zone

    I noticed some tests fail when run in certain time zones. This is due to flipping dates when time of a DateTime object is close to midnight. For now I found the following tests fail with time zone America/New_York:

    • [ ] testRecurrenceSetsToAndroidString_TimeAlthoughAllDay
    • [ ] testRecurrenceSetsToAndroidString_Date
    • [ ] testHasUntilBeforeDtStart_DtStartDate_RRuleUntil_TimeBeforeDtStart_noTimezone
    opened by sunkup 0
  • recurrenceSetsToAndroidString, androidStringToRecurrenceSet: handle multiple entries separated by newline

    recurrenceSetsToAndroidString, androidStringToRecurrenceSet: handle multiple entries separated by newline

    • [ ] Check whether Android can have multiple entries in the recurrence set columns (RDATE, …), possibly with different time zones.
    • [ ] Handle these cases accordingly in recurrenceSetsToAndroidString
    • [ ] and androidStringToRecurrenceSet
    opened by rfc2822 0
Owner
bitfire web engineering
bitfire web engineering
Wrapper around the android Camera class that simplifies its usage

EasyCamera Wrapper around the android Camera class that simplifies its usage (read more about the process) Usage: // the surface where the preview wil

Bozhidar Bozhanov 641 Dec 29, 2022
A simple Android utils library to write any type of data into cache files and read them later.

CacheUtilsLibrary This is a simple Android utils library to write any type of data into cache files and then read them later, using Gson to serialize

Wesley Lin 134 Nov 25, 2022
A low intrusive, configurable android library that converts layout XML files into Java code to improve performance

qxml English 一个低侵入,可配置的 Android 库,用于将 layout xml 文件转换为 Java 代码以提高性能。 与X2C的对比 X2C: 使用注解处理器生成View类,使用时需要在类中添加注解,并替换setContentView方法,侵入性较强; 对于布局属性的支持不够完美

null 74 Oct 6, 2022
BinGait is a tool to disassemble and view java class files, developed by BinClub.

BinGait Tool to diassemble java class files created by x4e. Usage To run BinGait, run java -jar target/bingait-shadow.jar and BinGait will launch. If

null 18 Jul 7, 2022
Expirable Disk Lru Cache is a secure(with encryption) wrapper for [DiskLruCache](https://github.com/JakeWharton/DiskLruCache) that allows expiring of key/value pairs by specifying evictionTimeSpan. It has very simple API.

ExpirableDiskLruCache ExpirableDiskLruCache is a wrapper for DiskLruCache that allows expiring of key/value pairs by specifying evictionTimeSpan. It h

Vijay Rawat 24 Oct 3, 2022
This project is an add-on for the excellent J2V8 Project. It allows users to debug JS running in V8 using Chrome DevTools. Uses Stetho for communication with Chrome DevTools.

J2V8-Debugger This project is an add-on for the excellent J2V8 Project. It allows users to debug JS running in V8 using Chrome DevTools. Uses Stetho f

Alex Trotsenko 76 Jan 3, 2023
λRPC allows using code with high-order functions as a service

λRPC Simple native RPC with high order functions support. Inspired by @altavir and Communicator. λRPC allows using code with high-order functions as a

Andrey Stoyan 5 May 18, 2022
Android Shared preference wrapper than encrypts the values of Shared Preferences. It's not bullet proof security but rather a quick win for incrementally making your android app more secure.

Secure-preferences - Deprecated Please use EncryptedSharedPreferences from androidx.security in preferenced to secure-preference. (There are no active

Scott Alexander-Bown 1.5k Dec 24, 2022
Android library which makes it easy to handle the different obstacles while calling an API (Web Service) in Android App.

API Calling Flow API Calling Flow is a Android library which can help you to simplify handling different conditions while calling an API (Web Service)

Rohit Surwase 19 Nov 9, 2021
Gesture detector framework for multitouch handling on Android, based on Android's ScaleGestureDetector

Android Gesture Detectors Framework Introduction Since I was amazed Android has a ScaleGestureDetector since API level 8 but (still) no such thing as

null 1.1k Nov 30, 2022
Use Android as Rubber Ducky against another Android device

Use Android as Rubber Ducky against another Android device

null 1.4k Jan 9, 2023
Android Utilities Library build in kotlin Provide user 100 of pre defined method to create advanced native android app.

Android Utilities Library build in kotlin Provide user 100 of pre defined method to create advanced native android app.

Shahid Iqbal 4 Nov 29, 2022
A util for setting status bar style on Android App.

StatusBarUtil A util for setting status bar style on Android App. It can work above API 19(KitKat 4.4). 中文版点我 Sample Download StatusBarUtil-Demo Chang

Jaeger 8.8k Jan 6, 2023
A logger with a small, extensible API which provides utility on top of Android's normal Log class.

This is a logger with a small, extensible API which provides utility on top of Android's normal Log class. I copy this class into all the little apps

Jake Wharton 9.8k Dec 30, 2022
Java implementation of a Disk-based LRU cache which specifically targets Android compatibility.

Disk LRU Cache A cache that uses a bounded amount of space on a filesystem. Each cache entry has a string key and a fixed number of values. Each key m

Jake Wharton 5.7k Dec 31, 2022
a simple cache for android and java

ASimpleCache ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 1、它可以缓存什么东西? 普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 b

Michael Yang 3.7k Dec 14, 2022
gRPC and protocol buffers for Android, Kotlin, and Java.

Wire “A man got to have a code!” - Omar Little See the project website for documentation and APIs. As our teams and programs grow, the variety and vol

Square 3.9k Dec 31, 2022
✔️ Secure, simple key-value storage for Android

Hawk 2.0 Secure, simple key-value storage for android Important Note This version has no backward compatibility with Hawk 1+ versions. If you still wa

Orhan Obut 3.9k Dec 20, 2022
A robust native library loader for Android.

ReLinker A robust native library loader for Android. More information can be found in our blog post Min SDK: 9 JavaDoc Overview The Android PackageMan

Keepsafe 2.9k Dec 27, 2022