KA Engineering

KA Engineering

We're the engineers behind Khan Academy. We're building a free, world-class education for anyone, anywhere.

Subscribe

Latest posts

Let's Reduce! A Gentle Introduction to Javascript's Reduce Method

Josh Comeau on July 10

Creating Query Components with Apollo

Brian Genisio on June 12

Migrating to a Mobile Monorepo for React Native

Jared Forsyth on May 29

Memcached-Backed Content Infrastructure

Ben Kraft on May 15

Profiling App Engine Memcached

Ben Kraft on May 1

App Engine Flex Language Shootout

Amos Latteier on April 17

What's New in OSS at Khan Academy

Brian Genisio on April 3

Automating App Store Screenshots

Bryan Clark on March 27

It's Okay to Break Things: Reflections on Khan Academy's Healthy Hackathon

Kimerie Green on March 6

Interning at Khan Academy: from student to intern

Shadaj Laddad on Dec 12, 2016

Prototyping with Framer

Nick Breen on Oct 3, 2016

Evolving our content infrastructure

William Chargin on Sep 19, 2016

Building a Really, Really Small Android App

Charlie Marsh on Aug 22, 2016

A Case for Time Tracking: Data Driven Time-Management

Oliver Northwood on Aug 8, 2016

Time Management at Khan Academy

Several Authors on Jul 25, 2016

Hackathons Can Be Healthy

Tom Yedwab on Jul 11, 2016

Ensuring transaction-safety in Google App Engine

Craig Silverstein on Jun 27, 2016

The User Write Lock: an Alternative to Transactions for Google App Engine

Craig Silverstein on Jun 20, 2016

Khan Academy's Engineering Principles

Ben Kamens on Jun 6, 2016

Minimizing the length of regular expressions, in practice

Craig Silverstein on May 23, 2016

Introducing SwiftTweaks

Bryan Clark on May 9, 2016

The Autonomous Dumbledore

Evy Kassirer on Apr 25, 2016

Engineering career development at Khan Academy

Ben Eater on Apr 11, 2016

Inline CSS at Khan Academy: Aphrodite

Jamie Wong on Mar 29, 2016

Starting Android at Khan Academy

Ben Komalo on Feb 29, 2016

Automating Highly Similar Translations

Kevin Barabash on Feb 15, 2016

The weekly snippet-server: open-sourced

Craig Silverstein on Feb 1, 2016

Stories from our latest intern class

2015 Interns on Dec 21, 2015

Kanbanning the LearnStorm Dev Process

Kevin Dangoor on Dec 7, 2015

Forgo JS packaging? Not so fast

Craig Silverstein on Nov 23, 2015

Switching to Slack

Benjamin Pollack on Nov 9, 2015

Receiving feedback as an intern at Khan Academy

David Wang on Oct 26, 2015

Schrödinger's deploys no more: how we update translations

Chelsea Voss on Oct 12, 2015

i18nize-templates: Internationalization After the Fact

Craig Silverstein on Sep 28, 2015

Making thumbnails fast

William Chargin on Sep 14, 2015

Copy-pasting more than just text

Sam Lau on Aug 31, 2015

No cheating allowed!!

Phillip Lemons on Aug 17, 2015

Fun with slope fields, css and react

Marcos Ojeda on Aug 5, 2015

Khan Academy: a new employee's primer

Riley Shaw on Jul 20, 2015

How wooden puzzles can destroy dev teams

John Sullivan on Jul 6, 2015

Babel in Khan Academy's i18n Toolchain

Kevin Barabash on Jun 22, 2015

tota11y - an accessibility visualization toolkit

Jordan Scales on Jun 8, 2015

Meta

Starting Android at Khan Academy

by Ben Komalo on Feb 29, 2016

The journey of a thousand miles...

In March, 2015—almost 1 year ago to the day—we started developing our first Android app at Khan Academy.

first commit A single step

By then, Android was on version 5.0 Lollipop and nearing 1 billion active monthly users, representing around 8 out of every 10 phones worldwide. Our mission is to provide a free world-class education for anyone, anywhere, so we had to provide a great learning experience on this platform: Android reaches billions of users, many of whom rely on their phone as their only computing device.

We launched version 1.0 of our app on the Play Store in August 2015, having learned a ton about Android development as a team. There’s plenty more ahead, but we thought now would be a good time to share a bit of our journey.

Libraries and foundations

Ironically, being late to the Android game came with its advantages. The platform had evolved significantly by early 2015, and we were able to target API level 16 and higher while still reaching 95% of users. Furthermore, the Support Library had provided fantastic new utilities like the RecyclerView and CoordinatorLayout, making modern Android “Material UI” significantly easier to build. The vibrant open-source community had also gifted us with plenty of useful libraries like Retrofit and Picasso, which we weren’t shy about adopting.

Of course, good utility libraries are not enough: we knew we needed strong foundations throughout our code. We enforced separation of concerns right off the bat with two separate modules in our app: an Android-agnostic “core” module, and an “app” module for Android-specific application code:

Our core module deals with tasks like fetching data, storing data, and transforming that data, while our app module reads that data, shows it to the user, and writes changes. Besides keeping our code clearer and more organized, this separation delivered a variety of secondary benefits. For instance, we can run our core module on a vanilla JVM without any Android runtime libraries or special mocking, making tests easier to write and also significantly faster to run – fast enough that we can run them as a pre-commit check before sending out a change revision:

test run 1290 tests in ~3s ⚡️

Those core tests can run on our CI server without having to deal with emulators, which have proven to be difficult to maintain. This has made us more confident in our tests, instilled a test-heavy culture in our development team, and allowed us to run more extensive end-to-end tests pretty easily. For example, one test tries to download and process our content library; we run this continuously to warn the content and server teams in case they accidentally change an API in a backwards-incompatible way.

Modules add some complexity to the build setup, but the relatively small cost has been well worth paying. We’ve since added a few more small modules, though the broader separation of “core” from “app” delivered the most benefit. In the future, as we consider cross-platform code sharing solutions, we may adapt the core module to be shared across our iOS and Android apps (more on that below).

Tools

In addition to having solid architectural foundations, we wanted to make the surrounding developer experience great. We had invested in various kinds of tools for our web app infrastructure, and we wanted to sharpen our tools on Android too.

We’re still far from the ideal scenario: deploying and testing UI changes end-to-end still takes too long. But tools like Facebook’s Stetho provide a great debugging experience that can save lots of time once the app is on a device. All our network requests use OkHttp, and with the right configuration, Stetho can inspect them.

We’ve also created a custom DumperPlugin, which runs arbitrary commands in our app via the command line. Here we force our app to sync new content from the server:

$ dumpapp ka-debug update-topic-tree
Kicked off service to update topic tree

For automating releases, we use Triple-T’s Gradle plugin to upload APKs to the Play Store. Our CI server publishes a new build from master every night to our alpha channel (internal employees). We use Git tags to track the version code; each build increments the number and makes a new tag (though we bump the marketing-oriented “version name” manually).

We’re still building out lots of tooling to make things easier, including our still-nascent linting tools. If you’ve got favorites to share, we’d love to chat.

Many miles ahead

Our team has learned a lot in the last year. Not only have we come a long way in building out our technical capabilities, but our fantastic design team has also adapted to thinking about new features in a holistic fashion; all three platforms (web, iOS and Android) are considered up front and designs are typically done simultaneously so the learning experience can make sense regardless of how you access it.

That being said, we’re still a fairly small team, and re-building a feature three times is costly. We’re actively exploring possibilities for mobile code sharing strategies, but have yet to find a satisfactory solution. There’s also much to learn as a broader team about coordinating work across three platforms. Should we build features on one platform before starting work on the rest, for validation’s sake? How should we best enable our content creators to make compelling experiences that are flexible and can adapt to the learner’s device?

Despite the challenges ahead, we’re excited to be building on Android. More importantly, we’re excited about the possibility of reaching vast numbers of learners through the platform. There’s a lot more we’re working on, like bringing the interactive exercises and other features learners have enjoyed on our website and in our iOS app to Android. We’re also thinking about ways to deliver our content in extremely limited connectivity environments, and other situations which can benefit from a native Android app. Excited about empowering learners using mobile technology? Come join us.