Development London Bus Pal

Android OS version distribution in a real app

I was reading a post on Reddit which had some interesting statistics about Android OS versions and the speed (or tardiness really) of updating to the latest OS versions.

Of course the post is focused on individual phones, so it becomes difficult to get a sense of how many people are using the latest version of Android. So I decided, as I do, to check my own app for how version distributions have changed over the last four months. Here is a side by side comparison of the charts (the sample sizes are around 2500 users in both sets):

Of course – this doesn’t tell the full story either. It isn’t clear whether the shifts are due to software upgrades on the same phones, or whether users have just got new phones – or whether they are completely different users, but it paints a picture.

Something else to keep in mind when looking at this, is that my app is geographically biased towards London. So it isn’t representative of Android OS distribution across the world, or even Europe, it is very centred on London.

Here is the same data represented as a bar chart – just for a different perspective:

Development London Bus Pal

Building long-lasting apps

I’ve been looking around for interesting data points to share with other app publishers and found some data in a place I didn’t really expect to find it. After logging into my Google Analytics account for an entirely different purpose, I was taken to the analytics data for my app which I replaced with Firebase about 18 months ago. I don’t check it very often, but to my surprise, there is still a fair amount of action going on.

Users sessions in Google Analytics in January 2019

To give some context to the graph:

  • Version 2.1.1 – released November 2014
  • Version 3.1.3 – released 11 June 2017 and replaced on 24 June 2017 (Google Analytics was deprecated at this time).

This is amazing user retention for you! I don’t like the fact that I have data in two different places and that these users are mostly forgotten about, but I also cannot complain about it, since this is now just pure passive income. I actually cannot do anything to improve or remove it. Of course, it will also continually decrease as people upgrade phones, they uninstall the app and so on.

Why no upgrade?

At the point where I moved from Google Analytics to Firebase, I had to change my minimum SDK version from 14 to 15. This put me under the assumption that these users are probably unable to upgrade since they are using an old version of Android (4.0.2 or below). So I decide to validate it and check.

Checking which Android version my users are using

In fact, what’s not shown in the pie chart above (as you might think it’s hidden in “other”), is that I had 0 (yes, zero) users who were unable to upgrade to a later version.

Checking my Firebase stats confirmed a similar trend, some users are just very slow in upgrading their apps.

Apk’s lazing about on the internet?

I’ve found my APK’s all over the internet before and then had a look to see whether this is some new app store which I wasn’t aware of distributing old versions of my app. This pointed me to a really interesting installation source: Most of my users with old versions of the app, had this as their installation source. This is Samsung’s tool to move all your data from an old phone to a new one. Of course, this doesn’t point me to where these users initially got the application from, but it just points again at users who do not update their apps. (This also reminded me that I have a very small number of people using my app on the Amazon app store and I decided to upgrade it – it might actually work better for them, since I don’t use Google maps any more).

Architecting the enduring app

I did an earlier post on my app’s version history, where I walked through all the versions of my app from 2013 onwards. I was slightly surprised when I installed version 1.0.0 and it was still working exactly as it did the day I built it. This was mostly by design, but also with a bit of luck.

The external API which my application uses, hasn’t changed since 2013. This is the bit of luck which I had, because if the API (which is not in my control), changed even just a bit, all my old versions would break.

On the other hand, some of the design was deliberate. I had two options when I was designing my app – I could either stick a server between the mobile device and the external API or I could just call the API directly from the mobile device. (Incidently, I had already written much of the server-side code, as I had already done a web-version of the app before even starting the mobile version). I decided to cut out the server, mostly to keep costs down and also for speed considerations – I did not want to create a bottleneck or have to pay when it becomes really popular.

Option 1: Let the device get data directly from the API
Option 2: Put some middleware in place

Note that just because option 1 worked out for me, it doesn’t mean that it is necessarily the best option (in fact, in many instances it probably won’t be). There are pros and cons to both and you have to carefully consider them. Speed and cost were two important considerations for me. Not having to have a server in between means that I don’t have to pay for it when 10,000 devices all try to access data at once.

On the other hand, if the external API had to introduce a breaking change, my old versions of the app would all break irreparably and all the users who have been happily using my app for years now, would be really upset (this could be really damaging for my app at some unknown point in the future).

I had to take a bit of a gamble in terms of how to architect my app – as an independent developer, I simply didn’t have the resources to maintain a server and I ended up here out of necessity. Also, as an independent developer, I don’t necessarily want to maintain a server indefinitely just to keep my app running.


There are no right or wrong answers on what the perfect architecture looks like, but you have to keep in mind that people may continue to use your app for a long time after you intended them to do so. One version doesn’t simply replace another and as soon as you publish something, it’s going to be out there for a long time, so make sure that you plan for this. You wouldn’t want you users to give you bad reviews in 5 years time because of a decision you made today.

As a quick side-note, I have seen apps which force you in the app to upgrade to a later version when it becomes available. I don’t like this – in fact, I hate it as a user experience. A better idea might be to just let the user know every now and again that they might be using an out of date version and they should consider upgrading. Don’t force it, unless it is absolutely necessary.

Development London Bus Pal

Flutter on iOS for Android developers

I’m previously an Android developer who got started with Flutter and rewrote my Android app in Flutter to release it on iOS. During this process, I learnt a few things about implementing material design in iOS and generally things you might want to think about as an Android developer when you also work on iOS. (I flip-flopped between using Flutter or material design in the title as this post is about a bit of both).

As an Android user and a bit of a purist, I get pretty annoyed when I use an app and it looks like an iOS app. I want developers to respect the Android platform. In comes material design and this changes the thinking, material design is supposedly cross-platform and apparently should be fine for iOS too. Ok, so Google said that is the case and I believed them.

I took my Android app and developed it for Android and at the last minute, picked up the MacBook and built an iOS app from it. It surprisingly just worked! I put in no special code for iOS (the only exception for platform specific code was a check I had to do in order to support upgrading from my native Android app to my Flutter app (which I know is still native!)).

Never look back

When I ran the app on the Apple simulator, I realised that there wasn’t really an easy way to navigate back in the app. Since I used the Bloc pattern and I had a burger menu, I rely on the Android or hardware back button in order to go back in my app. I wrongly assumed (and I’ve had an iPhone before, so I realise how naive this was) that since Apple users don’t have back buttons, they think differently about navigation and would probably just find a different way of navigating to the thing they saw two screens ago.

I showed my app to a colleague on his iPhone and his very first reaction was – “how do I go back” – he was looking for a way to go back in the top left hand corner of the screen.

Luckily, since I was already handling the back navigation using the Bloc pattern, I could just provide a button on the page that would do the same thing and help the user to navigate back.

Show context

When I investigated “back navigation” in iOS, a pattern I noticed is that you generally want to see context of what you are navigating back to, rather than just “back”. So I also had to start keeping track of that too.

The back navigation which also shows the name of the previous page (Routes).

In the screenshot I did, I realised that my app bar is looking a bit crammed, but the general idea is there. I had to add in back navigation, since there would be no other way to achieve this.

The other thing I had to do for Apple devices, is to shift the burger menu to the right, since the left is now taken up with the back navigation. I have seen examples where the back navigation and burger menu would be below each other, but I chose to just have it on the right hand side instead for Apple devices.

Back ≠ exit

On Android devices, once nothing is left on the back stack, you just exit the app. This is not a pattern followed on Apple and you should not just quit the app. At the point that nothing is left on the back stack, I just remove the navigation button.

No transparency with Apple

A bit of an issue I had was with my launcher icons and also with my screenshots for the app stores. You are not allowed any transparency in these images. In hindsight, it feels like good practice, but it’s annoying when you have made a bunch of icons and a bunch of screenshots and have to redo them.

Build is different

It is worth mentioning here. Building an app for iOS is a bit different and there is a bit of a process. I had to get my hands on a MacBook and had to do a few weird things with certificates (I really have no idea what exactly I did!). I follow a fairly mechanical process in getting a build done and Xcode also automatically submits your app to the store. In there the process is also a bit different (and slightly slow).


It was a whole lot easier getting an iOS app out than I ever thought it would be. Apart from a few minor styling changes and a change in the way my users navigate back in the app, the app works the same on both platforms. I was really surprised at how easy it was – especially since I told my users about 6 months ago that I’m unlikely to ever give them an iOS app.

Development London Bus Pal

Ideas on monetisation

As I start a new year and trying to make a bit more revenue from my app, I’ve been thinking a lot about monetisation lately.

My current “strategy” for monetisation is:

  • Free app with a banner ad neatly placed out of the way. This is my main source of revenue.
  • Paid for app with the banner ads removed. I earn more on a bad day of advertising, than I do in a good month of sales.

Killing off the paid for version

My paid-for version is a bit of a thorn in the side. People have paid for it, and I am guessing it is mostly people who wanted to support me. I have fewer than 100 active installs, but they are active installs nonetheless. I have several issues with having this as a standalone app:

  • There are overheads in maintenance. It’s not massive, as my PC does most of the work, but it generates a separate APK, I have separate space in the app store, analytics and crash reporting apps have to be aware of this separate app. Just because it is easy to create a separate app without ads, doesn’t mean you should always do it.
  • As a standalone app, if I wanted my users to have the ability to easily port their data to the paid version, I would have to specifically write something to handle this and then support it.
  • As a separate app on the app store, I am competing with myself. I think there are some benefits to this, but I never look at the rankings for my paid for app, because it will always be lower than a free one with the same functionality. All those lovely 5 star reviews on my paid app don’t really matter, because my free app will always rank higher.
  • I consider users who have paid for my app as loyal supporters – and I want to return that loyalty. However, at what point does that loyalty run out? Do I have to indefinitely support a user who paid £0.79 back in 2015? (It sounds like I resent those users, I really don’t!).

Other ways to monetise

AdMob is constantly suggesting to me that I should move to more aggressive forms of advertising in my app (like interstitials and rewarded ads). I think that putting a 30 second ad in between a user and the information in my app is a really bad idea. My app is all about instant information and I have to be aware that no amount of short-term revenue will fix a really poor user experience. By looking at it this way, I think I may be able to find opportunities in my app where a user doesn’t want instant information and may have some opportunity for this.

Tip jars

I read somewhere about the idea of a tip jar in an app. I haven’t really seen any implementation like that, but I like it. I don’t really want to see how others have done it, because I think I can take my own spin on it. Basically, I want to allow users to contribute whatever they can afford in return for something. The way I want to implement it, moves more towards a subscription model, rather than a tip jar model, but I think from a user’s point of view, it might look the same.

Giving them something

Let’s talk about the “something” that they would get in return. I don’t want to put any of my core functionality behind a pay wall. Why would someone pay for it in my app, if they can get it for free plus a few annoying ads in another? So the general idea is that the something they would get, is probably the removal of ads and maybe some functionality which doesn’t form part of the core of my app or functionality which differentiates me from my competitors.


In terms of the subscription model I was talking about, rather than making “premium” features available forever, it would be for a limited (but long) time period. I am thinking between 6 and 12 months at the moment, possibly dependent on the amount you tipped.

Rewarded ads?

Maybe I can credit a user with some “subscription credits” when they decide to watch a rewarded ad instead of paying. I would imagine that these credits should run out a lot sooner than it would for paying users, but you could get a “try before you buy” experience by watching a rewarded ad.

Putting it together

So my offering would change to look something like:

  • Only a single free app with in-app purchases
    • If you use the free app, you get all of the core functionality and some neat little banner ads which try and grab your attention
    • You can pay me to remove ads and gain access to premium features (prices and time periods are for illustration only – it probably still needs some balancing):
      • Buy me a coffee for £1.95 – gets you 4 months premium access
      • Buy me a pint for £3.95 – gets you 9 months premium access
      • Buy me a something which costs £4.95 – gets you 12 months premium access
    • You can watch a rewarded ad which allows you to gain access to premium features for a number of days (somewhere between 3 and 7).

Not just about money

Whilst the idea is to try and increase my revenue and make more money, I also want to protect the user experience as much as possible. I could just slap ads in the middle of everything and I could try and be sneaky by making ads appear in different spots on every page to really confuse my users, but this doesn’t work for me in the long-run. I need to protect the user experience as far as possible and for me, this way of monetisation feels like it could be a win-win for all. Obviously this is still an idea and still need implementation, but time will tell as with everything related to revenue in the app market.

Development London Bus Pal

Reordering favourites

Today was spent finally implementing something I have been meaning to do for probably years now. Up until now, there just wasn’t a way to reorder your favourites – probably the only control you could have would be to add them in exactly the right order.

I kept flip-flopping between doing it directly on the favourites screen, or doing it in the settings screen. My opinion is that it would feel more natural to just take a stop on the main screen and drag it to the position you want it to be. That is, until you realise that some users have 10 or 20 favourites. It would be very difficult to organise it – especially if you want to drag something all the way from the one end to the other.

One other thing I have to think about was the potential of breaking the favourites screen to add this. You wouldn’t want to re-order favourites all the time. So I settled for the idea to do it in the settings screen. It also gave me the chance to quickly reorganise the settings screen a bit.

Quick plan to reorder some of the settings

I had the plan to use chips (if you don’t know what they are, there is a screenshot below) and allow users to reorder using them. I’ve never used them before and I had haven’t used drag and drop in Flutter before either. It took a couple of hours due to a silly little issue which had me stumped (thank you Stackoverflow – At one point during the struggle, I was going to give up and use lists instead and maybe even “move up/down” buttons, rather than fancy drag and drop, but I wanted to have my chips! I persisted and got it to work.

Chips which allowed reordering of favourite stops by using drag and drop.

It worked okay on the simulator, but it felt a little bit fiddly. I got it to work really well and then decided to test it on a real phone. I’m not happy. It is pretty awful. It’s difficult to get the chips to land where they should and the chips are much bigger on the real phone, which meant that each one was on its own line any way. This would not really help a user very much and probably frustrate them.

I’m going to do it over again – I’ll probably just use a list view with up and down buttons. It is unfortunate, because I liked the look of the chips in general, but it’s just not practical.

Back to the beginning for me now…