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.


Assets, Files, and Data Parsing

Android offers a few structured ways to store data, notably SharedPreferences and local SQLite databases. And, of course, you are welcome to store your data “in the cloud” by using an Internet-based service. We will get to all of those topics shortly.

Beyond that, though, Android allows you to work with plain old ordinary files, either ones baked into your app (“assets”) or ones on so-called internal or external storage.

To make those files work — and to consume data off of the Internet — you will likely need to employ a parser. Android ships with several choices for XML and JSON parsing, in addition to third-party libraries you can attempt to use.

This chapter focuses on assets, files, and parsers.

Packaging Files with Your App

Let’s suppose you have some static data you want to ship with the application, such as a list of words for a spell-checker. Somehow, you need to bundle that data with the application, in a way you can get at it from Java code later on, or possibly in a way you can pass to another component (e.g., WebView for bundled HTML files).

There are three main options here: raw resources, XML resources, and assets.

Raw Resources

One way to deploy a file like a spell-check catalog is to put the file in the res/raw directory, so it gets put in the Android application .apk file as part of the packaging process as a raw resource.

To access this file, you need to get yourself a Resources object. From an activity, that is as simple as calling getResources(). A Resources object offers openRawResource() to get an InputStream on the file you specify. Rather than a path, openRawResource() expects an integer identifier for the file as packaged. This works just like accessing widgets via findViewById() – if you put a file named words.xml in res/raw, the identifier is accessible in Java as R.raw.words.

Since you can only get an InputStream, you have no means of modifying this file. Hence, it is really only useful for static reference data. Moreover, since it is unchanging until the user installs an updated version of your application package, either the reference data has to be valid for the foreseeable future, or you will need to provide some means of updating the data. The simplest way to handle that is to use the reference data to bootstrap some other modifiable form of storage (e.g., a database), but this makes for two copies of the data in storage. An alternative is to keep the reference data as-is but keep modifications in a file or database, and merge them together when you need a complete picture of the information. For example, if your application ships a file of URLs, you could have a second file that tracks URLs added by the user or reference URLs that were deleted by the user.

XML Resources

If, however, your file is in an XML format, you are better served not putting it in res/raw/, but rather in res/xml/. This is a directory for XML resources – resources known to be in XML format, but without any assumptions about what that XML represents.

To access that XML, you once again get a Resources object by calling getResources() on your Activity or other Context. Then, call getXml() on the Resources object, supplying the ID value of your XML resource (e.g., R.xml.words). This will return an XmlResourceParser, which implements the XmlPullParser interface. We will discuss how to use this parser, and the performance advantage of using XML resources, later in this chapter.

As with raw resources, XML resources are read-only at runtime.

Assets

Your third option is to package the data in the form of an asset. You can create an assets/ directory in your source set (e.g., src/main/assets), then place whatever files you want in there. Those are accessible at runtime by calling getAssets() on your Activity or other Context, then calling open() with the path to the file (e.g., assets/foo/index.html would be retrieved via open("foo/index.html")). As with raw resources, this returns an InputStream on the file’s contents. And, as with all types of resources, assets are read-only at runtime.

One benefit of using assets over raw resources is the file:///android_asset/ Uri prefix. You can use this to load an asset into a WebView. For example, for an asset located in assets/foo/index.html within your project, calling loadUrl("file:///android_asset/foo/index.html") will load that HTML into the WebView.

Note that assets are compressed when the APK is packaged. Unfortunately, on Android 1.x/2.x, this compression mechanism has a 1MB file size limit. If you wish to package an asset that is bigger than 1MB, you either need to give it a file extension that will not be compressed (e.g., .mp3) or actually store a ZIP file of the asset (to avoid the automatic compression) and decompress it yourself at runtime, using the standard java.util.zip classes. This restriction was lifted with Android 3.0, and so if your minSdkVersion is 11 or higher, this will not be an issue for you.

Files and Android

The preview of this section is [REDACTED].

Working with Internal Storage

The preview of this section is sleeping in.

Working with External Storage

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

Removable Storage

The preview of this section was accidentally identified as an Android 'tasty treat' by the Cookie Monster.

Multiple User Accounts

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

Linux Filesystems: You Sync, You Win

The preview of this section will not appear here for a while, due to a time machine mishap.

StrictMode: Avoiding Janky Code

The preview of this section was abducted by space aliens.

Files, and Your Development Machine

The preview of this section is presently indisposed.

XML Parsing Options

The preview of this section took that left turn at Albuquerque.

JSON Parsing Options

The preview of this section is off trying to sweet-talk the Khaleesi into providing us with a dragon.

Using Files with Implicit Intents

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

Visit the Trails!

The preview of this section is out seeking fame and fortune as the Dread Pirate Roberts.