Enhancing Applications Using Content Providers Android

The concept of a content provider is complex and best understood by working through an example. The Pet Tracker series of applications from the previous chapter are nice and all, but the application could really use some graphics. Wouldn’t it be great if we could include photos for each pet record? Well, let’s do it! There’s only one catch: We need to access pictures provided through another application on the Android system—the Media Store application.

In Figure, you can see the results of extending the previous Pet Tracking projects using the Media Store content provider.

Pet Tracker application: Entry Screen (left, middle) and Pet Listing Screen (right).

Pet Tracker application: Entry Screen (left, middle) and Pet Listing Screen (right)

Accessing Images on the Device

Now that you can visualize what adding photos looks like,let’s break down the steps needed to achieve this feature. The PetTracker3 application has the same basic structure as our previous Pet Tracker projects, with several key differences:

  • On the Pet Entry screen, you can choose a photo from a Gallery control, which displays all the images available on the SD card, or simulated SD card on the emulator, by accessing the MediaStore content provider (left).
  • On the Pet Listing screen, each picture is displayed in the ListView control (right), again using the MediaStore content provider to access specific images.
  • On the Pet Listing screen, each item in the ListView (right) is a custom layout. The new PetTracker3 sample application provides two methods to achieve this: by inflating a custom layout XML file, and by generating the layout programmatically.
  • Internally,we extend BaseAdapter on two different occasions to successfully bind pet data to the ListView and Gallery with our own custom requirements.
  • Finally,we provide custom implementations of the methods for Simple CursorAdapter .CursorToString Converter and FilterQuery Provider to allow the AutoComplete TextView to bind directly to the internal SQLite database table called pet_types (middle), and change the AutoComplete TextView behavior to match all substrings, not only the beginning of the word. Although we won’t go into detail about this in the subsequent text, check out the sample code for more information on the specific details of implementation.

First, we need to decide where we are going to get our photos. We can take pictures with the built-in camera and access those, but for simplicity’s sake with the emulator (which can only take “fake pictures”), it is easier if we download those cute, fuzzy pictures from the browser onto the SD card and access them that way.

Locating Content on the Android System Using URIs

Most access to content providers comes in the form of queries: a list of contacts, a list of bookmarks, a list of calls, a list of pictures, and a list of audio files. Applications make these requests much as they would access a database, and they get the same type of structured results. The results of a query are often iterated through using a cursor. However, instead of crafting queries, we use URIs.

You can think of a URI as an “address” to the location where content exists. URI addresses are hierarchical. Most content providers, such as the Contacts and the Media Store, have URI addresses predefined. For example, to access images the External Media Device (also known as the SD card), we use the following URI defined in the Media Store.Images.Media class:


Retrieving Content Provider Data with managedQuery()

We can query the Media Store content provider using the URI much like we would query a database. We now use the managedQuery() method to return a managed Cursor containing all image media available on the SD card.

We have retrieved the records for each piece of media available on the SD card.

Now we have this Cursor, but we still have some legwork to get our Gallery widget to display the individual images.

Data-Binding to the Gallery Control

We need to extend the BaseAdapter class for a new type of data adapter called ImageUriAdapter to map the URI data we retrieved to the Gallery widget. Our custom Image UriAdapter maps the Cursor results to an array of GalleryRecord objects, which correspond to the child items within the Gallery widget. Although the code for the ImageUriAdapter is too long to show here, we go over some of the methods you must implement for the adapter to work properly.

  • The ImageUriAdapter() constructor is responsible for mapping the Cursor to an array of GalleryRecord objects, which encapsulate the base URI and the individual image’s id. The image id is tacked on to the end of the URI, resulting in a fully qualified URI for the individual image.
  • The getItem() and getItemId() methods return the unique identifier for the specific image. This is the value we require when the user clicks on a specific image within the Gallery. We save this information in our database so that we know which image corresponds to which pet.
  • The getView() method returns the custom View widget that corresponds to each child View within the Gallery. In this case, we return an ImageView with the corresponding image. We set each view’s Tag property to the associated GalleryRecord object, which includes all our Cursor information we mapped for that record. This is a nifty trick for storing extra information with widgets for later use.

After all this magic has been implemented, we can set our newly defined custom adapter to the adapter used by the Gallery with our new Cursor.

Retrieving Gallery Images and Saving Them in the Database

Notice that we added two new columns to our SQLite database: the base URI for the image and the individual image id, which is the unique identifier tacked to the end of the URI. We do not save the image itself in the database, only the URI information to retrieve it.

When the user presses the Save button on the Pet Entry screen, we examine the Gallery item selected and extract the information we require from the Tag property of the selected View, like this:

We can then save our Pet Record as we have before.

Displaying Images Retrieved from the SD Card Using URIs

Now that our Pet Entry form is saved properly, we must turn our attention to the Pet Listing screen. Our ListView is getting more complicated; each item needs to contain an ImageView and two TextView widgets for the pet name and species. We begin by defining a custom layout template for each ListView item called pet_item.xml. This should be familiar; it contains an ImageView and two TextView objects.

We want to make sure this implementation is scalable, in case we want to add new features to individual ListView items in the future. So instead of taking shortcuts and using standard adapters and built-in Android layout templates, we implement another custom adapter called PetListAdapter.

The PetListAdapter is similar to the ImageUriAdapter we previously implemented for the Gallery widget. This time, instead of Gallery child items, we work with the ListView child records, which correspond to each pet. Again, the constructor maps the Cursor data to an array of PetRecord objects.

The getView() method of the PetListAdapter is where the magic occurs. Here we use a LayoutInflater to inflate our custom layout file called pet_item.xml for each ListView item. Again we use the Tag property of the view to store any information about the record that we might use later. It is here that we use the URI information we stored in our database to rebuild the fully qualified image URI using the Uri.parse() and ContentUris.withAppendedId() utility methods and assign this URI to the ImageView widget using the setImageURI() method. Now that we’ve set up everything,we assign the PetListAdapter to our ListView:

That’s about it. Note that you can also create the ListView item layout programmatically (see the PetListItemView class and the PetListAdapter.getView() method comments for more information).

Now you’ve seen how to leverage a content provider to make your application more robust, but this example has scratched only the surface of how powerful content providers can be.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics