One of my most important learnings on Android development is to take control over my releases. What truly makes me confortable during any release is having control over changes, issues, product definitions, user experience and battery and data plan consumption.
I want to share with you some important features that sooner or later I have found needed in any Android app. That’s why I recommend to implement them earlier so other developers can get used to them and avoid having a massive refactor in the future.
- 🇦🇶 Keep calm and use dynamic feature flags.
- 🆎 Perform AB testing, it is truly useful.
- 📈 Track your application and users.
- 📬 Stop polling and use push notifications.
- 🚲 Simplify your development by using Http clients and Json parsers.
- 🏎 Increase speed perception by caching server responses.
- 💾 Provide a force and soft update mechanism.
Note: It is not my intention on this story to explain how to implement each learning but instead give you an idea about why they are useful and important.
1. Dynamic Feature Flags & Variables
As developers we exactly know the power of any single and innocent code change. That’s why when we code new features our chances of being deploying a MOAB (mother-of-all-bugs) into the wild are basically HIGH.
To decrease the damage of this MOAB we use stage rollouts (thanks Google for this!) and that’s good but we can go even further.
Dynamic Feature Fags allows us to turn on/off the features we have coded. This means that if I release my new code to 100% of my users and I screw it up (and I will!) then I can turn it off by switching it from a config file on my servers and no one is going to be affected anymore.
Having Dynamic Feature Flags plus using stage rollouts gives me the total control of the impact of my next feature (or bug?).
Dynamic Variables are pretty similar; the difference is that instead of being a boolean it could be any other type of variable (let’s say String) controlled by the server. This is useful when I am using things like number formatters and I want be able to control that format from a server configuration.
A very important thing here is to choose the right feature toggles tool. The right one at least needs to offer a good panel to easily change the values of the flags, be accesible by different stakeholders, have default and cached values and allow to turn on/off flags by different criteria (percentage of users affected, choose users by country, new/old users, app version, OS version, etc).
2. AB Tests
How many times have you been thinking if you should put that button here or there? Easy! AB test it and find out where it converts better.
AB tests are great tools to try out different UI variants to validate which one performs better.
How does this magic work? Let’s say I have users with the variant B and variant A (which is the regular version of the UI) at the same time. This allows me to have metrics of each variant and compare which one converts better.
The power of AB tests lies in having different variants after releasing once and become the winner variant into the default one for all my users; again only with after one release.
Caution: although AB tests sound like an easy thing to work with they are tricky to define, implement, measure and analyze but it it’s truly worth all the effort.
3. User and app Trackers
If I have to name what apps developers hate the most I would start naming from trackers. It is not a mystery why I would say that. Trackers consume battery, data plans, disk space, methods count, developers time (for “real” features) and a long list of other reasons to hate them even more.
Sadly trackers are also a very important part of an application. They allow us to understand our users, figure out where we made a mistake, measure how new changes are performing, check the effectiveness marketing campaigns and some more cool stuff.
Finally these are my two cents regarding this topic (1 cent each).
- Adding new trackers to your app should be easy and painless. Seriously you must invest your engineering skills to make it a really pleasant task to do.
- Advise wisely about which trackers should be added. Make a balance between all the pain and gainings they give to your app and business. You should be the woman/man in the middle between the users (and app’s performance) and the business.
4. Push Notifications
I believe a great feature is to notify to users that something cool happened in our app while she/he is (not) using it. For example we can notify that a new book is on sale, a payment was approved or that there are pending friend requests.
The old unrecommended don’t do it! way to achieve this is to frequently ask (let’s say every 5 seconds) to your servers if there is anything new to notify or update. This is not a good approach because it consumes a lot of battery, data plan, server processing and in case someone implements it she/he will have to figure out how to do this even if the app is closed.
Good news is there is something called Push Notifications which allows to implement this notifications thing on a very easy way and without most of the tradeoff of the approach mentioned above.
You can check out this tutorial about adding push notifications using Firebase: https://www.codementor.io/flame3/send-push-notifications-to-android-with-firebase-du10860kb
5. HTTP clients and Json parsers
Some years ago when I start coding on Android I coded all the networking calls and Json parsing with my bare hands. Luckily I have learned lots of cool stuff specially that is very complex to do it in a clear, right and optimal way.
There are a bunch of HTTP clients and Json parsers available to be used. They are quite an industry standard and save tons of time, pain and allows to add network calls on a very easy, clear and fast way.
A cache memory is a place between where you need the information and where you actually store it. Information that is frequently used is placed here and it can be accessed faster than the place where you actually store the data. The concept of caching information is applied almost everywhere. You can find it for example between your browser and the servers or inside your CPU.
Regarding Android applications we can “cache” (action of saving information to use it later) server responses which gives key advantages. Just to name a few: increase app speed perception, save battery and data plan and decrease the number of network calls the dev can make by mistake.
A golden rule here is to implement a solution which is easy to use and supports different cache policies. All these can be achieved using Sqlite, one table and some Java code.
A good Open Source example of implementing caching and how it should easily work can be found in Parse Platform: http://docs.parseplatform.org/android/guide/#caching-queries
7. Force and Soft Updates
Once our app is out in the wild we kinda loose the control basically because it will depend on our users to automatically update it which leads to have apps pointing to legacy APIs, crashes and bugs that will never be fixed, new cool features that will never be used, etc.
In order to have more control what I do is to implement a mechanism of force and soft updates.
The way a force update works is pretty simple. I show to the user a blocking screen (which means he/she cannot move forward or backward from there) which basically says why she/he have to update the app and provides a way to update it (typically a button that lands the user to my app’s Play Store entry).
On the other hand a soft update will let the user know that there is a pending update that she/he should install soon and a way to update the app but she/he still can move through the app.
I didn’t want to mention any particular solution to each topic but they aren’t hard to find on the Internet. If you have any particular question I will be more than glad to answer it.
Finally I will write about the implementation of these suggestions and third-party solutions in the future in case you find it useful.
Thanks for reading! Did you like it?
Recommend this story (by clicking the ❤ button) so other people can read it too! You can also react on Twitter @santihollmann.