At ioki GmbH, we complement existing public transport with a demand-responsive transport (DRT) system. We equip our customers with the platform to provide on-demand transport services, including consulting, transport APIs, mobility intelligence and white-label apps (WLAs).
White labelling mobile applications is an integral process for customising on-demand solutions at ioki. We currently have 80 modules in-app and 70+ projects being released biweekly, a number that is ever-growing! With an increasing number of features and code, we need to separate responsibilities between the core feature-driven app and the white-label projects, while optimising for scalability.
In 2022, we gave time to our internal refactoring efforts to streamline our white label process, organize a clear project structure and improve app modularisation so the Android team could access modules faster and assign ownership for better workflows.
So how do we white-label Android apps?
With branding and feature customisation.
With customers all over Europe, ioki not only needs to support multiple languages, but also needs to allow customization of certain texts. Using a translation management system like Lokalise allows the team to eliminate localization for developers. With the support of the UI/UX team, we localize the product in parallel with the development cycle and speed up publishing with over-the-air updates.
The wide range of translations is then downloaded and uploaded to our CI/CD workflow while building the release variant for our white-label apps.
The UI experience: Colors, Drawables, Strings and Dark mode support
We have one codebase and work on a single app as we go along. Then we customise it for our customers by overriding strings, colors, drawables, and dark mode resources for every white-label app.
API Keys and Secrets and Identifiers
As we went along, we started to offer many options, making it hard to keep track of what was necessary for a particular customer and what was optional
We use an AppConfiguration file to opt-in to features, add a primary locale, provide technical configuration keys and identifiers, add deep link hosts and more.
But what’s so special about an AppConfiguration file?
With a base class defined for `AppConfiguration` and a sealed interface for `TechnicalConfigurations`, we restrict the hierarchy and carry out an exhaustive list of possible configurations. This way, we can be sure that we’ve dotted the i’s and crossed the t’s with every white-label app customer.
Ioki offers customers many features on the mobile app to choose from: multiple booking solutions, dynamic passenger options, alternate messaging and notification services, ride series booking, city ticket and more.
Before: We’ve split up every optional library into 3 libraries – `lib-feature`, `lib-default-implementation` and `lib-opt-in-implementation`.
- In `lib-feature`, we include only a minimal set of classes that allow us to differentiate between the feature implementation types and an interface that is implemented by the libraries that actually supply the Fragments.
- In `lib-default-implementation`, we have the generic implementation as a fallback for customers that do not use this feature.
- In `lib-opt-in-implementation`, we include the opt-in feature related implementation, with a lot more code and complexity.
We used to include all the dependencies of all the features for each customer. But with an increasing number of features, we needed to handpick dependencies as needed with the features that have been opted into.
In the Android team, we have core members who work on features and project implementation members who work on white-label apps. By adding a CODEOWNERS file, we allocate the responsibility for the features and libraries that are customer related. This way, developer teams are automatically requested for review when a team member opens a pull request that modifies code that the team owns.
We’re constantly evolving our processes to overcome present problems and improving as we go along. Find out what else we’re up to at ioki.engineering!