Almost all apps include some sort of content with the app package; it can be a database, image, or just plain text.
We can only get read-only access to bundled assets and resources but that is often all that is needed, as most app data comes from other sources such as the Internet or device sensors. We will create and add three basic types or resources by performing the following steps:
Assets
at the root of the project.Assets
folder and save some text into that file, for example, a file named MyAsset.txt
with the following contents:Hello Asset World!
raw
in the Resources
folder.raw
folder, again create and save any text file, for example, a file named MyRaw.txt
with the following contents:Hello Raw World!
values
under the Resources
folder.values
folder, create a new XML file with the Android-style resources, for example, a file named MyResources.xml
with the following content:<?xml version="1.0" encoding="UTF-8" ?> <resources> <string name="myString">Hello Resource World!</string> </resources>
Once we have the resources created, we can now start writing code to access them:
Resources
property:string stringValue = Resources.GetString(Resource.String.myString);
Stream
element:using (Stream raw = Resources.OpenRawResource(Resource.Raw.MyRaw)) using (StreamReader reader = new StreamReader(raw)) { string rawValue = reader.ReadToEnd(); }
Stream
instance:using (Stream asset = Resources.Assets.Open("MyAsset.txt")) using (StreamReader reader = new StreamReader(asset)) { string assetValue = reader.ReadToEnd(); }
There are three main types of app content: assets, raw resources, and special resources.
Special resources, or resources, are the most common and easiest to use. These resources can be accessed in layout files and in code. There are two main groups of special resources; there are Android-specific resources, such as animations, layouts, and menus, and there are value resources, such as strings, Booleans, and integers.
These value resources are accessed via various getter methods on the Resources
property, and they return the value of the resource directly. They are stored in the values
resource folder and are structured as basic XML elements with a name attribute.
Each resource folder can have a suffix that is used to determine the resource file that is to be loaded. There are many different suffixes that can be used, and a full list can be found on the Android developer website at http://developer.android.com/guide/topics/resources/providing-resources.html.
If there are two folders with the same name and different suffixes, such as values
and values-land
, Android will correctly select the appropriate file when the Resources
property is used. This feature is especially useful for creating alternative resources, such as layouts, menus, and values based on the device characteristics, such as orientation and screen size, as well as device settings, such as language or culture.
Another benefit of using resources is the fact that the compiler generates a type that contains all the various resources. For example, if we create a string resource with the name myString
, the compiler will generate a field named myString
in the String
type nested inside the Resource
type. This provides compile time checking and resource validation allowing us to write Resource.String.myString
when accessing the string resource, instead of having to use string keys.
All resource types, from animations to values, have the benefit of allowing the Android runtime to select a variation of a resource, making resources very useful. The same is true for raw resources, which are just a type of resource. One main difference is that raw resources allow us to specify any resource type as a resource, such as the database files, binary data files, and ZIP files. Although these types aren't used by Android, we can use them in our code.
We access raw resource files through the OpenRawResource()
method on the Resources
property, passing in the ID of the raw resource. This method returns a stream with which we can work as we would work on any other stream.
Assets, on the other hand, are quite different. They are simply are files that bundled in the app package and stored in the Assets
folder. Using assets allows us to dynamically load and list the files at runtime, but we have to do the work ourselves. Assets can also be organized into a folder hierarchy, which is not supported by resources.
Also, some features are only available to assets; these features include using a custom typeface or loading cascading style sheets. The reason for this is that assets actually have a URI for accessing any particular file: file:///android_asset/<some-file-name>
(note the three slashes). We can load pages into the web browser component using this URI, and the browser can resolve the resource paths automatically.
Accessing assets is done through the AssetManager
instance, accessed either through the Assets
property or the Resources.Assets
property. We use the Open()
method and pass in a path relative to the assets
folder. Just as we did with raw resources, we obtain a stream that we use to read the contents of a particular asset.