Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Storing and Retrieving Data via a Content Provider

Author: Ian Darwin
Published? true
FormatLanguage: WikiFormat

Problem:

You want to read from a Content Provider such as Contracts.

Solution:

Create a PICK uri, open it in an Intent using startActivityForResult, extract the URI from the returned intent, use Activity.getContentProvider(), and process the data using SQLite Cursor methods.

Discussion:

This is part of the Contact selection code from TabbyText, my SMS text message sender for WiFi-Only Honeycomb tablets (the rest of the code is in the Persistence chapter, under Reading Contacts Data.

First, the main program sets up an OnClickListener to launch the Contacts app from a "Find Contact" button.

	b.setOnClickListener(new View.OnClickListener() {			
		@Override
		public void onClick(View arg0) {
			Uri uri = ContactsContract.Contacts.CONTENT_URI;
			System.out.println(uri);
			Intent intent = new Intent(Intent.ACTION_PICK, uri);
			startActivityForResult(intent, REQ_GET_CONTACT);
			}
	});

The URI is pre-defined for us; it actually has the value "content://com.android.contacts/contacts". The constant REQ_GET_CONTACT is arbitrary; it's just there to associate this Intent startup with the handler code, since more complex apps will often start more than one intent, and need to handle the results differently. Once this button is pressed, control passes from our app, out to the Contacts app. The user can then select a contact they wish to SMS. The Contacts app then is backgrounded and control returns to our app at the onActivityResult() method, to indicate that the activity we started has completed and delivered a result.

The next bit of code shows how the onActivityResult() method converts the response from the activity into an SQLite cursor.

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == REQ_GET_CONTACT) {
			switch(resultCode) {
			case Activity.RESULT_OK:
				// The Contacts API is about the most complex to use.
				// First we have to retrieve the Contact, since we only get its URI from the Intent
				Uri resultUri = data.getData(); // e.g., content://contacts/people/123
				Cursor cont = getContentResolver().query(resultUri, null, null, null, null);
				if (!cont.moveToNext()) {	// expect 001 row(s)
					Toast.makeText(this, "Cursor contains no data", Toast.LENGTH_LONG).show(); 
					return;
				}

Key things here: make sure the request code is the one you started, and the resultCode is RESULT_OK or RESULT_CANCELED (if not, pop up a warning dialog). Then, extract the URL for the response you picked - the Intent data from the returned Intent - and use that to create a Query, using the inherited Activity method getContentResolver() to get the ContentResolver and its query() method to make up an SQLite cursor.

We expect the user to have selected one Contact, so if that's not the case we error out. Otherwise we'd go ahead and use the SQLite cursor to read the data. The exact formatting of the Contact database is a bit out of scope for this recipe, so it's been deferred to the Recipe Reading Contact Data.

No records found.