Mobile Apps — iPlayer tech on the move

Ross Harper
BBC Product & Technology
10 min readSep 8, 2017

An insight into the tech stack that powers iPlayer’s mobile apps

Introduction

In “The Tech Stack that powers BBC iPlayer”, we gave a high-level introduction to the product, the platforms it runs on, and the technologies that support it. In this post, I’d like to give an insight into some of the specific technologies used, and challenges faced, by the iPlayer Mobile Apps engineering team in pursuit of our goals to iterate fast and maximise audience reach by continuously delivering to a wide range of mobile devices.

In our team, we produce the BBC iPlayer and BBC iPlayer Kids apps for Android and iOS. These apps have a combined total of over 45 million downloads since we launched the first iPlayer mobile app in early 2011 — just over three years after the BBC iPlayer service first launched in the UK. The apps serve over 4.5 million unique browsers in an average week, watching over 6.5 million hours of live, on-demand, and downloaded BBC content, across myriad mobile phones and tablets.

High-Level Architecture

The mobile iPlayer apps are front-end clients of the BBC iPlayer service. The apps rely on services that can be grouped into three broad categories:

  • Identity & Sign-in
  • Catalogue and Metadata
  • Media Delivery

The diagram below shows a simplified overview of these broad service categories.

This is a gross simplification; there’s a lot more to the system architecture that powers iPlayer than is illustrated here, but these are the basic services that the iPlayer app communicates with directly and requires to function. In reality, the back-end services that the iPlayer apps rely on are much more decomposed than a single box on a diagram can illustrate.

The services that power iPlayer are covered in more detail in Kit’s post: “The Tech Stack that powers BBC iPlayer

What’s Special About Mobile Apps?

Developing native mobile applications has a few differences and raises a few challenges that aren’t faced by all applications that run across web platforms.

Platform Diversity

In supporting the iOS and Android mobile operating systems — and by extension, Amazon’s FireOS — there are myriad diverse devices across which our software must run, with a multitude of screen sizes, platform/OS versions/device bugs, quirks, and capability differences. This presents a challenge for testing: how do we get sufficient coverage of these variants to find problems?

Fragmentation isn’t a problem that is entirely unique to native mobile apps—web applications also need to work across various browsers — but the degree of fragmentation across a greater variety of devices and operating system versions make this more of a challenge on mobile. Our iPlayer on TV colleagues also have to face a similar challenge: like us, their app has to run on thousands of different device variants.

At the time of writing, we support iOS 8–11 and Android 4.1–8.0, which is effectively 13 operating system versions for iPlayer mobile.

(In this illustration, OS versions are segmented based on where API and behaviour changes are usually introduced — for iOS this is on major version number increments; for Android this is usually on both major & minor version number increments)

Because we support some older operating systems, we can’t always adopt the latest OS features immediately. For example, on iOS we couldn’t support UI size classes for designing UI layouts until we dropped iOS 7, which made creating UI layouts more difficult and complex in the interim. While Google solve many of these problems with the Android Support Library — which provides new features in library form so that they can be included in the app and used on older operating systems — Android also presents a similar challenge for features that are baked into the operating system itself.

When deciding to deprecate support for older operating systems, we have to consider the size of our audience that is using them, and the adoption rates for newer operating systems. For example, we see faster adoption of newer operating systems and fewer users on legacy operating systems in the iOS ecosystem (48% of our Android audience is using an OS that is more than two years old, compared with 3% of our iOS audience).

Deployment

At the BBC, many teams employ Continuous Delivery. In practice, this means something slightly different to a mobile app team than it does to a web app/service team.

“Continuous delivery (CD) is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time.” — Wikipedia

For a web service team, this might mean that a change is running in a test environment very shortly after being committed to source control, and shortly thereafter (after test & verification) can be pushed live. If the changes are bad, they can be rolled-back easily, or a new version quickly deployed over the top. Because the development team is in control of the computing resource that runs the software, they have complete control over what version of software the end-user is being served by.

A mobile app is different in that it is deployed to devices in the end users’ control — once the code is deployed and downloaded by the user, the development team have limited ability to change the code that is executed. Changes typically rely on new versions of the app being distributed and adopted by the end user.

Furthermore, the end user may not even notice deployments to web services and the change associated with them (unless there are obvious UX changes). But for mobile apps, even in today’s world of automatic app updates, users tend to notice when an app needs updating. We’ve noticed that there’s some friction with this and have to find the right balance between delivering regularly in short cycles, and not upsetting users with app updates that are too frequent.

Currently we release to the public on a cycle of approximately 4 weeks for minor version updates, and occasionally in-between for patch releases (although this cycle length varies quite a bit based on various demands and factors). Internally, we aim for a much shorter cycle time for developing small stories that can be tested, distributed to stakeholders, and iterated upon in hours and days rather than weeks.

Deployment of iPlayer apps internally and to public distribution

We currently use Jenkins — hosted on custom infrastructure—as a continuous integration and build pipeline tool which automatically tests and builds the apps upon every commit to source control (GitHub), and uploads those builds to HockeyApp.

HockeyApp is used for distribution to testers and internal stakeholders, and crash report collection from our test and production apps.

Developers usually aim to commit to master regularly throughout the day (“10 minute commits”). This, combined with our continuous integration environment means changes can be in testers’ (and stakeholders’) hands within minutes when there is something of value to test.

When we release to the public, we upload the app to the various platform distribution services: Apple App Store, Amazon App Store, and the Google Play Store.

The deployed nature of mobile apps means that there can be many different versions of the app in use by the audience at any one time. Occasionally we have reached up to 61 versions of iPlayer and iPlayer Kids across iOS and Android—which is unusual!

We have the means to mitigate the legacy of old app versions via our remote configuration system. Through this, we have coarse-grained control to indicate to users that an update is available (“suggested upgrade”) and for versions that we cannot support anymore, we have the ability to “force upgrade” them, effectively disabling the app. This system also has finer-grained control built-in, that allows us to enable/disable features via “feature flags” so that we can disable certain backend interactions when reacting to operational issues. For example, if we release an app that is misbehaving and causing increased load on the back-end, we can degrade one part of the app in the offending version while we prepare a patch release.

Our Technology Stack

We develop our apps natively for iOS and Android using the platform SDKs provided by Apple and Google (as opposed to using cross-platform development technologies such as Xamarin, Cordova, or React Native).

Programming Languages

Given the iPlayer codebase is over 6 years old, most of the code we have today is written in Java for the Android platform and Objective-C for the iOS platform.

It is clear that Swift will be the language of choice for developing on Apple platforms in the future. Now that Swift is maturing and stabilising as a language, we have started writing some new code using it. Furthermore, some of our dependencies are now arriving as libraries written in Swift also.

Similarly, Kotlin has been rising in popularity in the wider Android community, and this year it was announced at Google I/O that it will be supported as a first-class language for Android development. Whilst we haven’t written any production code in Kotlin just yet, a number of our developers have been experimenting with it for a couple of years and are very excited about it.

For both platforms, we will need to carefully transition to using these new languages, ensuring we adopt good modularisation practices to avoid peppering new language code all over the codebase. Initially we aim to adopt these new technologies by writing new features in them as new modules, with well-defined boundaries, and rewrite/refactor old modules where necessary (rather than starting from scratch and rewriting the entire product in these new languages).

One Codebase, Two Products

In late 2015, we began work to create the BBC iPlayer Kids app. iPlayer Kids shares the same back-end architecture as iPlayer, and has largely similar features, tailored for a younger audience.

We could have started a completely new project and built this app from scratch, but that probably would have taken too long and we would have not got the app to market in time to meet our aspirations. We were challenged to reuse what we already have to help us build this new product. We chose to do this by building two products from a common codebase.

At a high-level, this resulted in us splitting the original monolithic iPlayer app codebase into three modules: one for each of the app products that would be built from the codebase, and a common module that contains code shared by both applications.

Build-time configuration allows us to run automated tests for each module independently, and to build each app independently.

(I’ve talked about a single conceptual codebase here. In reality, there are two codebases: one for Android and one for iOS. But, we applied this pattern to both platforms’ codebases)

Technologies We Build Upon

We use a number of third-party and open-source libraries in the apps, as well as libraries provided by our other teams in the BBC, such as our core BBC Mobile Platform team, who contribute code that is used across the BBC mobile app estate.

(This is just a high-level overview of the main libraries we use — it does not represent all of the code that makes up iPlayer)

Some of our core capabilities are delivered as libraries that are shared across multiple apps. Some of the key ones are:

  • SMP (Standard Media Player) — provides playback of Simulcast, VoD, and Downloaded video. It is built upon ExoPlayer on Android and AVPlayer on iOS.
  • Downloader—manages the downloading of video assets (and associated subtitles) for our “Downloads” feature. It also manages the interaction with a third-party DRM Agent library that provides content protection for the downloaded media.
  • AuthToolkit—manages the sign-in process, and making authenticated network requests for personalised data.
  • Echo—manages statistics reporting, providing an abstraction from the back-end analytics services that app statistics are reported to.

We also use a number of third-party libraries, for example:

  • Google Cast—allows us to “Cast” video content to TV screens that either have Cast built-in, or via a connected Chromecast device. (iOS also has built-in AirPlay support).
  • Realm—an object database that is used for storing local playback positions for downloads while a user is playing content offline. This database is synced with the user’s account when online, so that progress through a programme/series can be maintained across devices that the user is signed-in to.
  • HockeyApp—for reporting crashes from test and production builds.
  • GSON—JSON parsing on Android.
  • Picasso—image loading on Android.
  • OkHttp—HTTP client used under-the-hood on Android.

What’s Next?

Increasingly, we are adding personalisation features, such as cross-device “pick-up a programme”, the “Watching” list, recommendations based on what you’ve watched, and “My Channel” in the home stream. As part of a wider strategy to deliver a more personal BBC, there will be further focus on personalising the service that iPlayer provides to its users. This is what will form our main focus over the next year, in collaboration with our colleagues in iBL and across the BBC.

Join Us

If you’re interested and excited by the technical challenges we’re facing, we’re always looking for driven engineers to join us. We’re not prescriptive about what languages you know since we think a good engineer can learn quickly. That said, experience with iOS, Android, JavaScript or Java would definitely give you a head start.

In the Mobile iPlayer team we’re currently hiring for Software Engineers and Senior Software Engineers.

You can see all our job listings for BBC iPlayer here by searching for iPlayer.

--

--