A narrative about my 10 years of experience developing on the Android Platform
How it all started?
Java Mobile Development :
It was during my Post Graduate(M.Tech in Information Technology — 2009) when I was first introduced to Mobile Application Development by my professor Navin from SRM University, India. The IDE was Eclipse. It was a surreal experience seeing a mobile simulator for the first time. The development platform was kindly called Java ME. Clicking the Play button on Eclipse and seeing the helloworld app run on a mobile simulator was the first spark which made me like Mobile Development.
Then came Meego which was buzzing around the Smart Phone circuit. The first Android Phone by HTC made heads to turn. It was a time when Nokia was ruling the mobile world with its Symbian OS. I have heard stories about how Symbian developers were concerned about releasing objects using C++ destructors, since Symbian was C++ based and Garbage collection was non-existent to C++ devs.
And I landed my first internship opportunity where I was developing applications with Meego, with the hope that Meego would be the next big thing since Nokia was backing it. But it went Phooof. Also there was something called Sailfish which was yet another Operating System for Mobile phones making some noise.
And the company where I was interning was developing Apps and Framework for Mobile OEM’s. OEM’s are big mobile phone manufacturers. For example, Samsung, Motorola, OnePlus are OEM’s aka Original Equipment Manufacturers. The platform was called AOSP aka Android Open Source Platform. If you wonder what it was like developing on AOSP, let me give you a context.
The world of AOSP
Mobile phone manufacturers like Samsung, Motorola, OnePlus take the Android Open Source Platform, do some customisations like changing the Home Screen, applying manufacturer specific theming, building custom software for crazy cameras and sensors, also including their own apps, on top of vanilla Android. They then get it certified by Google, burn the custom Android Images into their Phone and ship it.
Developing on such a platform was challenging. Why? Because the whole Android Source Code for Kit Kat was around 8 GB. The compiled code would become 20 GB and the generated Android img file would be around 600 mb iirc(If i remember correctly). It was not as simple as building an Android Application, where you can import the code into Android Studio. I even naively tried importing the entire source code(5 GB) into Eclipse. So I had to code on Notepad and VIM.
The hurdle of downloads
Downloading the source code using a 8Mbps connection was a separate challenge on itself. Companies often cached a copy of the whole AOSP code in their servers to make the downloading faster. Being a small team, I had sometimes stayed during nights hoping that the downloads will not be interrupted at night :). :snowflake:
Vim or notepad for development
While modifying the source code of AOSP,
- For most of the time I had to use VIM or notepad
- Compile the source code which would take 25–30 mins for every line of change
- Building the code would produce an artefact with the extension .img
- Finally burn the .img file into a phone using a tool called Fastboot
- Reboot the phone to see if the changes are applied.
An OEM that I worked with later, gave a remote workspace with faster build machines. The code was hosted remotely and I could download just one file, make changes, push the file to the remote workspace, build remotely. That was remote execution way back in 2012. It was super fast (like 5–6 minutes per build) because we had enough memory and cpu to run on.
Debugging on AOSP?
I used to put System.out.println() or Log.d() :exclamation: inside the source code and generate an executable. And then burn it on the phone, do some playing around, and observe what is being printed out. That was the only way I was able to map out execution flows in a huge code base.
CI and CI for AOSP
With AOSP comes intrinsic challenges of scale. Developers are spread all over the globe. Code reviews were done mostly on Gerrit and this was tightly coupled with JIRA.
Think about this.
A JIRA ticket associated with a feature or a bug, would be closed only if the code is reviewed and upvoted by at-least 3 reviewers on Gerrit. Changes to the trunk would be accumulated and a suite of regression tests (More than 200k tests) were run every 30 minutes. Every developer whose change is run through the suite would be notified and would have to keep an eye for failures. If there was a failure, the developer is expected to fix or revert the code within 30 mins, else the code would be automatically reverted.
And having spent some time on AOSP and built Apps like Home Screen, Contacts, Settings application and building SDK’s for OEM developers, I got a chance to look into consumer apps which was a whole other world.
The First Consumer app
The first Playstore app that I got an opportunity to build was a live news streaming app for a popular news channel with a good amount of viewership. The IDE was still Eclipse.
I often used the term ‘flash’ very often. I used to say “Lets flash the apk into the phone” instead of install because of the terminologies that I carried forward from the AOSP development days. It took sometime to change.
Building Consumer applications was a high because, good or bad you would get feedback right away. Ratings and Reviews became very personal. Sometimes it would be very good and sometimes very blunt. It took sometime to digest the reviews. But it was this traction that kept the drive to develop better apps.
I was developing more and more apps from scratch. I was building mostly utility apps, until I plunged myself into startups and e-commerce which was a whole new world, where speed was measured in light speed and not in kmph(Kilo-meters per hour).
The plunge into Startup’s
It was 2014 when I got an opportunity with redBus and I gladly took it up. What drove me to work everyday was the rush of seeing the products that I develop, being used by people around me. For instance, in the AOSP days, I worked on a super hit phone and it was a satisfying feeling when I saw so many people around me use the phone.
I used to think to myself, “Oh my code runs on that phone. Oh my code executed on that button click”. It was very satisfying. And redBus amplified this. Almost everyone around me had used/uses redBus very frequently.
True to a startup person, I used to go to the bus stops, where I would see people using the app that I am building. I would guide them and resolve any queries. This soon became a habit. This also helped me to suggest changes and features for improving the app.
Startup was a different ball game when compared to Software services or big product organisations. The amount of ownership and belonging that i felt was immense. I started to get emotionally attached to the code that I wrote( which I discovered should not happen).
Terminologies in E-Commerce
While working closely with Product Managers, Marketing, Operations, TechOps, Content writers, Designers and a varied disciple of folks, there was a wealth of terminologies that I had learnt.
I heard and got accustomed to terminologies like ‘CR(Conversation ratio)’, ‘Drop Offs’, ‘Funnel’, ‘GMV’, ‘Average transaction value’, ‘ User segmentation’, ‘Analytics’, ‘A/B’, ‘Retention’ and so on. The CEO was very approachable. The CTO sat next to me. Being surrounded by people of different disciples opened up my mind. This was a big mental leap. I was no longer a (Senior) Software Engineer. I was transformed to a Product Engineer who understood Product and Engineering. I was able to keep both Engineering and Business in mind and make balanced decisions.
Android at E-commerce
Androiding at E-Commerce applications was joyous and challenging, because of a lot of parameters.
- Choice of Android APIs
- Multiple language support
- Cost of mobile internet bandwidth
- Impact on Phone Battery life
- Variety screen sizes
- Varying internet bandwidth
- Frequency of updates
Let me explain how this was a challenge
Choice of Android API’s : There were always a few different option of API’s available for a certain use case
- Should I use an Activity ? Or a Fragment ? or a custom view within an Activity or a Fragment inside an Activity?
- Should I use an Async Task(back in 2015 these existed) or Service or a Handler Thread?
- Should I use a Bounded Service? or an Unbounded Service? or AIDL?
All these API’s suited for a specific use case. This meant I should have a good understanding of when to use these API’s.
Choice of Android Libraries:
For a startup it was necessary to ship frequent and fast. This meant, we use solutions that were already built. It does not make sense to build a Networking library from scratch while moving fast. But while using open source libraries, I had to be wise enough to make sure that the open source solutions would last for at least two years.
Some examples are
- Volley(Yeah it was there and is still there) vs Retrofit vs Plain old OkHttp
2. RXjava vs Simple threads vs Thread Pools
4. Picasso or Glide
And while considering these libraries, it was important to keep in mind the heaviness of the library. Performance mattered. Over a period of time, I developed a ruleset which helped in decision making. These were
- Method count of a library
- Number of dependencies that a library depends upon
- Size of a library on a whole
Multiple language support
There are three challenges in this aspect.
The first one is the number of string variants that has to be included in an app. The Indian subcontinent alone posed a challenge, where I saw more than 20 languages bundled inside an app. The more the number of languages inside an app, the more bulky the app becomes. After a couple of solutions like run time delivery of strings, and config driven apps, one solution looked promising which was App Bundles which has the ability to deliver language packages at run time.
The second one is context specific translation. Not all strings can be literally translated. String translation needed specific context in different languages which meant that there has to be many content writers(per language). This was an expensive solution to have content writers in different languages. Language translation as a service was provided by a few companies which was utilised in a cost efficient manner.
The third one is the layout itself. RTL meant that I had to test in different languages and screens.
Cost of mobile bandwidth
Before 2015, when 1 GB of data was available for a month to spend, consumers of apps were conservative about using apps. This meant we count every penny starting from
- Request and Response payload size
- Analytics payload size
- Size of images downloaded from the servers
I remember that we once were debating if we needed to shorten the keys of a JSON response to reduce the response payload. And we did :)
Impact on Phone Battery Life
While travelling or when the battery is low, consumers often put their phone on battery saver mode and this meant that notifications, schedules would not be triggered on time.
API’s like Work Manager helped in the later part of 201X’s
I was part of a small team of developers churning out feature after feature for a large scale e-commerce app. When we realised that we needed more developers we had to scale the team. This was yet another challenge in terms of …
- Onboarding : New engineers joining the team should get up and running as soon as possible
- Maintaining code quality and consistency : As the number of developers working in the codebase increases, individual developer characteristics start to show up on the code base. Things like Code Style, Code Formatting, Architecture, Choice of libraries had to be regulated. This is often overlooked but it has the potential to stall business continuity.
Maintaining code quality had 2 challenges
- Agreeing to a set of standards
- Making sure that the standards are followed
Agreeing to a set of challenges would have to be democratic. And some decisions would solely depend upon voting. Ex: Agreeing between Camel case or Snake Case is hard because neither of them has any impact programmatically. It is aesthetics. It can be debated for years. In such cases, a vote of majority(Democracy) wins.
For enforcing standards, the obvious way is to automate. No developer likes being told that there are tabs instead of spaces during a code review. So that’s when I started setting up automation. This meant, checks on each commit. And that led to CI. That’s when I started experimenting with different CI Systems like Jenkins, GitLab CI, Circle CI. Also this is when I realised, Mobile CI is a thing.
As soon as I started setting up CI for mobile builds, I realised that running builds on a Mac Mini or a Linux machine is soon going to go out of control for a 20 member team, who commit at-least 10–20 times a day and checks have to be performed at every commit. This was a mental leap that I had to make. From a mobile app development engineer to a mobile infrastructure engineer. The first thing that I was thinking about was “I need more build servers for my team. Where do I get some?”. I reached out to the Backend engineers and they had suggested setting up machines on the cloud (VM’s and all). So I started experimenting on Amazon EC2 and on Kubernetes. From developing apps to developing infrastructure for mobile developers.
This is when I joined Gojek, and the scale of developers exploded. And I was in for the ride of a lifetime. Gojek mobile developer count was 200+ mobile engineers. Making sure that 200+ mobile engineers stay productive on a huge codebase was the next challenge in front of me.
Parameters like build times, IDE responsiveness, code consistency, build infrastructure, scaling up CI are challenges that were at a bigger scale than what I was used to and I was up for the challenge.
Subconsciously, I was a data driven engineer and this soon was going to help me immensely. I began to realise that Developer Experience was not a nerd thing anymore, but a product development of a different nature. Measuring how happy developers were was the crux of developer experience. The developer experience team had to design products to be used by developers. So they had to be their own Product Manager, Designer, Architect, Developer, Tester, analyst. Is’nt this exciting? The developer experience team at Gojek was already doing this and I was glad to join them and make an impact.
Analytics/Data was the base of everything that we did in the developer experience team. The questions that goes in the minds of developer experience team are
- How fast are the builds?
- Are developers able to build features faster?
- Where are developers spending unnecessary time?
- What can be automated?
- What part of a build is taking time? Would the build system sustain for the future? How would the builds behave when adding more and more code? What is the environment in which builds are being run (Too many chrome tabs open? CPU usage? Memory usage?
There were a myriad of questions. Just like any product development, understanding users was critical.
Traditional Backend engineers could not understand Mobile builds because unlike a Go lang build or a Ruby build, Android Clean builds were so expensive.
When encountering 20+ minute build times, I had a question in my mind. “20+ minutes for a build is insane. Am I configuring Gradle correctly or am I doing something fundamentally wrong?”. This made me go in search of answers and that’s when I started going deep into build systems.
I have to be honest in this aspect. Until this moment, .gradle files were a bunch of cryptic files and when build broke, it was either clean builds or stackoverflow that helped me to get on track. Never bothered about what gradle was doing wrt Android Development.
But it was time I started looking into what gradle was doing. Oh Boy ! I did plunge myself into Build Systems. The learning was steep. Understanding the life cycle of Gradle builds, understanding the life cycle of Tasks, Understanding what buildSrc were and learning Groovy was something that helped me understand build systems. And after understanding the anatomy of Gradle, I realised that good caching was one way to speed up builds. Gradle scan was invaluable. I realised how fragile Android builds were and how easy it was to screw up builds on Android.
And the journey continues.
Seeing millions of daily active users, using the app that I build for their day-to-day use has been an adrenalin rush. It has been a satisfying experience making the lives of people around the world better every day. But the want for more adrenalin and meaning is not stopping any soon.
Over the 10 year period I have come to realise that technology as a tool to make lives better. Being a polyglot Software Engineer has helped me in seeing problem statements abstractly and getting the confidence to solve them without looking at the limitations of technology. Along the way, I have learnt GoLang, Python and Ruby.
I will continue to build products that will reach millions and millions of people all over the world and make life simpler and easier for developers, travellers, entrepreneurs, small businesses, farmers, wildlife photographers, artists and many more.
This, I guess is my way of contributing to the world and making a bigger impact. With 10 fingers, a brain, a laptop(and the internet and stackoverflow of course :P ) , I guess I can.
And for anyone starting on Android or Mobile development, remember that the basics is still what is going to cut through. If there is one thing on Android that needs to be understood well, it is the UI Thread.
With so many API’s like Architecture components, Work Manager, Jetpack Compose, Coroutines it is possible for a developer to be spoilt for choices. The only way to build efficient and performant apps is to understand the basics of Activity, Fragment, Intent, Broadcast receiver, Services well. This can help a developer to make the best choice of API’s for each use case.
One moment that I cherish in my career is when I got featured in the official Android Developer Website.
Cover Image Credit : Photo by Kira auf der Heide on Unsplash