Categories
London Bus Pal

It broke!

I have a post ready to tell you all about the new functionality that I launched for bus information, but during a migration to a better service today, it broke a bit. This doesn’t affect anything except for the additional bus information telling you which routes the buses run on historically. All the prediction stuff continues to be stable.

Once fixed, we will continue.

Categories
London Bus Pal

London Bus Pal v4.4.1

Version 4.4.x introduces more bus information into London Bus Pal.

Firstly, I tried to keep the design of all of the functionality to ensure that it is unobtrusive to users not interested in the information, but still easily enough to access for those who are.

Changes which can be observed in the main functionality:

  • When searching for a specific bus, type-ahead is now available and the app will make suggestions when you start typing either a bus registration number or a fleet number. The type ahead information will also indicate the fleet number and operator.
  • Rather than just displaying a “no information or not running” message which is unclear, if you search for a bus and it is not in service, the app will show you this message quite clearly now.

New bus information screens:

  • Once you have found a bus, whether in service or not, you can access the information screens. For in-service buses, an information icon is now displayed in the top right-hand corner and for out of service buses, a clear button is available to show you bus information.
  • On the bus information screen, there are three tabs available:
    • Assembly: this tab gives information about the fleet number and operator. If additional information is available about the bus assembly (such as engine, number of doors, chassis etc), it will be displayed here.
    • Usage: this tab will show you which routes the bus has been used on over the last 7 days. Please note that these are estimates based on information interpreted from TfL. These numbers should be used as indicative rather than specific.
    • Photos: the photos tab will show you publicly available photos from Flickr for this bus.

This functionality is in a pilot phase at the moment and subject to change. I have some rough plans on what I want to do with this functionality in future, but the purpose of this pilot is to see what the uptake is like and then maybe expand it out a bit further.

At the time of writing this, we have the information available for over 10,000 buses. Only around 750 of those have missing assembly details and I expect to start completing this over the coming months (of course, this will be an ongoing task).

Some plans for the future which I may look at are:

  • Bus lists of interest (rare workings, new buses, old buses and so on).
  • Personal bus lists – ability to put buses into your own personal groups; this can then later be used to see where all these buses are.
  • Route information – based on the information collected at the moment, it becomes possible to see how many buses are working any route at a point in time
  • Crowd-sourcing vehicle information – all fleet number and operator data is currently managed by myself; this is not sustainable in the long-run.
  • And many other ideas (some which I just don’t want to mention right now or others which might come from my users).

The roll out of this version is underway at the moment. I am expecting the Android roll out to be complete in a couple of days and iOS might take a little bit longer due to Apple’s requirements (and a technical issue which I experienced trying to create a build).

Categories
Development London Bus Pal

Flutter – the honeymoon is over

In January, I created a post where I sang Flutter’s praises over Android native. Three months later, does this still hold true?

First, let me give you a brief background. I launched my app back in 2013 on Android and the app has naturally grown from there. Late in 2018, I decided to do a full rewrite of the app in Flutter (with two things in mind: make the app more future-proof and ability to expand to iOS). I soft-launched on iOS in mid-December and went onto Android at the end of December. Despite a few hiccups (such as forgotten or missed features!), it generally went okay.

As of today, only about 6% of my Android user base is still on the old Android native app. I have around 2700 active users a day, so not massive, but it is a well-used app. Almost 4 months of constant hammering by users should give me a good flavour of what it is like to run a Flutter app in production.

What is still good?

Apple (almost for free): Being able to launch my app on Apple is definitely worthwhile. Revenue and use isn’t exactly where I want it to be, but I’m on the platform, so that is 100% further ahead than I was before Flutter. Apart from the nuances in terms of the iOS UX, I haven’t experienced any difference between the two platforms. It is great to do all of my development on Android and it just works on Apple.

Rapid developement: I have managed to add several new features to my app (including some fairly complex new features) which I would never have been able to achieve so quickly in Android native. And I also got this on Apple, almost for free. It may also be a sign of how well I architected my app, but this is also because Flutter and Dart allows this.

Community: The Flutter community is big and growing exponentially. Help is always at hand and I see new tutorials and walkthroughs coming out daily.

What’s not so good?

Dependency hell: I have found myself stuck in some dependency hell. I have one library which hasn’t updated and it causes a bad domino effect. I thought it was easier to manage in Dart, but appears not so. It took a fair amount of effort to unpick bit by bit and find the offending library.

Incomplete Google features: Further to the dependency hell I mention above, Google’s own features are still incomplete. Their maps are not usable yet, so I’ve had to use another package called “flutter_maps”, which is currently causing my dependency hell.

More incomplete Google features: AdMob is not really incomplete, rather just incompatible with the way that Flutter is meant to work. The library hasn’t been updated since February and I have to use awkward workarounds. I’ve had a really good explanation by Andrew Brogdon after I raised the issue on a Flutter Youtube video, but it is still frustrating that we are where we are with this. Nowhere.

Null handling: I’m not sure if it recently changed or if I just didn’t notice before, but I preferred the way that Dart handled nulls in that it won’t fatally blow up and just carry on. I had some really bad issues recently where it would just stop running parts of my code when I accidently tried doing something with a null. No errors, no nothing. It would literally just skip the rest of the function without throwing anything. It took hours to unpick and I would honestly have preferred the app to just crash instead.

Instability: I started using the stable channel of Flutter, so that I could keep up to the latest versions of Flutter, but without too much risk of things going wrong. Unfortunately, a fairly bad regression issue has appeared and it is causing some frustration (mostly just that Samsung decided to suspend my app).

Other weird bugs: This issue has appeared most than 4000 times in my app for more than 350 users. It has proven impossible for me to reproduce, but I can see it happening. I’ve had a number of other weird issues also occur. A more stable framework would not have these sorts of issues.

Do I still prefer Flutter?

Absolutely, I still prefer Flutter. I know that on balance, it appears from the above lists that I have more complaints about Flutter than praise, but this is not accurate. I simply recognise the current flaws with Flutter, but I still believe that the future is bright. Using Flutter, I believe that I can keep on expanding my app and giving my users all of the great experiences they are after.

Categories
Development London Bus Pal

Monetisation – the results

It’s been a while since I posted here, mostly because I’m busy behind the scenes with huge new features. It will take a while, so I can’t promise or really say anything yet.

Today I had to do a bit of housekeeping and had a look at how sales were doing. It’s has been about 2.5 months since I started my in-app purchases, so I can finally start to see how these are performing in comparison with ad revenue and sales revenue. The breakdown in percentage from 1 February until today is as follows:

  • Advertising revenue: 95.7%
  • In-app purchases: 3.2%
  • Mobile app sales: 1.1%

The thing which is not obvious here, is that there hasn’t been any obvious drop-off in advertising revenue, although, it would be very difficult to tell, since advertising revenue is a little bit volatile any way. Revenue is up by 3% vs the previous 28 days, but it can be down 5% next month for reasons beyond my control.

I see in-app purchases as an additional revenue source, rather than cannibalising my advertising revenue.

Another interesting metric I could look at, is how Android compares to iOS, however, my iOS take up is still fairly low, so it would be an unfair comparison. I simply don’t have enough data points to really say.

Feel free to get in contact if you want to know more – I’m always happy to talk to other developers and share any experiences I may have had. Back to work for me then…

Categories
London Bus Pal

London Bus Pal v4.3.1

The next release is here. I fixed a few small issues which I picked up on the journey planner (for example, if you asked for a route where it wasn’t possible to see it on a map, it would mostly just break!).

For the rest of it, I spent a lot of time testing small intricate details of the app to make sure it works well. Through this, I picked up a few small issues which I also fixed.

  • Journey Planner improvements and bug fixes. πŸ—ΊοΈ
  • Small bugs fixes including one where the routes were not properly sorting in the route list. πŸ›
  • Continuous updates to ensure the app is always as fast as possible and using your phone as efficiently as possible. πŸ“š
Categories
London Bus Pal

London Bus Pal v4.3.0

This version brings the beta version of the new journey planner to you and a few small fixes:

  • β€’ Journey Planner is here – it is very much in beta phase, but should be very usable! Let me know if you experience any issues. πŸ—ΊοΈ
  • Small improvements to ensure very efficient battery use. πŸ“š
  • Mostly minor bug fixes and one major one where routes were broken. πŸ›
  • Please don’t forget that you can support me by leaving a rating in the app store 🌟 or by removing ads for a small donation in the settings menu πŸ’·
Categories
Development London Bus Pal

Bad apps will wreck your battery

Following my previous post where I did some rudimentary experiments on other bus apps, I decided to leave my phone running for another couple of hours and see the effects on battery usage. This experiment involved opening and viewing specific stop and then simply leaving the app by pressing on the home button. I left the apps, but didn’t kill them. I did this for all the apps in the experiment and then reset all the counters.

And then I just left the phone for a couple of hours.

During the experiment – I left the phone off – in fact, I left the house and just left the phone on a desk. I used the phone for a couple of minutes, but made sure not to go anywhere near any of the bus apps.

The results were interest in that one app had woken up the phone 28 times and enabled the sensors for over 7 minutes during the 2 hours and 24 minutes the experiment was running for. It also transmitted 32.2KB of data during this time – not a significant amount, but that’s almost 50% of the amount that was transmitted by London Bus Pal when it was doing some real work.

Here is a breakdown of the results for this offending app (it is listed as a top app on the Google Play Store):

Duration:2h 24m 51s
CPU Usage:47s
Number of times waking device28
GPS:7m 27s
MPU6500 Acceleration Sensor7m 26s
MPL Rotation Vector7m 27s
Gravity Sensor7m 27s
YAS537 Magnetic Sensor (compass)7m 29s

I went back into the app to check why it would need to be on in the background. I noticed that Push Notifications were enabled and that I was automatically subscribed to get notifications for “special promos etc”. I turned off everything and disabled auto-refresh and also turned off analytics data sharing. After having to dismiss an ad (wow these are annoying!), I killed the app and restarted it (to make sure that all of the settings would load properly). I loaded a bus stop and pressed the home button and reset my battery usage monitor.

Time for some tea…

After tea, the results were so bad, that I thought I did something wrong and restarted the whole experiment. This time making sure that I take a couple of minutes before resetting the battery usage monitor to ensure that the app should be asleep.

Duration:18m 26s
CPU Usage:1m 25s
Number of times waking device:3
GPS:18m 26s
MPU6500 Acceleration Sensor:31s
Gravity Sensor:1m 1s
MPL Rotation Sensor:1m 1s
YAS537 Magnetic Sensor (compass) 58s

The GPS timing was the reason I didn’t take the results from my first test, because I thought it was broken. It turns out the app is broken and holds onto the GPS when it really doesn’t have to.

Now I’m really frustrated

Do users even realise how this app is killing their battery? I looked through the reviews and this app gets a lot of praise (yes I’m slightly jealous) – but it seems that users don’t generally notice. I wouldn’t know without extensive testing which app is it that caused my battery to die so quickly – I usually blame the phone, not the apps. There are users who noticed, but they are far and few between:

Out of interest, this app was “App 2” on my previous list. It was exceptionally bad in terms of data usage and really bad on the battery in real usage testing too.

I’m going to stop writing now, because I don’t like focusing on other people’s work – I want my own to be the best it can possibly be. This was a useful exercise to make me believe in what I am doing, but it equally gets me down that unsuspecting users don’t realise why their phone batteries are draining so fast!

Categories
London Bus Pal

Kinder to your battery and data

London Bus Pal now has a dark mode which will help you to save some crucial battery life. This was just a quick experiment, rather than something users have been asking for. London Bus Pal has never been accused for draining battery – and this is for very good reason as I carefully think about every line of code I write to be as good for your phone’s battery as it could be.

This lead me to do some more experiments in terms of battery usage of London Bus Pal and other similar apps – some of the results shocked me to be honest.

The setup

The test I ran was fairly rudimentary. I took the top 8 apps which all return live bus times in London from the Google Play store. I made sure that I installed them and opened them all previously, wherever possible, I followed the same pattern:

  • If asked, don’t allow location to be tracked
  • If asked, select non-personalised ads – all apps were the free versions (had ads enabled)
  • Make sure I tap through the app to get rid of any “one-off” requests or app hints
  • All tests done in “light” / default mode

Location off means location off

I then had a small script which I manually executed, which involved searching for a stop, viewing a bus, viewing a stop, viewing another bus and so on. I executed the same steps on all the apps.

The first thing which grabbed my attention was the one app which was insisting that I enable my location before it would work. I persisted and kept saying no and eventually it gave in, and I managed to run through to the end of the experiment on that app. It turns out that it didn’t really require location to be enabled – it was just a lazy developer who didn’t want to work around this.

The next thing was the fact that despite location service being disabled and not really required (all the apps produced results in the end), three of the eight apps were still using the accelerometer. The is absolutely pointless and just wastes battery power.

The results

For the first round of tests, London Bus Pal was so low down the ranking of battery use by apps, that I almost thought my test was broken. But it was there, way down on the list. Even in light mode, it was by far, the kindest to my phone’s battery for the same test.

What about location on?

Next up was running the application with location services on. I decided I would do the simplest of tests and that is only allow the app to find my location and then close the app.

I ran through the test again and this time things were a bit less annoying (except for one app which insists on showing full screen ads all the time). This test was a bit more tricky to run because the first app run would possibly have the worst hit if it uses the GPS as efficiently as possible.

London Bus Pal kept coming back as the app, out of the eight, which uses the least amount of battery. In fact, three apps (London Bus Pal and two others) were clearly optimised for battery use whereas none of the others seemed to be, based on the numbers.

Of course, you’ll be asking, show us the numbers, and I have a list of numbers for you below – but it is worth pointing out, that the numbers are relative to each other in the same test, you cannot really compare them too much from one test to the next. It will give you an idea of the ranking and scale of usage of each application during both tests.

The most surprising thing for me was the worst offending app was engaging all of the sensors the whole time the app was open and even had some wakelocks going on (translated – this app is designed to suck the juice out of your battery).

Data usage

While I was doing my first test with location off and doing a set number of steps, I also tracked the data usage of each app. Again, the results truly surprised me – the app which was the worst on battery usage, was also the worst on the data usage (note, these are probably also related). What’s useful to note here, is that ad traffic was included in all of the data usage stats.

AppBattery drain (location off)Battery drain (location on)Data usage
App 1
7479428.8KB
App 2811002.3MB
App 381
44
818.8KB
App 47453617.3KB
App 510058776.5KB
App 6212187KB
App 7163787KB
London Bus Pal142193KB

Conclusion

The purpose of my experiment was to see whether I could officially claim that my app was battery and data optimised. It is something I care about deeply and carefully consider whenever I do anything. Based on the results, I think this is a resounding yes – I can definitely claim that my app has been built to optimise battery use.

Categories
London Bus Pal

London Bus Pal v4.2.4

β€’ Introduced dark mode which you can activate and deactivate in the settings. This should save your eyes and battery life! πŸ‘€

β€’ Library updates to make sure that everything is as efficient and stable as it can possibly be. πŸ“š

β€’ Please don’t forget that you can support me by leaving a rating in the app store 🌟 or by removing ads for a small donation in the settings menu πŸ’·

Categories
Development London Bus Pal

Dark mode: this is why I love Flutter

I’ve seen all of the hype around dark mode lately and I knew that at some point, I’d probably have to jump on that band wagon. But, it isn’t on my priority list as I’ve promised my users something else.

As I was wasting time yesterday, I saw a Youtube video about the dark mode craze and I thought, let’s give it a go – I needed a distraction anyway.

Flutter theme

  ThemeData theme = ThemeData(
      primarySwatch: Colors.red,
      primaryColorDark: Colors.red.shade700,
      secondaryHeaderColor: Colors.white,
      accentColor: Colors.orangeAccent,
    );

I previously pulled out my theme into a separate variable as I was playing around to make sure that my entire app respected the theme as far as possible, but my entire MaterialApp uses the above theme (it’s a bit redacted). In it’s basic form, all I had to do to change to dark mode, was to add the following into my theme:

      brightness: Brightness.dark,

And that was it. I had a look through my app and quickly found three or so instances where my app wasn’t respecting my theme. Generally, I pull the colours from the theme, rather than it being hard-coded, for example:

Color backgroundcolor = Theme.of(context).dialogBackgroundColor;

The worst offender was my search delegate and after a bit of playing around, I ended up with what feels like a slight workaround, it now does what it did before if the brightness is light (which actually doesn’t respect my theme too much, but it works and doesn’t change anything) and then it fully respects my theme if the brightness is dark:

  @override
  ThemeData appBarTheme(BuildContext context) {
    final ThemeData theme = Theme.of(context);

    switch (theme.brightness) {
      case Brightness.dark:
        return theme;
        break;
      case Brightness.light:
        return theme.copyWith(
          primaryColor: Colors.white,
          primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
          primaryColorBrightness: Brightness.light,
          primaryTextTheme: theme.textTheme,
        );
        break;
    }
  }

So that was it for being able to switch between dark mode and light mode in code, now to do it in run-time.

Switching during run-time

The implementation was quite straight-forward (I’m using the bloc pattern). Firstly, I hooked up a new setting in my application preferences (this doesn’t deserve a code example as it won’t be necessarily helpful for others), but what I end up with is a stream in my bloc which emits true or false depending on whether light or dark mode was selected. This is what the declaration in my bloc looks like to give you an idea (I start with false just to make sure that we have a value):

  BehaviorSubject<bool> _darkmodeController = BehaviorSubject<bool>(seedValue: false);
  Sink<bool> get inDarkMode => _darkmodeController.sink;
  Stream<bool> get outDarkMode => _darkmodeController.stream;

And then, the easiest part of all was hooking up the app (which I thought would be the most difficult) – btw I replaced irrelevant code with …:

class _BusPalState extends State<BusPal> with WidgetsBindingObserver {
  ...
  StreamSubscription themeListener;
  bool isDarkMode = false;

  @override
  void didChangeDependencies() {
    ...
    ApplicationPreferencesBloc _appPrefs =BlocProvider.of<ApplicationPreferencesBloc>(context);
    themeListener = _appPrefs.outDarkMode.listen((data) {
      setState(() {
        isDarkMode = data;
      });
    });

  @override
  void dispose() {
    ...
    themeListener.cancel();
    ...
  }

  @override
  Widget build(BuildContext context) {
  ThemeData theme = ThemeData(
      ...
      brightness: isDarkMode ? Brightness.dark :Brightness.light,
      ...
    );
    return MaterialApp(
      ...,
      theme: theme,
      ...
    );
}

And that is it. As I change from light to dark mode, Flutter takes care of the rest and even the transition looks really good.

I think I was worried as I don’t do too much setState, since I’m using bloc, but this just worked. It doesn’t break anything and it looks great.

This is why I love Flutter.

Here are some screenshots (in the interest of full disclosure, while I was looking some screens which would show light vs dark nicely, I found one other screen which doesn’t respect my theme – but it will be a quick and easy fix – test your apps properly!!).