Files
agendula/docs/CONTENT_PROVIDER.md
T
Jean-Luc Makiolaandmakiolaj e7bf23e276
Beta — Codeberg pre-release / detect (push) Successful in 7s
Beta — Codeberg pre-release / beta (push) Skipped
Publish the own store through a read-only OpenTasks provider (#43) (#62)
In Own storage mode, Agendula now publishes its Room store as a ContentProvider that follows the OpenTasks contract. It serves `tasklists`, `tasks`, `instances` and `properties` (reminders and tags) at `<package>.tasks`, behind a dangerous-level `<package>.permission.READ_TASKS` that the user grants per app. An app that already reads OpenTasks or tasks.org only has to change the authority and the permission.

On a query, the provider lays the Room store out in OpenTasks' columns and loads that into an in-memory SQLite database, so a client's selection, arguments and sort order run as real SQL. The snapshot is rebuilt after a write, after a storage mode switch, or once it is an hour old, because instance ids and `distance_from_current` move with the clock. Observers on the authority get one notification per burst of changes. In External mode every table is empty.

Recurrence expansion moved out of `RoomTasksDataSource` into shared functions, so the app and the provider expand a series the same way.

`docs/CONTENT_PROVIDER.md` describes the contract for client developers, with the authority and permission for each build. README, CHANGELOG and the privacy policy mention the new permission.

Where this differs from the issue: the issue asked for read and write permissions, and this PR is read-only. Insert, update and delete throw. Accepting writes from other apps means deciding what happens to the fields Agendula keeps verbatim for CalDAV round-tripping, which was the issue's second open question, and that needs its own design. That is tracked in #63.

Closes #43

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/agendula/pulls/62
2026-10-15 13:25:48 +02:00

2.9 KiB

Reading Agendula's tasks from another app

When Agendula keeps tasks in its own database (the default storage mode), it publishes them through a read-only ContentProvider that follows the OpenTasks contract. An app that already reads OpenTasks or tasks.org can read Agendula by using a different authority and permission.

Authority de.jeanlucmakiola.agendula.tasks (offline build: de.jeanlucmakiola.agendula.offline.tasks)
Permission de.jeanlucmakiola.agendula.permission.READ_TASKS (offline build: de.jeanlucmakiola.agendula.offline.permission.READ_TASKS)
Protection level dangerous: request it at runtime
Package visibility add <provider android:authorities="de.jeanlucmakiola.agendula.tasks" /> to your <queries>

Both names are derived from the installed package name, so every build has its own and they can be installed side by side: the authority is <package>.tasks and the permission <package>.permission.READ_TASKS.

Build Package
Release de.jeanlucmakiola.agendula
Release, offline de.jeanlucmakiola.agendula.offline
Debug de.jeanlucmakiola.agendula.debug
Debug, offline de.jeanlucmakiola.agendula.offline.debug
Release test de.jeanlucmakiola.agendula.releasetest
Release test, offline de.jeanlucmakiola.agendula.offline.releasetest

Tables

URI Rows
content://<authority>/tasklists one per list
content://<authority>/tasks one per task; a modified occurrence of a recurring task is its own row with original_instance_id / original_instance_time set
content://<authority>/instances one per occurrence: recurring tasks are expanded up to one year back and two years ahead, and modified occurrences replace the ones they override
content://<authority>/properties reminders (vnd.android.cursor.item/alarm) and tags (vnd.android.cursor.item/category)

Each table also accepts /<id>. Column names, value encodings (epoch millis, all-day dates as UTC midnight, status, priority, class) and MIME types are the OpenTasks ones. selection, selectionArgs and sortOrder work as they do against OpenTasks.

Behaviour

  • Read-only. insert, update and delete throw UnsupportedOperationException.
  • Change notifications. Register a ContentObserver on content://<authority> with notifyForDescendants = true. It fires when tasks change or when the user switches storage mode.
  • External storage mode. When the user has Agendula work on top of OpenTasks or tasks.org, every table is empty. Read that provider directly.
  • Instance ids are not stable: as in OpenTasks they are reassigned when the data changes, and also hourly as the expansion window moves (observers are notified then too). Key on task_id plus instance_original_time.