Medication management can become complicated when someone needs to track multiple medicines, follow different schedules, and maintain a reliable history of doses.
To address this problem, I developed Doseleaf, an offline-first Android application designed to make medicine scheduling and medication record-keeping more organised.
Doseleaf is a product of Wafyro Software, developed by Afee Muhammod Wafy.
The project focuses on native Android development, local data persistence, scheduled reminders, and practical data-management workflows.
Explore Doseleaf:
- Website: doseleaf.amwafy.xyz
- Source code: GitHub Repository
What Is Doseleaf?
Doseleaf is a native Android application built with Kotlin and Jetpack Compose. It provides a central place to manage medicines, organise schedules, maintain dose history, and handle related records.
The application includes:
- Medicine creation and editing
- Multiple daily reminder times
- Family profiles for organising medication records
- Dose history with Taken and Skip actions
- Reminder notifications and alarm interactions
- Medicine recovery through a Recycle Bin
- Local JSON backup and restore
- CSV dose-history export and PDF reports
- Inventory management and expiry-date handling
One of the core design goals is to keep the main medication-management workflow local-first, without requiring a backend account for ordinary use.
Tech Stack
Doseleaf uses native Android technologies rather than a cross-platform UI framework.
| Technology | Purpose |
|---|---|
| Kotlin | Primary programming language |
| Jetpack Compose | Declarative UI |
| Material 3 | UI components and visual design |
| Room | Structured local database |
| SQLite | Persistent data storage |
| Kotlin Coroutines and Flow | Asynchronous operations and observable state |
| Android AlarmManager | Scheduled reminders |
| BroadcastReceiver | Reminder events and system broadcasts |
| DataStore Preferences | Preference storage |
| Storage Access Framework | User-initiated file export and restore |
| FileProvider | Controlled sharing of app-managed files |
The project targets Android SDK 35, supports Android API 26 and above, and uses Java 17 compatibility.
Architecture: A Local-First Android Application
Doseleaf combines three main areas of responsibility.
1. UI layer
Jetpack Compose renders the application interface. The main UI entry point is DoseleafApp.kt, which contains the application navigation, screen composables, and DoseleafViewModel.
2. Data layer
Room provides structured persistence through entities and Data Access Objects (DAOs).
The database includes five entity types:
FamilyProfileEntityMedicineEntityMedicineScheduleEntityDoseLogEntityInventoryEntity
These represent family profiles, medicines, schedules, dose history, and inventory records.
3. Android integration layer
Dedicated components handle reminder scheduling, notification delivery, alarm interactions, and restoration of scheduled reminders following device reboot or relevant system time changes.
Keeping these responsibilities organised makes the codebase easier to reason about and maintain.
Designing the Database
Medication management involves more than storing medicine names and reminder times.
The application must associate medicines with profiles, support multiple schedules, preserve historical activity, and handle deletion and restoration.
Doseleaf separates medicine records from schedule records. A single medicine can have multiple associated schedule entries, allowing different reminder times without duplicating the medicine itself.
Dose history is stored separately in dose_logs. The log entity also stores a medicine-name snapshot, helping preserve historical context when the current medicine record changes.
The database is currently at schema version 5 and includes explicit migrations from earlier versions.
This highlights an important lesson in Android development: database changes must account for existing installations and their stored data, not just the latest application schema.
Implementing Medication Reminders
Reminder reliability is one of the most interesting engineering challenges in Doseleaf.
The application uses Android's AlarmManager to request scheduled reminder events. The main scheduling logic lives in ReminderScheduler.kt, while ReminderReceiver.kt handles reminder delivery.
The general workflow is:
- Read the enabled schedule entries from the local database.
- Calculate the next occurrence for each schedule.
- Create a
PendingIntentassociated with the relevant medicine and schedule. - Request an exact alarm when the required access is available.
- Fall back to an inexact alarm when exact-alarm access is unavailable.
- Handle the event and expose the available dose actions.
The project also includes a BootReceiver to handle device reboot and system time or time-zone changes.
Android's background execution policies make this more complicated than simply scheduling a callback. Exact-alarm access, notification permissions, battery-management behaviour, and device-specific restrictions can all affect the result.
Doseleaf includes fallback scheduling behaviour, but reminder delivery still requires validation across supported Android versions and physical devices.
Preventing Duplicate Dose Records
A notification action can be triggered more than once. Users may tap repeatedly, or multiple events may attempt to record the same scheduled occurrence.
Doseleaf uses a coroutine Mutex around dose logging and checks existing records before inserting another entry for the same medicine and scheduled timestamp.
The objective is to make repeated actions idempotent for a scheduled occurrence.
This is a useful general engineering principle: preventing duplicate operations requires attention to the persistence layer, not merely disabling a UI button.
Further automated testing is needed to establish the behaviour under concurrent events, process recreation, and other edge cases.
Family Profiles and Data Integrity
Doseleaf supports multiple family profiles to organise medication records by person.
The default profile is protected against deletion. When another profile is deleted, the application cancels the associated medicine reminders, processes related medicines through its deletion workflow, and retains dose history.
The Recycle Bin provides a recovery path before permanent deletion.
These workflows illustrate why deleting a database record is rarely an isolated operation. Related records, scheduled alarms, and historical data must be considered together.
Backup, Restore, and Export
Local-first applications also need a practical way to protect and retrieve user data.
Doseleaf supports:
- JSON backup and restore
- CSV dose-history export
- Date-range PDF reports
The JSON backup includes profiles, medicines, schedules, dose logs, and inventory records. The restore implementation validates the backup format, supported schema versions, and important relationships before replacing database contents within a Room transaction.
Prescription-photo data can also be embedded in a backup when the source file is accessible and satisfies the implementation's size limit.
For exporting and restoring files, the application uses Android's document APIs, allowing users to choose an available destination. A compatible cloud-storage document provider may be used as a destination, but this is manual file export rather than automatic cloud synchronisation.
Backup and restore workflows deserve careful testing because malformed files, incompatible versions, and interrupted operations can threaten data integrity.
Engineering Lessons from Doseleaf
Building Doseleaf brings together several practical Android engineering concerns.
Data persistence requires lifecycle planning. Schema migrations, historical records, deletion, restoration, and backup compatibility must work together.
Background execution is platform-dependent. Android APIs provide mechanisms for requesting scheduled work, but permissions and operating-system policies influence delivery.
Duplicate actions are data-integrity problems. A reliable solution must consider concurrent operations and existing database records.
Offline-first does not eliminate data-loss risks. Local persistence reduces dependence on remote services, but backup and restore become particularly important.
Implemented does not automatically mean verified. A feature's source code, successful builds, automated tests, and real-device behaviour are different stages of engineering.
These considerations have shaped how I approach application architecture and reliability.
Current Status and Areas for Improvement
Doseleaf is an ongoing development project. The current source snapshot has not yet been verified through a complete successful build and comprehensive real-device QA cycle.
Important next steps include:
- Validating reminder delivery and reboot restoration across supported Android versions
- Testing notification and exact-alarm permission flows
- Expanding automated tests for database operations and duplicate dose actions
- Testing database migrations against existing installations
- Strengthening backup and restore failure handling
- Completing and validating Bangla localisation
- Testing battery-management behaviour across device manufacturers
Doseleaf is intended for medication scheduling and record-keeping. It does not determine medically appropriate doses or replace professional medical advice.
About Wafyro Software
Wafyro Software is the product organisation behind Doseleaf.
Doseleaf is developed by Afee Muhammod Wafy, with a focus on native Android engineering, maintainable architecture, and practical user-facing software.
You can explore the project through the following official links:
- Product website: https://doseleaf.amwafy.xyz
- GitHub repository: https://github.com/afeemuhammodwafy1/doseleaf
The project is licensed under the MIT License.
Feedback, bug reports, and contributions that improve reliability, maintainability, accessibility, and user experience are welcome.
When reporting issues, please include relevant technical details such as the Android version, device manufacturer, and error logs. Avoid sharing real prescriptions, personal health records, or identifying patient information in public issues.
What's Next?
The next priorities are expanding automated test coverage, validating reminder behaviour on physical devices, strengthening database and restore workflows, and completing localisation.
I would particularly appreciate feedback from Android developers who have worked with AlarmManager, notification permissions, Room migrations, and offline-first architectures.
If you have built an application with similar constraints, what engineering challenges did you find most difficult?
You can explore Doseleaf and follow its development here:
Website: doseleaf.amwafy.xyz
Source code: github.com/afeemuhammodwafy1/doseleaf
Top comments (0)