Library / SDK
getodk/collect avatar
getodk/collect

ODK Collect is an offline-first Android form app, and its release process is the interesting part

ODK Collect is an Android app for filling out forms. It's been used to collect billions of data points in challenging environments around the world. Contribute and make the world a better place! ✨📋✨

796 stars1,435 forksKotlinNOASSERTION

At a glance

What is it?
ODK Collect is an Android application for filling out forms, built for resource-constrained environments with unreliable connectivity or power, and it renders forms written to the ODK XForms standard through the JavaRosa parser. It is developed in Kotlin, published on the Play Store, and its README documents a deliberate release cycle with betas, regression testing and a fourteen day quarantine on dependency updates.
Who is it for?
ODK Collect fits organisations running structured field data collection, from health surveys to land management, because it is designed for a device with no reliable network and a form standard that other ODK tools can consume.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Built for the case where the network is not there

ODK Collect is an Android app for filling out forms, and the README says it is designed to be used in resource-constrained environments with challenges such as unreliable connectivity or power infrastructure.

That single sentence explains most of the design decisions in the repository. The app is expected to run for days in a place with no signal, collecting data that must survive being closed, backgrounded, and the device being switched off, so the local database is the centre of the system rather than a cache. The repository layout shows the same emphasis. There is a db/ directory, a forms/ directory with a forms-test/ counterpart, an async/ directory, and entities/, metadata/, permissions/ and projects/ alongside them.

The hardware surface is broad and visible in the tree. There is geo/ and location/, maps/ with maplibre/ and google-maps/ as the two map providers, a selfie-camera/, an audio-recorder/ with audio-clips/, a printer/ for direct printing, and a qr-code/ module. There is a db/ and a mobile-device-management/ directory, which points at the enterprise side of the product where a central administrator configures devices in the field.

The primary language is Kotlin, and the topics list the field the project serves, with mhealth, global-health, global-development, social-impact and mobile-data-collection named alongside the technical ones such as android, java and xforms.

It is part of the wider ODK project, a free and open source set of tools that help organisations author, field and manage mobile data collection solutions, and the usage documentation is at docs.getodk.org/collect-intro.

A subset of XForms, parsed by JavaRosa

The rendering pipeline has one specification and one library, and knowing both tells you what a form can contain.

ODK Collect renders forms that are compliant with the ODK XForms standard, which the README describes as a subset of the XForms 1.1 standard with some extensions. The form parsing is done by the JavaRosa library, which Collect includes as a dependency.

So the input is XML describing a form, the parser is a separate project with its own repository, and the app is the presentation layer. That split is worth understanding before you design a form, because the subset is the constraint. A form written against the full XForms 1.1 specification may use constructs that ODK XForms does not include, and the failure would show up in the app rather than in a validator.

The repository is large, and the directory names are a good index of the feature set. Besides the ones already mentioned there is open-rosa/ for the OpenRosa protocol layer that lets a server push forms to devices, crash-handler/ and analytics/ for the reporting side, external-app/ for handing files to other applications, and forms-test/ and androidtest/ for the test suites, alongside a benchmarking/ directory and a service-test/ directory.

There is also a .hgtags file at the root, which is a leftover of the Mercurial era and a reminder of how long this code has been in service.

The release cycle: beta on the Play Store, then regression

The Release cycle section is the most detailed part of the README, and it reads like a process document because it is one.

Releases are planned to happen every two to three months, which is about four a year, and the stated goal is to balance the pace of delivery with keeping things stable for users while minimising the risk in each release. The work list lives in a backlog that the Collect team continually revises, and the majority of it is influenced by the priorities in the ODK roadmap.

The mechanics of a release are specific. Once the majority of high risk or visible work is done, a new beta is released to the Play Store by the person with the handle @lognaturel, and that beta is used for regression testing by the getodk/testers team. If problems are found, the release is blocked until fixes can be merged. Regression testing continues on the original beta build rather than a new one with fixes, unless the problems block the rest of testing. When the process completes, the same person pushes the releases to the Play Store following the signed release instructions.

Fixes to a previous release are merged to a release branch, with v2023.2.x given as the example, so that master stays available for the current release's work. A hotfix that also needs to land in the current release is merged in afterwards, generally as a single pull request for the whole hotfix release.

The net effect for a user is that the Play Store build is the supported artifact, the betas are tested by a dedicated team before they ship, and the branch layout means a field device can be kept on a known good version while new work continues on master.

Dependency updates wait fourteen days on purpose

There is a paragraph in the release cycle section about dependency updates that is worth reading closely, because it explains a policy that would otherwise look like an oversight.

At the beginning of each release cycle, the person with the handle @grzesiek2010 updates all dependencies that have compatible upgrades available and ensures the build targets the latest SDK. To see which dependencies have updates available, you run a Gradle task.

bash
./gradlew dependencyUpdates --no-parallel

What that task does is report available updates, and it only suggests stable versions that are at least fourteen days old. It never applies the updates and it never blocks a build.

The reason is spelled out. The main threat this guards against is a supply chain attack, in the form of a compromised maintainer account or a poisoned artefact published as a fresh release, which are typically spotted and yanked within days. A fourteen day quarantine keeps them out of the report before anyone adopts them, and requiring stable releases avoids the same risk from pre-release channels.

The cost is stated as well. A genuine bug fix is also held back for fourteen days, but that only delays its appearance in the report, since an urgent fix can still be bumped by hand at any time. The --no-parallel flag is required because the task does not support parallel project execution.

This is a small, well argued piece of supply chain hygiene, and it is the kind of decision that is usually made once and then forgotten.

master is a development branch, not a product

The README puts a warning near the top that is easy to miss and expensive to ignore.

Please note that the master branch reflects ongoing development and is not production-ready. The default branch of the repository is master, which is the branch a newcomer lands on when they clone, and the tagged releases are what a deployment should use.

The release history shows the same pattern in the version numbers. The three most recent tags are v2026.4.0-beta.1 from 2026-10-16, v2026.4.0-beta.0 from 2026-09-29 and v2026.3.5 from 2026-09-28, so a beta and a production release from the same month sit side by side.

For a user, the README is unambiguous. If you are looking to use ODK Collect, it strongly recommends the Play Store build, and current and previous production builds are in the Releases section.

For a developer, there are two build routes. Per-commit debug builds are on CircleCI, where you log in with your GitHub account, click the build you want, and find the APK in the Artifacts tab. The repository also carries a create-release.sh script, a check-size.sh script, a download-robolectric-deps.sh helper for the JVM based tests, a debug.keystore for local signing, and a secrets.gradle file for the release signing configuration.

The release branch structure, the beta in the Play Store, and the recommendation to use the store build are all parts of the same discipline: the shipping artifact is tested, and the development branch is explicitly not it.

Where ODK Collect is the wrong tool

Three situations rule it out.

The first is a general purpose survey app. ODK Collect is tied to a form standard, a server ecosystem and a data workflow, and a team that wants a drag and drop questionnaire with a results dashboard should look at a general survey product instead. The XForms subset is a constraint, and constraints are the point of a specialised tool, but they are constraints.

The second is a product that needs a release cadence of its own. The shipping path runs through a beta on the Play Store and a regression cycle with a dedicated tester team, and the release train is planned every two to three months. A company that needs to push a build to a specific customer on a specific date is working against that process rather than with it.

The third is a device platform other than Android. The badge says Android and the build system is Gradle with an androidshared/ directory, the androidtest/ suites and a Google Play Store release path.

For the work it does target, the design is right. A field worker in a place with one bar of signal needs an app that collects first and syncs later, needs to read a form written in a standard other tools understand, and needs to work on a cheap phone. The repository, with its offline database, its printer and camera support, its crash handler and its OpenRosa client, is the code that follows from those requirements.

Editorial conclusion

ODK Collect fits organisations running structured field data collection, from health surveys to land management, because it is designed for a device with no reliable network and a form standard that other ODK tools can consume. It is the wrong choice for a generic survey tool, because the XForms subset and the field data workflow are deliberate constraints rather than defaults, and the wrong choice for a team that needs its own release cadence, because the Play Store beta process is the shipping path. Before you build, read the release cycle section, and if you need an unreleased build remember that the master branch is explicitly not production ready while the Play Store build and the tagged releases are.

Frequently asked questions

What is ODK Collect and who uses it?

It is an Android app for filling out forms, designed for resource-constrained environments with unreliable connectivity or power infrastructure, and it is part of the ODK project, a free and open source set of tools for authoring, fielding and managing mobile data collection.

Which form standard does ODK Collect support?

It renders forms compliant with the ODK XForms standard, which is a subset of the XForms 1.1 standard with some extensions. The parsing is done by the JavaRosa library, which Collect includes as a dependency.

How often does ODK Collect release, and how are releases tested?

Releases are planned every two to three months, so roughly four a year. A beta is published to the Play Store and used for regression testing by the getodk/testers team, and a release is blocked until any problems found are fixed and merged.

Why does ODK Collect hold dependency updates back for fourteen days?

The dependencyUpdates Gradle task only suggests stable versions that are at least fourteen days old, because a compromised maintainer account or a poisoned artefact is typically spotted and yanked within days, so a short quarantine keeps it out of the report. An urgent fix can still be bumped by hand.

Can I run the master branch of ODK Collect in production?

No. The README states that the master branch reflects ongoing development and is not production-ready. For use, the Play Store build is strongly recommended, with current and previous production builds in the Releases section and per-commit debug builds on CircleCI.

Official sources

  1. getodk/collect on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/getodk-collect.svg)](https://hysenlabs.com/projects/getodk-collect)

Was this useful?