PM

Prince Malani

AI Specialist & Data Scientist
INITIATING ENVIRONMENT... [INIT]
← Return to Projects Portfolio

Marios Towing - Driver, Customer, and Admin Mobile Application

Real-time towing dispatch platform with Customer, Driver, and Admin apps enabling request submission, driver assignment, live trip tracking, and end-to-end fleet operations. Led full-stack Mobile development, API integration, and deployment at WebCodeGenie Pvt. Ltd.

Author: Prince Malani | Technologies: Kotlin, Android, Android + XML Structure , Firebase, SQLite

Project Overview & Architecture

# Mario's Towing — Nationwide Roadside Assistance Platform **The Android platform behind a Canada-wide towing operation: 3 applications serving 400+ drivers and 1,000+ customers, with live vehicle tracking on the map and card payments taken at the roadside.** - **Role** — Android Developer (Native, Kotlin): live tracking, payments, offline sync, release operations - **Company** — WebCodeGenie Pvt. Ltd., Ahmedabad - **Team** — 25-engineer delivery team - **Scale** — 400+ drivers and 1,000+ customers across Canada - **Surface** — 3 Android applications: Customer, Driver, and Admin - **Stack** — Kotlin · Jetpack Compose · MVVM · Hilt/Dagger · Room · WorkManager · Google Maps · Sockets · MQTT · Firebase · Square ### By the numbers - **3** Android applications shipped — Customer, Driver, Admin - **400+** drivers operating on the platform across Canada - **1,000+** customers served nationally - **25** engineers on the delivery team - **4** defects logged against my work across the full engagement - **2** real-time transports running in production — sockets for location, MQTT for job state - **2 years 2 months** total tenure, opening with a 6-month structured training program - **3 months** to design, build, and ship the Admin application solo - **1** payment gateway integrated from near-zero reference material, live without a rework cycle This was the project I grew up on as an engineer. I joined it as a trainee still finishing college, knowing Android only as a subject. I left it owning the 2 surfaces the product could least afford to get wrong — real-time location and real money — and having shipped a third application on my own. --- ## Project Brief Mario's Towing is a roadside assistance and vehicle recovery service operating across Canada. The platform I worked on is the Android side of that operation: the software a stranded customer uses to call for a tow, the software a driver uses to accept and complete the job, and the console dispatch staff use to route work between them. I was 1 of 25 engineers on the delivery team, and spent the bulk of a 2 year 2 month tenure on this product. Over that period my responsibility moved from assigned screens to owning entire feature areas end to end — live tracking, the payment stack, the offline data layer — and finally to building and shipping the Admin application myself in the final 3 months. The system runs in production against **400+ drivers and 1,000+ customers** nationally. Everything described here was built for people using it on real roads, in real weather, with real money moving through it. --- ## Problem Statement Roadside assistance is an unusually unforgiving software problem, because every constraint that makes mobile development hard shows up at once. A customer requesting a tow is stranded, often at night, often somewhere with poor reception, and their single most urgent question is not *has my request been received* but *where is the truck and how long*. A driver accepting that job is operating from a moving vehicle, switching between navigation and the app, and needs to take payment at the kerb without carrying separate card hardware. A dispatcher needs to see the whole board and assign work to the right driver among 400+. All 3 views must agree with each other continuously, and none of them can assume a stable network. ### Key Challenges 1. **Live location under unreliable connectivity.** Continuous driver-to-customer position streaming that degrades gracefully rather than freezing on the last known point, across highway dead zones and rural coverage gaps in a country spanning 6 time zones. 2. **Taking money at the roadside.** Card payments processed in the field, where a silent failure or a duplicate charge is not a bug report — it is a customer service incident and a refund. 3. **Offline-first behaviour.** Drivers routinely lose signal mid-job. Job state, status updates, and uploaded attachments had to survive that and reconcile correctly on reconnection. 4. **Android background execution limits.** Location streaming and message subscriptions must keep running while the app is backgrounded, without being killed by the system or draining the battery across a 10-hour shift. 5. **3 applications, 1 domain.** Customer, Driver, and Admin each present a different slice of the same job lifecycle. Any drift between them shows up immediately as 3 parties disagreeing about the state of a live tow. --- ## Platform Architecture The 3 applications are built as separate native Android clients over a shared understanding of the job lifecycle, each with its own MVVM setup and dependency graph rather than a single shared codebase — a deliberate choice, since the Customer and Driver apps have almost no overlapping surface despite operating on the same entities. **Presentation and structure.** Kotlin throughout, with Jetpack Compose and MVVM across all 3 clients. Dependency injection through Hilt/Dagger keeps the view models decoupled from the data sources, which is what made the offline layer swappable without rewriting screens. **Local persistence as the source of truth.** Room holds the device's copy of job state. The UI reads from Room, not from the network, so the app behaves identically whether or not there is signal at that moment. Synchronization pushes changes outward rather than the UI waiting on responses. **Real-time transport.** 2 channels run in parallel: location streaming over sockets, and job state changes over MQTT, subscribed from a background service so updates continue arriving while the driver is in a navigation app. Firebase handles push notification delivery for events that need to reach a closed app. **Resilience.** Network failure handling is centralized into 1 handler rather than repeated across every call site, surfacing a single consistent "Server Under Maintenance" state instead of dozens of individually-handled error paths. 1 place to reason about, 1 behaviour for the user. --- ## Technical Execution ### 1. Foundation — 6 months of structured training I entered through a 6-month training program rather than straight onto the product. **Months 1–3** covered data structures, problem-solving, team collaboration practice, and working comfortably in an Ubuntu command-line environment. **Months 4–6** moved into Kotlin, native Android, Jetpack Compose, and MVVM. The program closed with a knowledge-transfer handover onto the live project. I mention this because it is the honest account of how I learned Android: not from the project alone, but from a deliberate ramp that meant my first production commits were written with the architecture already in mind. ### 2. Customer and Driver applications My first sustained ownership was across both client apps — 2 separate MVVM structures, 2 separate dependency graphs via Hilt, shared domain contracts. Working across 2 apps that model the same job from opposite sides is where I learned to think in terms of a domain rather than a screen: every state a driver can put a job into is a state a customer must be shown coherently. ### 3. Live tracking — the feature 1,000+ customers judge the product on I built the live tracking system end to end using the Google Maps APIs with socket-driven position updates. The driver's app streams position continuously; the customer's app renders the vehicle moving toward them in real time. This is the feature customers actually evaluate the product on. Someone waiting on a dark roadside does not care about architecture — they care whether the truck on their screen is moving. That meant the work was as much about degradation behaviour as about the happy path: what the map shows when updates stop arriving, how stale positions are treated, and how the app recovers when the connection returns without snapping the marker across the map. ### 4. Real-time job state over MQTT and background services Beyond location, job state changes propagate over MQTT with a background service subscription, so drivers continue receiving assignments and updates while the app is not in the foreground. This was my introduction to the parts of Android that are genuinely difficult — background execution limits, service lifecycles, and the trade-off between keeping a connection warm and not consuming a driver's battery across a full shift. ### 5. Payments — Square integration and Tap to Pay I implemented the Square payment gateway with very little existing reference material to work from, and it went into production **without a single rework cycle**. On top of it I built the credit card charging flow and integrated **Tap to Pay**, which turns the driver's own phone into the card terminal — removing 1 more piece of hardware from a kit that has to survive a truck cab. Payments were the highest-stakes work I did on this project, and it changed how I write code. Every other feature has a retry. A payment path has a customer's money in it, so the correctness bar is different: idempotency, unambiguous failure states, and never leaving a transaction in a condition where the driver cannot tell whether the charge went through. ### 6. Offline-first data layer I built the dynamic synchronization between the local Room database and the backend, with WorkManager driving retry and deferred upload. Job updates and file attachments queue locally when connectivity drops and reconcile on reconnection, so a driver in a dead zone works exactly as they would in a city — the difference is invisible to them and resolved by the sync layer afterwards. ### 7. Permissions, media, and notifications I handled the full runtime permission surface across the apps — **5 categories**: location, camera, storage, media access, and file read/write — including the migration pressure of Android's tightening scoped storage and background location rules. I also implemented the Firebase notification layer that delivers job events to a closed app. ### 8. Release operations I worked on the CI/CD pipeline covering **2 of the 3 applications**, handling build, signing, and distribution. Owning delivery alongside development is what turned "it works on my machine" into a habit of thinking about what actually reaches a user's device. ### 9. Mario's Admin — built and shipped in 3 months In my final 3 months I built the **Mario's Admin application** myself — the third client in the platform. It gives dispatch staff the operational view the product had been missing: assigning service requests to specific drivers among 400+ for vehicle pickup, managing job attachments with upload handling, and the same Room plus WorkManager offline synchronization the driver app relies on. Building an application alone after 2 years of contributing to one was the clearest measure of what the project had taught me. Nothing about the architecture was handed to me; the decisions that had been made for me earlier were now mine to make. --- ## Results & Impact * **400+ drivers and 1,000+ customers** on the platform across Canada — operating nationally rather than in a pilot region. * **3 Android applications** shipped into production, 1 of them designed and built solo. * **4 defects** logged against my work across the full engagement. * **1 payment gateway** integrated from near-zero reference material and live in the field without a rework cycle, plus Tap to Pay removing dedicated card hardware from every driver's kit. * **2 real-time transports** running concurrently in production — socket-driven location streaming and MQTT job state over a background service. * **5 runtime permission categories** handled across a tightening platform, including scoped storage and background location migrations. * **2 of 3 apps** covered by the CI/CD pipeline I worked on, spanning build, signing, and distribution. * **Full-surface Android competence.** Across 2 years 2 months I worked through essentially the whole native Android surface area on 1 production product: architecture, real-time transport, background execution, offline persistence, permissions, media, notifications, payments, and release. --- ## Key Learnings **Production Android is a different discipline from Android.** Coursework teaches the API surface. A live product with 1,400+ users teaches what happens when the network dies mid-transaction, when the OS kills your service, when the permission model changes under you in a platform update, and when a user's battery has to survive a 10-hour shift. Almost everything I know about Android I know because this product broke in a specific way and I had to understand why. **Money changes the standard.** Working on payments taught me a correctness bar I now apply everywhere. Most features fail loudly and recoverably. A payment failure can be silent, expensive, and irreversible, which forces you to design for the states you hope never happen rather than the flow you expect. **Offline is a design decision, not a fallback.** Treating the local database as the source of truth and the network as an eventual reconciler produced an app that behaves consistently regardless of connectivity. Treating the network as primary and offline as an error case would have produced a fragile one. That inversion is the single most valuable architectural idea I took from the project. **Low defect counts come from before the code, not after it.** 4 defects across the engagement was not carefulness at the keyboard. It came from understanding the domain well enough to know what a feature had to do at the edges before writing it, and from an architecture where failure paths were centralized into 1 handler instead of reimplemented across dozens of call sites. **Working across 3 clients teaches domain thinking.** When the same job is rendered 3 different ways for 3 different users, you stop reasoning about screens and start reasoning about the entity and its lifecycle. That shift is what let me build the Admin app in 3 months at the end — the domain was already clear, and only the presentation was new.

View All Projects | Discuss this Project