For Android APIs, Think Streams, Not Files

If you are creating a library for Android — JAR, Android library project, etc. — if you want your public API to take File objects as parameters, that’s fine.

However, those should be convenience methods, for the “real” API that takes streams as parameters.

There are many data sources in Android that surface themselves as streams instead of files:

  • Raw resources are available as InputStreams, not files

  • Assets are available as InputStreams, not files

  • content:// Uri values that you handle with ContentResolver are available as InputStreams (and sometimes OutputStreams), not files

  • Encrypted stores, like IOCipher, will sometimes work with streams instead of files

  • Network operations, such as HTTPS transfers, work with streams instead of files

  • And so on

A Java File object is a useful handle to a bit of persistent data, but it is only that: a handle. Even with a File, often you are going to be working with streams, or working with layers atop of streams (e.g., InputStreamReader).

This extends Google’s new recommendations, where they are steering you away from sending out file:/// Uri values in Intents, in favor of FileProvider:

Apps should generally avoid sending raw filesystem paths across process boundaries, since the receiving app may not have the same access as the sender.

So, I’m not saying that your API should not support File objects. Just be sure to support InputStream and OutputStream options as well, to allow the caller to have more control over where the data comes from.

Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!