This summer, we decided to architect and implement a mobile app accommodating the e-learning platform of one of our clients, troodi. We have chosen the Flutter framework, which allowed us to rapidly build a production-grade app within two weeks, ready to be deployed on both the iOS and Google Play app stores.
During the course of the development of the e-learning platform troodi, where customers can consume high-quality digital learning programs involving media ranging from worksheets to educational videos, it occured to us that a mobile app might be the perfect addition to their portfolio - considering the rising popularity of remote and on the go work culture, it was standing to reason that users might want to access and view their content on their mobile devices as well.
At dyve, we have many years of experience building mobile apps using both native platform tools/environments and various frameworks. Nowadays, we consider Flutter one of the best options when fast turnover and a near native end-user experience are paramount to the project - it allows us to concentrate engineering resources on a shared code base written in the Dart programming language and to target a variety of platforms (iOS, Android, macOS, Linux, Windows, and more).
Requirements
Since the app was aimed at an audience that likely would not be able to enjoy a stable internet connection (if at all) when using their mobile devices - say, on a train or plane ride - we established that one of the main requirements for the app was offline capability. A user should be allowed to preload content, such as videos, to their devices in order to consume them later, akin to the implementations of popular streaming platforms.
The app would also need to implement authentication interfacing with the existing troodi platform, since authorization is required to access most media.
In addition, the solution would also need to keep track of activities such as videos watched. This information is necessary for the troodi platform to record progress of participation in education programs, and must be synchronized whenever the user has a functioning internet connection.
Implementation
I’d like to share some interesting details regarding our implementation that we have come up with:
-
JSON annotation: we have extended the troodi platform with a minimal JSON API that the Flutter app interfaces with. To be able to enjoy the full benefits of Dart and its type system, we have employed
json_serializable
and used it to declare the JSON types and structures that we received from the backend. -
State management: one of the biggest challenges in a mobile app (and many other frontends) is proper statement management. We chose
hooks_riverpod
(reactive state management) in combination withflutter_hooks
to be able to catch a lot of programming errors at compile time already. -
Caching web content: all of the content is reachable through HTTPS endpoints, including the JSON API.
dio_cache_interceptor
, built on top of the populardio
HTTP client library, enabled us to implement offline capability in a straightforward manner, without writing any extra code. We usedhive
to store the data, including compressed images, in a database residing in the local app environment. -
Downloading videos: videos are served in both HD and SD qualities, and as mentioned before, a user must be allowed to preload them to their device. We leveraged
flutter_downloader
, which implements workers handling the downloading of (large) files on both iOS and Android in the background. I made a small contribution to the library in order to improve the process of cancelling download tasks. -
Video player: lastly, we chose
better_player
as a basis for the video experience. It allowed us to greatly customize the look and feel of the video player without resorting to platform specific code.
Result
After about two weeks, we were happy to report to troodi that we finished our implementation of a prototype version of the mobile app, fulfilling all the posed requirements and ready to be deployed onto both the iOS and Android app stores so that we could gather initial user feedback. Some impressions from the product: