The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Replacing App Code Dynamically

You write your app. You test your app. You upload your app to your favorite distribution channels. Your users download and use your app. You get bug reports and feature requests, to go along with your existing plans for the app.

So, you update your app. You test your app. You upload your app to your favorite distribution channels. Your users download and use your updated app. You get more bug reports and feature requests, to go along with your existing plans for the app.

So, once again, you update your app. You test your app. You upload your app to your favorite distribution channels. Your users download and use your updated app. You get still more bug reports and feature requests, to go along with your existing plans for the app.

Or, as the famous shampoo instructions go: lather, rinse, repeat.

Some developers have been working on breaking the cycle, specifically by delivering updates directly, bypassing the Play Store or other distribution channels. This offers a lot of potential for speed of updates and flexibility. It comes with some fairly substantial costs in terms of complexity and security. This chapter will explore some options in this area, so you can understand what is possible and what those costs and benefits are.

Prerequisites

Understanding this chapter requires that you have read the core chapters of this book.

The major example app in this book is based on the OkHttp3 sample app from the chapter on Internet access. The prose and code in this chapter will make a lot more sense if you are familiar with the Internet chapter’s examples.

The major example also uses TrustManagerBuilder, discussed in the chapter on SSL support.

Typical Objectives

There are any number of possible reasons why a developer may want to find ways to update the app’s code without having to ship a fresh APK.

Continuous Deployment

Many mobile developers have a history with Web development. Many firms have adopted a “continuous deployment” approach with their Web sites or Web apps. Here, rather than there being sporadic sweeping upgrades to the Web sites and apps, small changes are applied frequently, sometimes multiple times per day. Partially, the idea is to get good at deployment through repetition and practice, to reduce the odds of any given deployment running into a problem. Partially, the idea is to keep refreshing the Web site or Web app, so regular users get constant small improvements, as opposed to having to deal with big wrenching changes in UI or UX when major updates are deployed.

It stands to reason that firms with a history of continuous Web deployment would be interested in continuous mobile deployment as well. However, in Android, distributing a new APK is not seamless. While the work on the firm’s behalf may be small, every user has to apply the upgrade. Continuous deployment, from the user’s standpoint, means continuous aggravation, as the Play Store or other distribution channel pesters them about a new app update. Continuous deployment in Android is only practical when many of the upgrades can be done without replacing the APK.

Forced Immediate Updates

Many times, a mobile app is a peer of a Web app, both using the same server, just via different interfaces. The mobile app might be using REST or GraphQL endpoints to retrieve pure data, while the Web app is serving standard HTML/CSS/JavaScript.

One challenge in this case is keeping everything consistent with respect to business rules.

For example, perhaps the original business rule for passwords was “no longer than 8 characters”, because some manager was worried that the server might run out of disk space due to people having longer passwords. Eventually, security engineers pounded into the manager’s head that storing salted hashes of passwords in the database meant that the length of the password itself was immaterial in terms of server space. So, the business rule was amended to raise the password limit to 32 characters. On the Web app, this change might take seconds to implement and deploy. In the Android app, while the change might take seconds to implement, deployment poses two challenges:

  1. You have to ship a fresh APK with the changed code, and that takes time
  2. Not everybody updates the app right away, or ever, choosing to ignore those pesky notifications from the Play Store or other distribution channel

All the older editions of the app being used have the older business rule. So, a user goes into the Web site and changes their password to be 14 characters long… and now cannot log into the Android app, because their older Android app limits passwords to 8 characters.

Perhaps continuous deployment of new features and functions is beyond what you are interested in. However, this sort of business-rule change is the kind of thing that you might want to try to keep in sync between different editions of your app (Android, iOS, Web, etc.), and the coarse-grained nature of APK updates makes that difficult. Being able to deploy fresh business rules on the fly, without going through an APK update, would help.

Avoid Security Review

Not every reason for dynamically updating the code is a positive one.

The Play Store — and hopefully most other professional app distribution channels — performs some automated scans for malware. They do so on the APKs that are uploaded into the channels’ developer portals. Some, like the Play Store, also offer scanning services for APKs installed via other means (a.k.a., “sideloaded” apps), but once again, the scan is of the APK being installed.

A sophisticated malware distributor can apply the same basic techniques for deploying on-the-fly feature or business rule changes for deploying on-the-fly malware. The objective here is to bypass being detected by the APK security scans, simply by not having the malware be in the original APK, but rather via some dynamically-applied code that is loaded later.

The Challenges

The preview of this section apparently resembled a Pokémon.

The Scripting Solution

The preview of this section was whisked away by a shark-infested tornado.

The Hybrid Solution

The preview of this section may contain nuts.

The Patch Solution

The preview of this section is presently indisposed.

A DIY Solution

The preview of this section was lost in the sofa cushions.

Is Any Of This a Good Idea?

The preview of this section apparently resembled a Pokémon.