Exploring Android’s Content Providers
Android devices ship with a number of built-in applications, many of which expose their data as content providers.Your application can access content provider data from a variety of sources.You can find the content providers included with Android in the package android.provider.Table 11.1 lists some useful content providers in this package. Table 11.1 Useful Built-In Content Providers Provider Purpose MediaStore Audio-visual data on the phone and external storage CallLog Sent and received calls Browser Browser history and bookmarks ContactsContract Phone contact database or phonebook Settings System-wide device settings and preferences UserDictionary A dictionary of user-defined words for use with predictive text input Sharing Data Between Applications with Content 260 Chapter 11 Sharing Data Between Applications with Content Providers Now let’s look at the individual content providers in more detail. Tip Many of the code examples provided in this section are taken from the SimpleContentProvider application. This source code for the SimpleContentProvider application is provided for download on the book website.
Using the MediaStore Content Provider
You can use the MediaStore content provider to access media on the phone and on external storage devices.The primary types of media that you can access are audio, images, and video.You can access these different types of media through their respective content provider classes under android.provider.MediaStore. Most of the MediaStore classes allow full interaction with the data.You can retrieve, add, and delete media files from the device.There are also a handful of helper classes that define the most common data columns that can be requested. Table 11.2 lists some commonly used classes that you can find under android.provider.MediaStore. The following code demonstrates how to request data from a content provider.A query is made to the MediaStore to retrieve the titles of all the audio files on the SD card of the handset and their respective durations.This code requires that you load some audio files onto the virtual SD card in the emulator. String[] requestedColumns = { MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DURATION }; Table 11.2 Common MediaStore Classes Class Purpose Video.Media Manages video files on the device Images.Media Manages image files on the device Images.ThumbNails Retrieves thumbnails for the images Audio.Media Manages audio files on the device Audio.Albums Manages audio files organized by the album Audio.Artists Manages audio files by the artist who created them Audio.Genres Manages audio files belonging to a particular genre Audio.Playlists Manages audio files that are part of a particular playlist Exploring Android’s Content Providers 261 Cursor cur = managedQuery( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, requestedColumns, null, null, null); Log.d(DEBUG_TAG, “Audio files: “ + cur.getCount()); Log.d(DEBUG_TAG, “Columns: “ + cur.getColumnCount()); String[] columns = cur.getColumnNames(); int name = cur.getColumnIndex(MediaStore.Audio.Media.TITLE); int size = cur.getColumnIndex(MediaStore.Audio.Media.DURATION); cur.moveToFirst(); while (!cur.isAfterLast()) { Log.d(DEBUG_TAG, “Title” + cur.getString(name)); Log.d(DEBUG_TAG, “Length: “ + cur.getInt(size) / 1000 + “ seconds”); cur.moveToNext(); } The MediaStore.Audio.Media class has predefined strings for every data field (or column) exposed by the content provider.You can limit the audio file data fields requested as part of the query by defining a string array with the column names required. In this case, we limit the results to only the track title and the duration of each audio file. We then use a managedQuery() method call.The first parameter is the predefined URI of the content provider you want to query (in most cases, the primary external storage is the SD card).The second parameter is the list of columns to return (audio file titles and durations).The third and fourth parameters control any selection filtering arguments, and the fifth parameter provides a sort method for the results.We leave these null, as we want all audio files at this location. By using the managedQuery() method, we get a managed Cursor as a result.We then examine our Cursor for the results.
Using the CallLog Content Provider
Android provides a content provider to access the call log on the handset via the class android.provider.CallLog.At first glance, the CallLog might not seem to be a useful provider for developers, but it has some nifty features.You can use the CallLog to filter recently dialed calls, received, and missed calls.The date and duration of each call is logged and tied back to the Contact application for caller identification purposes. The CallLog is a useful content provider for customer relationship management (CRM) applications.The user can also tag specific phone numbers with custom labels within the Contact application. To demonstrate how the CallLog content provider works, let’s look at a hypothetical situation where we want to generate a report of all calls to a number with the custom 262 Chapter 11 Sharing Data Between Applications with Content Providers labeled HourlyClient123.Android allows for custom labels on these numbers, which we leverage for this example: String[] requestedColumns = { CallLog.Calls.CACHED_NUMBER_LABEL, CallLog.Calls.DURATION }; Cursor calls = managedQuery( CallLog.Calls.CONTENT_URI, requestedColumns, CallLog.Calls.CACHED_NUMBER_LABEL + “ = ?”, new String[] { “HourlyClient123” } , null); Log.d(DEBUG_TAG, “Call count: “ + calls.getCount()); int durIdx = calls.getColumnIndex(CallLog.Calls.DURATION); int totalDuration = 0; calls.moveToFirst(); while (!calls.isAfterLast()) { Log.d(DEBUG_TAG, “Duration: “ + calls.getInt(durIdx)); totalDuration += calls.getInt(durIdx); calls.moveToNext(); } Log.d(DEBUG_TAG, “HourlyClient123 Total Call Duration: “ + totalDuration); This code is similar to the code shown for the MediaStore audio files.Again, we start with listing our requested columns: the call label and the duration of the call.This time, however, we don’t want to get every call in the log, only those with a label of HourlyClient123.To filter the results of the query to this specific label, it is necessary to specify the third and fourth parameters of the managedQuery() call.Together, these two parameters are equivalent to a database WHERE clause.The third parameter specifies the format of the WHERE clause with the column name with selection parameters (shown as ?s) for each selection argument value.The fourth parameter, the String array, provides the values to substitute for each of the selection arguments (?s) in order as you would do for a simple SQLite database query. As before, the Activity manages the Cursor object lifecycle.We use the same method to iterate the records of the Cursor and add up all the call durations.