How To Design A Cross-Platform Mobile Application?
Mobile applications have taken a center stage for the past few years, and with the continuous improvements in mobile technology, we will see more and more applications embracing the mobile platform. However, as an Architect and a developer, building a mobile application that will work across multiple platforms, and yet keep the code as sleek as possible is a daunting task. This was the challenge I faced when designing the Shopping Guru app that helps in making the most out of your online purchases. In this article, I will cover how I went about making this cross-platform app with a high amount of code reusability.
Cross-Platform Mobile Application Key Challenges
For the sake of discussion, I’m summarizing the two core requirements for the Shopping Guru app so that we can understand the challenges and the key aspects of the design better.
- Do periodic checks to generate price drop and product availability alerts.
- Facilitate goal-driven purchases by organizing these into projects. For example, create a project to set up a home theater.
We briefly touched upon a couple of challenges in the introduction. But, let’s highlight the key challenges keeping the 2 dominant mobile platforms – iOS and Android.
- How to improve the code reusability? A big part of this question is how to use the same programming language? As we know, iOS supports Swift and Objective-C. Whereas, Android supports Java and Kotlin.
- How to manage the app data in the cloud? For example, iOS offers iCloud functionality to store data. But, the moment you add Android into the mix, you do not want to have multiple ways of managing data in the cloud, especially, if your app has cloud-based processes that need access to this data. In the case of Shopping Guru, we needed access to the data to generate price drop alerts and to check whether a previously unavailable product is now available.
- How to handle platform-specific interactions that originate “from” the common code? For example, when a price drop occurs generate a notification. The price drop check can be done in a platform-independent reusable code. However, the notification has to be generated using platform-specific features.
- How to handle resources, such as externalized text and images?
As you can see, if we don’t get hold of these aspects early on, the code could get quite messy.
Application Architecture
After doing a few prototypes, I decided to split the application into 2 parts.
- Mobile App: This is the app itself that contains primarily the user interaction code with basic logic.
- Cloud-based REST API: This handles the core business logic and provides additional capabilities to improve performance, such as caching and throttling calls to the Vendor API. The Vendor API is used to search and retrieve items.
Mobile Application Design
The app comprises the following key components.
- UI: The user interface and associated code. This layer is implemented separately for iOS and Android. The majority of the application code is written in Java. For Android, that’s pretty straight-forward. And, for iOS, I used Multi-OS Engine, which provides a Java runtime on iOS and makes it possible to write pretty much all of the code in Java. You still need to use Xcode to create the storyboard and generate the skeleton code (such as the controller header and implementation files). From that point, you can use Multi-OS Engine’s IDE plugins to generate Java artifacts. It’s free and the app performance was reasonable.
- Core: This component provides common business logic and maximum code reusability. It also handles common resources, such as externalized text, images, and configuration files. For outgoing calls from the Core module to platform-specific implementation, I decided to have specific interfaces that will be implemented by the respective platform-specific module. For example, both Android and iOS modules implement a NotificationManager interface to provide notification management functionality. The UI code passes these module instances to the Core module at initialization time.
- Data Refresh: This component helps in fetching prices periodically, especially when the app is running in the foreground. Again, this is a reusable component.
- The app uses the following custom libraries.
- NetworkMonitor: This is used for monitoring the network status, such as when the device is connected to WiFi versus when its connected to the cellular network. Depending on the type of connectivity, the app automatically switches network usage to avoid/minimize cellular data usage.
- AnalyticsManager: This is used to publish opt-in app usage metrics with user consent.
With this approach, I could significantly improve code and resource reusability.
REST API Design
The REST API acts as the brain of the solution and comprises the following key components.
- The API Gateway + Lambda combination provides the REST API layer that the app would use for needs like searching items and retrieving item prices. It interacts with the Vendor API behind the scenes on a need basis to fetch the latest data. Also, it can do price drop and product availability checks periodically.
- DynamoDB is used to cache the frequently accessed data.
- It also offers a platform-agnostic way of managing app data. In fact, for the most part, the cloud-based components do not even care about the device’s actual platform.
Apart from resolving some of the challenges cited earlier, cloud-based components provide additional flexibility to add improvements and enhancements that do not require changes to the mobile app. This saves significant time to deliver enhancements to the end-users.
Development Setup
- I chose Android Studio as the core IDE since it is quite convenient for Android development. Besides, Multi-OS Engine offers a neat plugin to generate Java artifacts.
- Xcode is used on a need basis when editing the storyboard and creating initial files. Also, it is used to publish builds to App Store Connect.
- The build uses the gradle framework. Each module has a build.gradle file.
- For cloud deployment, I am using the AWS CloudFormation templates. This makes it easy to add more regions, as needed, literally in a matter of minutes!
Resources
- Multi-OS Engine Getting Started Guide
- How To Design Applications For Cloud (SaaS)?
- How To Create a Multi-Tier Stack Using AWS CloudFormation?
Developing a cross-platform mobile application requires a focused approach to consistently identify platform-specific versus reusable code. Once you establish this basic rule of thumb, you can extend it further to identify components that can be reused across multiple applications (like the NetworkMonitor and AnalyticsManager in this article). And, I hope this article gives you a good enough starting point to build a prototype for your mobile application and see if it would meet your needs.
Happy developing!
– Nitin
If you liked this post, you will find my AWS Advanced For Developers course helpful that focuses on many such best practices and techniques to design and deploy real-world applications in AWS.
Also published on Medium.