Botanic Gardens of Sydney Mobile App
Written by
Jacob Colyvan
Published on 25 July 2024
The Research Centre for Ecosystem Resilience (ReCER) at the Botanic Gardens of Sydney applies scientific research and innovative technology to understand the factors which impact the distribution of plant species. ReCER gathers and maintains plant samples across a range of ecosystems and provides a database of genetic information about plant species in specific biomes. This knowledge infrastructure helps to ensure greater genetic diversity and resilience of restored ecosystems and better understanding of intact ecosystems to support conservation work.
In 2021, we took on the maintenance and development of the Restore & Renew database system. This web-based application allows researchers to catalogue and query the whole database of genetic plant samples. The information available in the database about those samples is recorded in the field by researchers using a mobile field collection application which had been developed internally by former staff at ReCER. The Restore & Renew database was originally designed and developed by our friends at Small Multiples.
ReCER built the mobile field collection app to replace a much more onerous process of taking field notes and then typing them into a spreadsheet back in the office. The app reduces errors, reduces the time to enter data after fieldwork and allows researchers to spend more time on data analyses and developing new ideas.
The more accurate the data, the less time ReCER staff have to spend tidying it up post field work – which, we gather, used to be quite a lot of work.
By making the data collection app freely available, has also allowed the Centre to receive data in the correct format from other researchers outside their team.
The data stored in the database also feeds other ReCER tools which provide crucial information for practitioners to consider when sourcing material for restoration. So it’s important for the database to be up-to-date and correct. This makes both the mobile field collection app and the web-based database crucial systems to support the project.
By early 2022, the Research Centre had found itself without any internal resources to maintain the mobile app and the app had entered the early stages of decay. Synchronising the app with the database had stopped working and other bugs couldn’t be fixed. The app stores were starting to warn that the app would soon be dropped. Something had to be done.
Because we were already working with staff at the Centre on the web-based database, they approached us to ask if we would consider rebuilding the mobile app on more contemporary technology. Since it gave us the opportunity to refine the whole data chain from field observations to the database we were already working with, we were excited to say yes.
About the ReCER Field Collection Application
The Field Collection app was originally developed for field researchers from ReCER, but it had also become popular with other collecting teams both within the Australian Institute of Botanical Science and beyond.
The app lets researchers log information about a genetic sample (or other) at the point of collection:
- Information about the collection site – location, soil type, people present, type of habitat, disturbance (eg fire), landform, aspect
- Species present at the site – taxon (infraspecific - subspecies, variety, form), juvenile/adult population, native or not, confidence, abundance
- For each sample – what type of sample, specific location, sample id
Data about samples is always connected to a site (or collection point) because the focus of ReCER’s research is species and ecosystem genetic diversity. Multiple samples from multiple species are often collected at a single site. Therefore site data is recorded and linked to all the many samples collected at this point. This saves time and lets them optimise sample collection.
Because field work often happens in quite remote areas, the app needs to function disconnected from the mobile network, in which case it saves entered data locally on the device, and then allows exporting of that data when it reconnects to a data network.
When a researcher collects a sample, the sample is placed in a small envelope with a pre-printed barcode on it. The barcode then acts as the ID for the sample.
So as well as manually entering data, the app needs to be able to gather accurate positioning data from the mobile device’s GPS to record the physical location of the collection site and to scan those barcodes to tie the physical sample with the data record.
Different user groups
The core requirements for the app were that it support the ReCER field researchers who have some needs for data integrity specific to their work:
- required fields
- data validation on some fields
- controlled vocabularies (for places and species etc )
The app has to do its best to make sure that the data which gets into the database is of high quality.
However, the app also has to be usable by researchers in other institutions and general collectors – both groups were users of the legacy app and the team would like to keep supporting them.
To support both ReCER team members and other users, we implemented two login paths:
- ReCER Login:
This path requires a Restore and Renew login, managed using Django and Django REST framework. It includes the extra validation needed by the collecting team, along with controlled vocabularies. - Local Login:
This path is for general collectors and researchers from other institutions. It only requires a name and email, which are used for the export of data to CSV (comma-separated values file).
{/* Autocomplete dropdown should only display for RnR users */}
{isRnRUser ? (
setSpeciesNameByType(item as Taxon)}
inputEnabled={inputEnabled}
isAccepted={speciesIsAccepted}
/>
) : (
)}
Development Approach
Over a few collaborative sessions between our team and the ReCER team we realised that it wasn’t appropriate to use the previous mobile app as a sort of specification for the new app. While the previous app served its purpose well, the team had realised some limitations after using it for a few years and they had a lot of ideas about how to improve it.
So we coached the team on how to write User Stories and – in conversation with other colleagues – they generated a couple of dozen quite quickly. From there we used a classic “iterative approach” to implementing the stories and therefore discovering the actual scope.
The iterative approach is simple and logical:
- the client and developers select a set of user stories to get started with,
- the dev team builds solutions for those,
- then the client tests the solutions and the devs fix anything that needs fixing
- If necessary, the client adds new user stories to the list
- Repeat until done
Most of us (even developers!) find it difficult to map out all the things an application should do before we start a project. One of the significant insights of the Agile movement was that it’s much easier to figure out what else software should do once you get to use it doing the things you thought it should do at the start.
This approach worked really well for this project – it gave the ReCER team a framework for sharing early releases with their wider team, allowed us to gather a more robust set of requirements and to cooperate to make sure what we were building stayed on the right trajectory to get a working app within the available budget.
As you can probably tell, it also creates a very collaborative process – quite quickly you stop thinking about “dev team” and “client team” and it just becomes “the team”.
Quality assurance becomes a shared responsibility between the client and the developers – that’s step 3 in that list above.
Choosing the technology stack
Technical Content Warning: If you’re a developer, this section is for you. If you’re not, you might want to skip down to “What did we learn?”
Our primary business is web application development. We’ve done some mobile development, but little enough that we don’t have a standard tech stack for mobile projects. We wanted to make sure we chose an option that would deliver a good result for the client and also be something we could maintain easily enough for a few years.
The technology had to support both Android and iOS.
Doing it as a Progressive Web App was appealing but that introduces a lot of potential difficulties with users using different browsers and different versions.
The app had to be able to access the camera to read barcodes and the GPS for location information. Current browsers on most mobile devices would support geolocation and camera access, but older browsers might not.
We considered:
- Platform-native versions for Android and iOS
- A cross-platform version using Flutter
- A cross-platform version using React Native
Ultimately, after a lot of research, we decided on React Native, partly because we already use React on a lot of projects. Still this would be our first React Native project, so we proceeded carefully forward.
Working out state management was tough – we had to figure out the right structure to match the existing export process and integrate seamlessly with the database on import. Ensuring robust state management was crucial to handle evolving specifications and maintain data integrity throughout the app.
Building automated testing for the user interface is also pretty challenging with React Native – you have to mockup the state, the actions, stub some libraries; it’s a lot of effort. Eventually, we focused mostly on building tests for data integrity. In the end, for this project, that’s actually the most important factor.
… And the winner is…
After careful research we went with the following tech stack:
- React Native - Provided a cross-platform mobile solution, ensuring a seamless experience on both iOS and Android devices.
- Expo - Streamlined the development process, builds, and deployments, making it easier to manage versioning, updates, and releases.
- React Native Elements - This component library facilitated consistent UI design and improved the development speed.
- React Hook Form - Simplified form building and validation, crucial for ensuring data integrity in the field.
- Django Backend and Django REST Framework - Enabled robust data handling and seamless integration with our existing systems.
- Redux toolkit and redux-persist - Ensured effective state management and persistence of state in storage, even when offline.
- Sentry - Provides application monitoring and logging, helping us quickly identify and fix issues.
- Jest - Facilitated rigorous testing, particularly focusing on data integrity.
- TypeScript - Enhanced code quality and maintainability with strong typing.
Performance and Scalability
Builds/Deployments: Expo made managing builds, deployments, and versioning relatively easy. It provided a unified workflow for both iOS and Android, allowing us to push updates seamlessly.
Scalability: As most data is stored on the device and downloads are handled via app stores, the app can easily support a high volume of users. The only potential bottleneck is our Django container that handles exporting data and managing controlled vocabularies for logged in users, but our setup with Django as the API allows for handling these tasks efficiently, even under high load.
State Management: By figuring out the exact specification, we settled on a state setup that could handle large amounts of data being added and removed, ensuring smooth performance, scalability and data integrity.
const handleExportPress = async (uploadAllOrNew: "all" | "new") => {
// confirm lock if user is RnR and uploading new
if (isRnRUser && uploadAllOrNew === "new") {
await confirmLockEvents();
return null;
}
if (uploadAllOrNew === "all") setAllUploadInProgress(true);
else if (uploadAllOrNew === "new") setNewUploadInProgress(true);
const uploadSuccessful = await dispatch(handleExport(uploadAllOrNew));
// Set a 1s timeout [because it feels better]
setUploadTimeout(uploadSuccessful, uploadAllOrNew);
};
Cross-platform device accuracy
This is where the difference between developing for the web and developing for mobile really stood out. Although React Native gives you an abstraction on the device peripherals, there are still a number of specific challenges to address.
Location
We faced quite a few issues with getting the same accuracy from both platforms when we accessed geo-location data. Android and iOS handle geolocation differently, leading to inconsistencies in location accuracy. We found that device accuracy can operate under a surprisingly large margin of error. To address this, we had to try several different settings and calibration methods to ensure reliable and precise geolocation across all devices.
Interestingly, we discovered that apps like Google Maps use more than just raw device location data to provide accurate location estimations. They incorporate additional data sources for better precision. We have future plans to migrate all maps within our app to use the Google Maps service for location, but for now, we're relying on raw device GPS data.
Barcode scanning
Getting a phone camera to reliably read a barcode was also surprisingly difficult. Different devices have varying camera quality and barcode scanning capabilities, which affected the app's performance.
We used a package provided by Expo to handle barcode scanning and added a guideline into the UI to help users position the barcode correctly, significantly improving scanning accuracy and reliability under various conditions.
A couple of very useful barcode features that evolved through iteration – which weren’t obvious when we started –
- When a user is a ReCER member, they can define that barcodes had to be within a certain specification – which makes it easier to detect a bad scan or use of the wrong barcode
- If a barcode was already scanned once, the app will warn you
export const checkBarcodeFitsNSWFormat = (barcodeString: string | null) => {
// If empty lets count it as valid as we're handling the case of all
// barcodes being empty in validateBarcodeLocally
if (!barcodeString) return true;
// Test string matches "NSW" followed by 7 or more digits (0-9)
const NSWregex = /^NSW[0-9]{7,}$/;
const barcodeValidatedStatus = NSWregex.test(barcodeString);
if (!barcodeValidatedStatus) return false;
return true;
}
What did we learn?
It’s easy to write an article to make it sound like we are so clever we never get anything wrong. Hindsight is magical. Instead, we think it’s better to try to document some of the “hard lessons” which we only learned by making mistakes (or very narrowly avoiding them).
Make tech choices that support the project long-term
It took us quite a while to decide on the development framework as a whole. There are a lot of promising choices, but each one locks you into downstream choices, so evaluating all that before starting is difficult. In the end, we decided the core principle for us had to be that tech stack choices should not stretch the business too much. In other words – how long would it take someone new to the project to get up to speed? If it’s too difficult for other developers to contribute to the project or take it over in future, then it’s a net negative. We had a fair bit of experience with React, so React Native (versus two versions in native code or another cross-platform framework) seemed the choice that respected this principle.
It’s all trade-offs. Make appropriate trade-offs
In any coding project, but especially when developing for mobile, you have to manage trade-offs between speed/efficiency, bundle size, data integrity, and development time. Some examples from this project:
- To use Expo or not – bundle size/efficiency vs development time.
- To use Flutter or React Native – flexibility and performance vs familiarity and ease of integration..
- How to persist and manage state/local app data – consistency and reliability vs complexity and performance.
There is no “right choice” or “best choice”, there’s just the trade-offs that are most effective for the project, the current team and the client’s needs.
Pay a lot of attention to getting complex data models right
Lots of applications will have fairly simple data – a few structured types with a few relationships. But some, like this one, will have very complicated structures in the data and it can take a lot of work and a lot of asking questions and listening carefully to even understand what those structures are and what they mean to the client. Some complexity in the client’s context won’t matter as much in the code, but some will – don’t confuse the finger pointing at the moon for the moon itself.
It will save a lot of time to really iron out the details of the data and the relationships before getting into development. This helps structure tests – especially tests for data integrity (which are core for this project).
If you haven’t done it before, do a “research spike” before you estimate
Estimating effort for a feature or project you’ve never done before is very error-prone. Doing a quick spike – a short, focused prototype – can help get a feel for what’s involved. This makes it easier to figure out the complexities and give a more realistic estimate.
Anticipate that dealing with the App Store will take some time
Apple does not make it easy to launch an app or app version through the App Store and, while that’s probably a good thing for the user, you should anticipate taking some time to prepare the necessary documentation, answer the questions and wait for approvals. It’s not fast. Start early.
Testing a React Native UI is not an easy task
You have to mockup the internal state, actions, and different libraries. When writing tests starts to be a real bottleneck, it’s better to narrow down to the most important parts to test (in this case data integrity when updating the state) and focus most of your effort on them.
Developing for mobile is a completely different task to developing a web application
When you say it like that, it sounds obvious, but the sheer amount of extra things to consider took us a little by surprise. For example: You can get native access to device peripherals (GPS, camera for barcodes); but different devices on different platforms produce very different results. It’s genuinely fun and exciting, but you need to be prepared to solve lots of new problems.
Final thoughts
ReCER is a great group of people doing really significant work to ensure the future viability of Australia’s ecosystems in a period of significant ecosystem disruption. We felt really privileged to get to work on this project and to get to know their work in more depth.
As you can tell from this article we learned a lot - both about botany and plant genetics and about mobile app development. The final product has improved the data integrity of the genetics database and successfully replaced the old mobile app with something that does the job even better and is more maintainable and usable.
We hope this article provides some helpful information to other developers considering a React Native project or mobile development in general.
If you are contemplating hiring some developers for a complex and interesting project, get in touch for a chat and we can help you work out how to approach it.
We want to acknowledge the ReCER team, especially Marlien Van Der Merwe, Samantha Yap, Patrick Fahey and Maurizio Rossetto for their support of this project and for the work they’re doing on behalf of us all.
References
- You can read more about ReCER’s work and why it matters here
- Small Multiples - original developers of the sample database application
- https://recer.org.au/recer-field-collection-app/ – the Gardens page about the app with download links