The Contacts database is one of the most commonly used applications on the mobile
phone. People always want phone numbers handy for calling friends, family, coworkers,
and clients.Additionally, most phones show the identity of the caller based on the contacts
application, including nicknames, photos, or icons.
Android provides a built-in Contact application, and the contact data is exposed to
other Android applications using the content provider interface.As an application developer,
this means you can leverage the user's contact data within your application for a
more robust user experience.
Accessing Private Contact Data
Your application needs special permission to access the private user information provided
by the Contacts content provider.You must declare a uses-permission tag using the
permission READ_CONTACTS to read this information.
The code to start reading contact data from the Contacts application should look familiar.
Cursor oneContact = managedQuery( People.CONTENT_URI, null, null, null,
"name desc LIMIT 1");
Log.d(debugTag, "Count: " + oneContact.getCount());
This short example simply shows querying for a single contact.We used LIMIT to retrieve
one contact record. If you actually look at the returned columns of data, you find
that there is little more than the contact name and some indexes.The data fields are not
explicitly returned. Instead, the results include the values needed to build specific URIs to
those pieces of data.We need to request the data for the contact using these indexes.
Specifically,we retrieve the primary email and primary phone number for this contact.
int nameIdx = oneContact.getColumnIndex(Contacts.People.NAME);
int emailIDIdx = oneContact
.getColumnIndex(Contacts.People.PRIMARY_EMAIL_ID);
int phoneIDIdx = oneContact
.getColumnIndex(Contacts.People.PRIMARY_PHONE_ID);
oneContact.moveToFirst();
int emailID = oneContact.getInt(emailIDIdx);
int phoneID = oneContact.getInt(phoneIDIdx);
Now that we have the column index values for the contact's name, primary email address,
and primary phone number,we need to build the Uri objects associated with those pieces
of information and query for the primary email and primary phone number.
Uri emailUri = ContentUris.withAppendedId(
Contacts.ContactMethods.CONTENT_URI,
emailID);
Uri phoneUri = ContentUris.withAppendedId(
Contacts.Phones.CONTENT_URI, phoneID);
Cursor primaryEmail = managedQuery(emailUri,
new String[] {
Contacts.ContactMethods.DATA
},
null, null, null);
Cursor primaryNumber = managedQuery(phoneUri,
new String[] {
Contacts.Phones.NUMBER
},
null, null, null);
After retrieving the appropriate column indexes for a contact's specific email and
phone number,we call ContentUris.withAppendedId() to create the new Uri objects
from existing ones and the identifiers we now have.This enables direct selection of a particular
row from the table when the index of that row is known.You can use a selection
parameter to do this, as well. Lastly,we used the two new Uri objects to perform two calls
to managedQuery().
Now we take a shortcut with the requested columns String array because each query
only has one column:
String name = oneContact.getString(nameIdx);
primaryEmail.moveToFirst();
String email = primaryEmail.getString(0);
primaryNumber.moveToFirst();
String number = primaryNumber.getString(0);
If an email or phone number doesn't exist, an exception called
android.database.CursorIndexOutOfBoundsException is thrown.This can be caught,
or you can check to see that a result was actually returned in the Cursor first.
Querying for a Specific Contact
If that seemed like quite a lot of coding to get a phone number, you're not alone. For getting
a quick piece of data, there is a faster way.The following block of code demonstrates
how we can get the primary number and name for one contact.The primary number for
a contact is designated as the default number within the contact manager on the handset.
It might be useful to use the primary number field if you don't get any results back from
the query.
String[] requestedColumns = {
Contacts.Phones.NAME,
Contacts.Phones.NUMBER,
};
Cursor contacts = managedQuery(
Contacts.Phones.CONTENT_URI,
requestedColumns,
Contacts.Phones.ISPRIMARY + "<>0",
null, "name desc limit 1");
Log.d(debugTag, "Contacts count: "
+ contacts.getCount());
int nameIdx = contacts
.getColumnIndex(Contacts.Phones.NAME);
int phoneIdx = contacts
.getColumnIndex(Contacts.Phones.NUMBER);
contacts.moveToFirst();
Log.d(debugTag, "Name: " + contacts.getString(nameIdx));
Log.d(debugTag, "Phone: " + contacts.getString(phoneIdx));
This block of code should look somewhat familiar, yet it is a much shorter and more
straightforward method to query for phone numbers by Contact name.The
Contacts.Phones.CONTENT_URI contains phone numbers but it also happens to have the
contact name.This is similar to the CallLog content provider.
Modifying Content Providers Data
Content providers are not only static sources of data.They can also be used to add, update,
and delete data, if the content provider application has implemented this functionality.
Your application must have the appropriate permissions (that is, WRITE_CONTACTS as opposed
to READ_CONTACTS) to perform some of these actions.
Adding Records
Using the Contacts content provider,we can, for example, add a new record to the contacts
database programmatically.
ContentValues values = new ContentValues();
values.put(Contacts.People.NAME, "Sample User");
Uri uri = getContentResolver().insert(
Contacts.People.CONTENT_URI, values);
Uri phoneUri = Uri.withAppendedPath(uri,
Contacts.People.Phones.CONTENT_DIRECTORY);
values.clear();
values.put(Contacts.Phones.NUMBER, "2125551212");
values.put(Contacts.Phones.TYPE, Contacts.Phones.TYPE_WORK);
getContentResolver().insert(phoneUri, values);
values.clear();
values.put(Contacts.Phones.NUMBER, "3135551212");
values.put(Contacts.Phones.TYPE, Contacts.Phones.TYPE_MOBILE);
getContentResolver().insert(phoneUri, values);
Just as we used the ContentValues class to insert records into an application's SQLite
database,we use it again here.The first action we take is to provide a name for the
Contacts.People.NAME column.We need to create the contact with a name before we
can assign information, such as phone numbers.Think of this as creating a row in a table
that provides a one-to-many relationship to a phone number table.
Next,we insert the data in the database found at the Contacts.People.CONTENT_URI
path.We use a call to getContentResolver() to retrieve the ContentResolver associated
with our Activity.The return value is the Uri of our new contact.We need to use it for
adding phone numbers to our new contact.We then reuse the ContentValues instance by
clearing it and adding a Contacts.Phones.NUMBER and the Contacts.Phones.TYPE for it.
Using the ContentResolver,we insert this data into the newly created Uri.
Updating Records
Inserting data isn't the only change you can make.You can update one or more rows, as
well.The following block of code shows how to update data within a content provider. In
this case,we update a note field for a specific contact, using its unique identifier.
ContentValues values = new ContentValues();
values.put(People.NOTES, "This is my boss");
Uri updateUri = ContentUris.withAppendedId(People.CONTENT_URI, rowId);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.d(debugTag, "Rows updated: " + rows);
Again,we use an instance of the ContentValues object to map the data field we want to
update with the data value?in this case, the note field.This replaces any current note
stored in the NOTES field currently stored with the contact.We then create the Uri for the
specific contact we are updating.A simple call to the update() method of the
ContentResolver class completes our change.We can then confirm that only one row
was updated.
Deleting Records
Now that you cluttered up your contacts application with sample user data, you might
want to delete some of it. Deleting data is fairly straightforward.
Deleting All Records
The following code deletes all rows at the given URI, although you should execute operations
like this with extreme care:
int rows = getContentResolver().delete(People.CONTENT_URI, null, null);
Log.d(debugTag, "Rows: "+ rows);
The delete() method deletes all rows at a given URI filtered by the selection parameters,
which, in this case, includes all rows at the People.CONTENT_URI location; in other
words, all contact entries.
Deleting Specific Records
Often you want to select specific rows to delete by adding the unique identifier index to
the end of the URI or remove rows matching a particular pattern.
For example, the following deletion matches all contact records with the name Sample
User, which we used when we created sample contacts previously in the chapter.
int rows = getContentResolver().delete(People.CONTENT_URI,
People.NAME + "=?",
new String[] {"Sample User"});
Log.d(debugTag, "Rows: "+ rows);
0 件のコメント:
コメントを投稿