StrictMode for Runtime Analysis on Android

Getting your Android app to compile is really only the first step: just because it compiles doesn’t mean it’ll work when you run your app. Thankfully, Android has invested in building analysis tools to catch some of the common Android-specific problems that bridge the gap between compilation errors and runtime crashes. Where lint provides static code analysis, StrictMode is the runtime equivalent: analyzing your app at the thread or virtual machine level and alerting you to potential problems.

Although traditionally used for performance-related checks, there are also a number of checks specifically surrounding some of the best practices for sharing files and accessing the network.

StrictMode Basics

To understand what StrictMode does and how it is used in your app, I’d strongly recommend watching our previous video on StrictMode. There we discuss a number of ThreadPolicy and VmPolicy configuration options for StrictMode, boiling down to detecting certain conditions at runtime and then reacting to those conditions with a penalty — be it logging, flashing the screen, or killing your app entirely.

VmPolicy’s detectFileUriExposure()

When sending files to other apps, it is really important that the other app can actually read your file. And it turns out that file:// Uris are actually a really bad way to do that. As explained in our Sharing Content post, using a file:// Uri means storage permissions and they’ll actually never work across users (such as in the case for Android for Work).

The detectFileUriExposure() StrictMode check (added in API 18 — Jellybean MR2) tries to catch those cases: looking for file:// Uris in any Intent your app sends out and then applying the penalty you’ve chosen for your VmPolicy. One thing to keep in mind is that this is a blanket ban on file:// Uris — while it’s technically safe to send file:// Uris between components in your own app, this check does not yet differentiate between who is receiving the Intent.

VmPolicy’s detectCleartextNetwork()

Security, particularly of your user’s data, doesn’t end in your app — it is just as important to secure communication with your server and, frankly, every connection your app makes — just because you trust your wireless access point and your network does not mean the same is true for all your users.

Android 6.0 Marshmallow adds a new StrictMode check in the form of detectCleartextNetwork() — a StrictMode check which ensures that all of the network traffic coming from your app is encrypted. There’s even a separate penaltyDeathOnCleartextNetwork() which will ensure your app is killed as soon as clear text network operations are detected (preventing any user data from leaking, even if you don’t want your app to be killed because of other StrictMode checks).

While this check does work on both IPv4 and IPv6 traffic, be it TCP or UDP, there is one caveat as per the documentation:

it may be subject to false positives, such as when STARTTLS protocols or HTTP proxies are used.

So keep that in mind if your app is using those techniques for your network traffic.

Simple analysis? I think not

As StrictMode works on the thread or VM level, it is at a much lower level than most runtime analysis can be. This has its pros and cons though — it is certainly extremely thorough, but the penalties available are hardcoded and inflexible. Alas, there are no custom handlers for StrictMode in the current API.

But don’t take that inflexibility as a death knell — just consider carefully what StrictMode checks you do use and make sure you enable them only on debug builds — the BuildConfig.DEBUG flag is helpful for those cases:

if (BuildConfig.DEBUG) {
// Enable StrictMode
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectFileUriExposure()
.detectCleartextNetwork()
.penaltyLog()
.penaltyDeath()
.build());
}

#BuildBetterApps

Follow the Android Development Patterns Collection for more!