Consuming content providers

The most common way for apps to share structured data is to use content providers. These providers present data in a table-like form for easy consumption.

Getting ready...

If we are targeting an Android version earlier than 3.0, we will need to add the Xamarin Android Support v4 NuGet package.

How to do it...

Content providers give us a way to access data from other apps and services on the device. Here, we will view the contacts through an Android content provider. Let's take a look at the following steps:

  1. As we are going to access the contacts, we have to request permission to do so:
    [assembly: UsesPermission(
      Manifest.Permission.ReadContacts)]
  2. Now that we have the permission, we will need a URI that directs us to the contact content provider:
    string uri = ContactsContract.Contacts.ContentUri;
  3. Next, we will request the contact ID and the display name using the column constants. There are several columns that can be selected, and we can request any combination of them:
    string[] projection = {
      ContactsContract.Contacts.InterfaceConsts.Id,
      ContactsContract.Contacts.InterfaceConsts.DisplayName
    };
  4. If we want to add a filter, we can do so. Here, we select all the contacts with the letter e in their name:
    string filter = string.Format("{0} like ?",
      ContactsContract.Contacts.InterfaceConsts.DisplayName); 
    string[] filterArgs = { "%e%" };
  5. We can also apply a sort, or ordering, to our selection:
    string sort = ContactsContract.Contacts.InterfaceConsts.DisplayName;
  6. Now that we have the target and the request data, we can use a CursorLoader type to start the connection:
    var loader = new CursorLoader(
      this, uri, projection, filter, filterArgs, sort);
  7. Once we have the connection, we can connect and get a cursor to the data:
    var cursor = (ICursor)loader.LoadInBackground();
  8. We can move through the results provided by the cursor, similar to what we did with a data reader in ADO.NET:
    if (cursor.MoveToFirst()) {
      int idIdx = cursor.GetColumnIndex(projection[0]);
      int nameIdx = cursor.GetColumnIndex(projection[1]);
      do {
        long id = cursor.GetLong(idIdx);
        string name = cursor.GetString(nameIdx);
      }
      while (cursor.MoveToNext());
    }
  9. When we are finished with the cursor, we need to ensure that we close it:
    cursor.Close();

How it works...

Using a ContentProvider type allows us to access data from both a central repository as well as access data from other apps or services installed on the device. Content providers offer a consistent and uniform interface for accessing data from any provider. They make accessing any data type or structure similar to accessing tables from a database.

An app can access data from a content provider through a CursorLoader or ContentResolver type. Both allow data queries, but a content resolver has additional operations for inserting, updating, and deleting, and the loader supports background threads.

Tip

Cursors should be released as soon as they are no longer in use in order to free up any resources that are in use by the cursor.

The resolver's Query() method, or the loader's constructor, accepts several parameters that provide the means to obtain data. The first parameter is the URI that determines which and what content provider to access. The URI identifies the provider, or the authority, to be accessed and the particular data in the provider or the path.

The next parameter is the projection, or the columns, to be returned in the resulting query. This consists of a collection of the column names.

The next two relate to the where clause or the filter aspect. This consists of two parts, the first being the actual textual statement and the second being the collection of parameter values. The where clause should use a parameter—the ? character—which will be substituted with the appropriate value from the array when the query is executed.

The final parameter is the column used to sort the resulting data and the name of the column we wish to sort by.

In order to obtain the values from the result, we can make use of the several getter methods, such as GetString() or GetLong(). There is also the GetColumnIndex() method, which allows us to find columns by name instead of position.

There's more...

Using a CursorLoader allows us to make requests on a separate thread to the UI (however, in this example we don't do that). We can also use the ContentResolver property on the Context type. This gives us access to more actions, such as insert, update, and delete; however, these operations occur on the UI thread.

In order to delete data, we construct a where clause and pass in an array of values to the Delete() method, as we would when filtering the query. The items returned in the filter will be removed.

In order to insert data, we pass a set of key-value pairs via a ContentValues object. Items are added via the Put() method with the key being the column name.

Updating data is simply a combination of the delete and insert aspects. We pass a query and arguments along with the collection of values to the Update() method. The items returned by the filter are updated with the values provided.

See also

  • The Creating content providers recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.108.9