609 lines
26 KiB
Plaintext
609 lines
26 KiB
Plaintext
page.title=Accessing Content Providers
|
|
@jd:body
|
|
|
|
<p>If you want to make your data public, you can create (or call) a content
|
|
provider. This is an object that can store and retrieve data accessible by all
|
|
applications. This is the only way to share data across packages; there is no
|
|
common storage area that all packages can share. Android ships with a number
|
|
of content providers for common data types (audio, video, images, personal
|
|
contact information, and so on). You can see some of
|
|
Android's native content providers in the {@link android.provider provider} package.</p>
|
|
|
|
<p>How a content provider actually stores its data under the covers is up to
|
|
the implementation of the content provider, but all content providers must
|
|
implement a common convention to query for data, and a common convention to
|
|
return results. However, a content provider can implement custom helper
|
|
functions to make data storage/retrieval simpler for the specific data that it
|
|
exposes.</p>
|
|
|
|
<p>This document covers two topics related to Content Providers:</p>
|
|
<ul>
|
|
<li><a href="#usingacp">Using a Content Provider</a></li>
|
|
<li><a href="#creatingacontentprovider">Creating a Content Provider</a></li>
|
|
</ul>
|
|
|
|
<h2>Using a Content Provider to Store and Retrieve Data <a name="usingacp"
|
|
id="usingacp"></a></h2>
|
|
|
|
<p>This section describes how to store and retrieve data using a content
|
|
provider implemented by you or anyone else. Android exposes a number of
|
|
content providers for a wide range of data types, from music and image files
|
|
to phone numbers. You can see a list of content providers exposed through the
|
|
convenience classes in the {@link android.provider android.provider} package.</p>
|
|
|
|
<p>Android's content providers are loosely linked to their clients. Each
|
|
content provider exposes a unique string (a URI) identifying the type of data
|
|
that it will handle, and the client must use that string to store or retrieve
|
|
data of that type. We'll explain this more in <a href="#querying">Querying for
|
|
Data</a>.</p>
|
|
|
|
<p>This section describes the following activities:</p>
|
|
|
|
<ul>
|
|
<li>
|
|
<a href="#querying">Querying for Data</a>
|
|
|
|
<ul>
|
|
<li>Making the query</li>
|
|
|
|
<li>What the query returns</li>
|
|
|
|
<li>Querying for files</li>
|
|
|
|
<li>Reading retrieved data</li>
|
|
</ul>
|
|
</li>
|
|
|
|
<li><a href="#modifyingdata">Modifying Data</a></li>
|
|
|
|
<li><a href="#addingrecord">Adding a Record</a></li>
|
|
|
|
<li><a href="#deletingrecord">Deleting a Record</a></li>
|
|
</ul>
|
|
|
|
<a name="querying" id="querying"></a>
|
|
<h4>Querying for Data</h4>
|
|
|
|
<p>Each contact provider exposes a unique public URI (wrapped by {@link android.net.Uri})
|
|
that is used by a client to query/add/update/delete data on that content
|
|
provider. This URI has two forms: one to indicate all values of that type
|
|
(e.g., all personal contacts), and one form to indicate a specific record of
|
|
that type (e.g., Joe Smith's contact information).</p>
|
|
|
|
<ul>
|
|
<li><strong>content://contacts/people/</strong> is the URI that would return a list of all contact names on the device.</li>
|
|
|
|
<li><strong>content://contacts/people/23</strong> is the URI string that would return a single result row, the contact with ID = 23. .</li>
|
|
</ul>
|
|
|
|
<p>An application sends a query to the device that specifies a general type of
|
|
item (all phone numbers), or a specific item (Bob's phone number), to
|
|
retrieve. Android then returns a Cursor over a recordset of results, with a
|
|
specific set of columns. Let's look at a hypothetical query string and a
|
|
result set (the results have been trimmed a bit for clarity):</p>
|
|
|
|
<p>query = <code>content://contacts/people/</code></p>
|
|
|
|
<p>Results:</p>
|
|
|
|
<table border="1">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="col">_ID</th>
|
|
|
|
<th scope="col">_COUNT</th>
|
|
|
|
<th scope="col">NUMBER</th>
|
|
|
|
<th scope="col">NUMBER_KEY</th>
|
|
|
|
<th scope="col">LABEL</th>
|
|
|
|
<th scope="col">NAME</th>
|
|
|
|
<th scope="col">TYPE</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>13</td>
|
|
|
|
<td>4</td>
|
|
|
|
<td>(425) 555 6677</td>
|
|
|
|
<td>425 555 6677</td>
|
|
|
|
<td>Kirkland office</td>
|
|
|
|
<td>Bully Pulpit</td>
|
|
|
|
<td>Work</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>44</td>
|
|
|
|
<td>4</td>
|
|
|
|
<td>(212) 555-1234</td>
|
|
|
|
<td>212 555 1234</td>
|
|
|
|
<td>NY apartment</td>
|
|
|
|
<td>Alan Vain</td>
|
|
|
|
<td>Home</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>45</td>
|
|
|
|
<td>4</td>
|
|
|
|
<td>(212) 555-6657</td>
|
|
|
|
<td>212 555 6657</td>
|
|
|
|
<td>Downtown office</td>
|
|
|
|
<td>Alan Vain</td>
|
|
|
|
<td>Work</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>53</td>
|
|
|
|
<td>4</td>
|
|
|
|
<td>201.555.4433</td>
|
|
|
|
<td>201 555 4433</td>
|
|
|
|
<td>Love Nest</td>
|
|
|
|
<td>Rex Cars</td>
|
|
|
|
<td>Home</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p>Note that the query string isn't a standard SQL query string, but instead a
|
|
URI string that describes the type of data to return. This URI consists of
|
|
three parts: the string "content://"; a segment that describes what kind of
|
|
data to retrieve; and finally an optional ID of a specific item of the
|
|
specified content type. Here are a few more example query strings:</p>
|
|
|
|
<ul>
|
|
<li><strong>content://media/internal/images</strong> is the URI string that would return a list of all
|
|
the internal images on the device.</li>
|
|
|
|
<li><strong>content://media/external/images</strong> is the URI string that would return a list of all
|
|
the images on the "primary" external storage (e.g., the SD card).</li>
|
|
|
|
<li><strong>content://contacts/people/</strong> is the URI that would return a list of all contact names on the device.</li>
|
|
|
|
<li><strong>content://contacts/people/23</strong> is the URI string that would return a single result row, the contact with ID = 23.</li>
|
|
</ul>
|
|
|
|
<p>Although there is a general form, these query URIs are somewhat arbitrary and
|
|
confusing. Therefore, Android provides a list of helper classes in the {@link
|
|
android.provider} package that
|
|
define these query strings so you should not need to know the actual URI value
|
|
for different data types. These helper classes define a string (actually,
|
|
a {@link android.net.Uri Uri} object)
|
|
called CONTENT_URI for a specific data type.</p>
|
|
|
|
<p>Typically you will use the defined CONTENT_URI object to make a query,
|
|
instead of writing the full URI yourself.
|
|
So, each of the example query strings listed above (except for the last one that specifies the record ID)
|
|
can be acquired with the following Uri references:</p>
|
|
|
|
<ul>
|
|
<li>{@link android.provider.MediaStore.Images.Media#INTERNAL_CONTENT_URI
|
|
MediaStore.Images.Media.INTERNAL_CONTENT_URI}</li>
|
|
|
|
<li>{@link android.provider.MediaStore.Images.Media#EXTERNAL_CONTENT_URI
|
|
MediaStore.Images.Media.EXTERNAL_CONTENT_URI}</li>
|
|
|
|
<li>{@link android.provider.Contacts.People#CONTENT_URI
|
|
Contacts.People.CONTENT_URI}</li>
|
|
</ul>
|
|
|
|
<p>To query a specific record ID (e.g., content://contacts/people/23),
|
|
you'll use the same CONTENT_URI, but must append the specific ID value that you want.
|
|
This is one of the few times you should need to examine or modify the URI string.
|
|
So, for example, if you were looking for record 23 in the people contacts, you might run a query
|
|
as shown here:</p>
|
|
<pre>
|
|
// Get the base URI for contact with _ID=23.
|
|
// This is same as Uri.parse("content://contacts/people/23");
|
|
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
|
|
// Query for this record.
|
|
Cursor cur = managedQuery(myPerson, null, null, null);
|
|
</pre>
|
|
<p class="note"><strong>Tip:</strong> You can also append a string to a Uri, using
|
|
{@link android.net.Uri#withAppendedPath(Uri,String)}.</p>
|
|
|
|
<p>This query returns a cursor over a database query result set. What columns
|
|
are returned, what they're called, and what they are named are discussed next.
|
|
For now, though, know that you can specify that only certain columns be
|
|
returned, the sort order, and a SQL WHERE clause.</p>
|
|
|
|
<p>You should use the {@link
|
|
android.app.Activity#managedQuery(android.net.Uri,java.lang.String[],java.lang.String,java.lang.String[],java.lang.String) Activity.managedQuery()}
|
|
method to retrieve a managed cursor. A managed cursor handles all the niceties
|
|
such as unloading itself when the application pauses, and requerying itself
|
|
when the application restarts. You can ask Android to manage an unmanaged
|
|
cursor for you by calling {@link
|
|
android.app.Activity#startManagingCursor(android.database.Cursor) Activity.startManagingCursor()}.</p>
|
|
|
|
<p>Let's look at an example query to retrieve a list of contact names and their primary phone
|
|
numbers.</p>
|
|
<pre>
|
|
// An array specifying which columns to return.
|
|
string[] projection = new string[] {
|
|
People._ID,
|
|
People.NAME,
|
|
People.NUMBER,
|
|
};
|
|
|
|
// Get the base URI for People table in Contacts content provider.
|
|
// ie. content://contacts/people/
|
|
Uri mContacts = People.CONTENT_URI;
|
|
|
|
// Best way to retrieve a query; returns a managed query.
|
|
Cursor managedCursor = managedQuery( mContacts,
|
|
projection, //Which columns to return.
|
|
null, // WHERE clause--we won't specify.
|
|
People.NAME + " ASC"); // Order-by clause.
|
|
</pre>
|
|
|
|
<p>This query will retrieve data from the people table of
|
|
the Contacts content provider. It will retrieve the name, primary phone number, and unique record ID for
|
|
each contact. </p>
|
|
|
|
<p><strong>What the query returns</strong></p>
|
|
|
|
<p>A query returns a set of zero or more database records. The column names,
|
|
order, and type are specific to the content provider, but every query includes
|
|
a column called _id, which is the ID of the item in that row. If a query can
|
|
return binary data, such as a bitmap or audio file, it will have a column with
|
|
any name that holds a content:// URI that you can use to get this data (more
|
|
information on how to get the file will be given later). Here is a tiresome
|
|
example result set for the previous query:</p>
|
|
|
|
<table border="1">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="col">_id</th>
|
|
|
|
<th scope="col">name</th>
|
|
|
|
<th scope="col">number</th>
|
|
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>44</td>
|
|
|
|
<td>Alan Vain</td>
|
|
|
|
<td>212 555 1234</td>
|
|
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>13</td>
|
|
|
|
<td>Bully Pulpit</td>
|
|
|
|
<td>425 555 6677</td>
|
|
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>53</td>
|
|
|
|
<td>Rex Cars</td>
|
|
|
|
<td>201 555 4433</td>
|
|
|
|
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p>This result set demonstrates what is returned when we specified a subset of
|
|
columns to return. The optional subset list is passed in the
|
|
<em>projection</em> parameter of the query. A content manager should list
|
|
which columns it supports either by implementing a set of interfaces
|
|
describing each column (see {@link
|
|
android.provider.Contacts.People.Phones Contacts.People.Phones},
|
|
which extends {@link android.provider.BaseColumns BaseColumns}, {@link
|
|
android.provider.Contacts.PhonesColumns PhonesColumns}, and {@link
|
|
android.provider.Contacts.PeopleColumns PeopleColumns}), or by
|
|
listing the column names as constants. Note that you need to
|
|
know the data type of a column exposed by a content provider in order to be
|
|
able to read it; the field reading method is specific to the data type, and a
|
|
column's data type is not exposed programmatically.</p>
|
|
|
|
<p>The retrieved data is exposed by a {@link
|
|
android.database.Cursor Cursor} object that can be used to
|
|
iterate backward or forward through the result set. You can use this cursor to
|
|
read, modify, or delete rows. Adding new rows requires a different object
|
|
described later.</p>
|
|
|
|
<p>Note that by convention, every recordset includes a field named _id, which
|
|
is the ID of a specific record, and a _count field, which is a count of
|
|
records in the current result set. These field names are defined by {@link
|
|
android.provider.BaseColumns BaseColumns}.</p>
|
|
|
|
<p><strong>Querying for Files</strong></p>
|
|
|
|
<p>The previous query result demonstrates how a file is returned in a data
|
|
set. The file field is typically (but not required to be) a string path to the
|
|
file. However, the caller should never try to read and open the file directly
|
|
(permissions problems for one thing can make this fail). Instead, you should
|
|
call {@link
|
|
android.content.ContentResolver#openInputStream(android.net.Uri) ContentResolver.openInputStream()}
|
|
/ {@link
|
|
android.content.ContentResolver#openOutputStream(android.net.Uri)
|
|
ContentResolver.openOutputStream()},
|
|
or one of the helper functions from a content provider.</p>
|
|
|
|
<p><strong>Reading Retrieved Data</strong></p>
|
|
|
|
<p>The Cursor object retrieved by the query provides access to a recordset of
|
|
results. If you have queried for a specific record by ID, this set will
|
|
contain only one value; otherwise, it can contain multiple values. You can
|
|
read data from specific fields in the record, but you must know the data type
|
|
of the field, because reading data requires a specialized method for each type
|
|
of data. (If you call the string reading method on most types of columns,
|
|
Android will give you the String representation of the data.) The Cursor lets
|
|
you request the column name from the index, or the index number from the
|
|
column name.</p>
|
|
|
|
<p>If you are reading binary data, such as an image file, you should call
|
|
{@link
|
|
android.content.ContentResolver#openOutputStream(android.net.Uri) ContentResolver.openOutputStream()}
|
|
on the string content:// URI stored in a column name.</p>
|
|
|
|
<p>The following snippet demonstrates reading the name and phone number from
|
|
our phone number query:</p>
|
|
<pre>
|
|
private void getColumnData(Cursor cur){
|
|
if (cur.moveToFirst()) {
|
|
|
|
String name;
|
|
String phoneNumber;
|
|
int nameColumn = cur.getColumnIndex(People.NAME);
|
|
int phoneColumn = cur.getColumnIndex(People.NUMBER);
|
|
String imagePath;
|
|
|
|
do {
|
|
// Get the field values
|
|
name = cur.getString(nameColumn);
|
|
phoneNumber = cur.getString(phoneColumn);
|
|
|
|
// Do something with the values.
|
|
...
|
|
|
|
} while (cur.moveToNext());
|
|
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<h3>Modifying Data<a name="modifyingdata" id="modifyingdata"></a></h3>
|
|
|
|
<p>To batch update a group of records (for example, to change "NY" to "New
|
|
York" in all contact fields), call the {@link
|
|
android.content.ContentResolver#update(android.net.Uri,android.content.ContentValues,java.lang.String,java.lang.String[]) ContentResolver.update()}
|
|
method with the columns and values to change.</p>
|
|
|
|
<h3>Adding a New Record <a name="addingrecord" id="addingrecord"></a></h3>
|
|
|
|
<p>To add a new record, call ContentResolver.insert() with the URI of the type
|
|
of item to add, and a Map of any values you want to set immediately on the new
|
|
record. This will return the full URI of the new record, including record
|
|
number, which you can then use to query and get a Cursor over the new
|
|
record.</p>
|
|
|
|
<pre>
|
|
ContentValues values = new ContentValues();
|
|
Uri phoneUri = null;
|
|
Uri emailUri = null;
|
|
|
|
values.put(Contacts.People.NAME, "New Contact");
|
|
//1 = the new contact is added to favorites
|
|
//0 = the new contact is not added to favorites
|
|
values.put(Contacts.People.STARRED,1);
|
|
|
|
//Add Phone Numbers
|
|
Uri uri = getContentResolver().insert(Contacts.People.CONTENT_URI, values);
|
|
|
|
//The best way to add Contacts data like Phone, email, IM is to
|
|
//get the CONTENT_URI of the contact just inserted from People's table,
|
|
//and use withAppendedPath to construct the new Uri to insert into.
|
|
phoneUri = Uri.withAppendedPath(uri, Contacts.People.Phones.CONTENT_DIRECTORY);
|
|
|
|
values.clear();
|
|
values.put(Contacts.Phones.TYPE, Phones.TYPE_MOBILE);
|
|
values.put(Contacts.Phones.NUMBER, "1233214567");
|
|
getContentResolver().insert(phoneUri, values);
|
|
|
|
//Add Email
|
|
emailUri = Uri.withAppendedPath(uri, ContactMethods.CONTENT_DIRECTORY);
|
|
|
|
values.clear();
|
|
//ContactMethods.KIND is used to distinguish different kinds of
|
|
//contact data like email, im, etc.
|
|
values.put(ContactMethods.KIND, Contacts.KIND_EMAIL);
|
|
values.put(ContactMethods.DATA, "test@example.com");
|
|
values.put(ContactMethods.TYPE, ContactMethods.TYPE_HOME);
|
|
getContentResolver().insert(emailUri, values);
|
|
|
|
</pre>
|
|
|
|
<p>To save a file, you can call ContentResolver().openOutputStream() with the
|
|
URI as shown in the following snippet:
|
|
</p>
|
|
<pre>
|
|
// Save the name and description in a map. Key is the content provider's
|
|
// column name, value is the value to save in that record field.
|
|
ContentValues values = new ContentValues(3);
|
|
values.put(MediaStore.Images.Media.DISPLAY_NAME, "road_trip_1");
|
|
values.put(MediaStore.Images.Media.DESCRIPTION, "Day 1, trip to Los Angeles");
|
|
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
|
|
|
|
// Add a new record without the bitmap, but with the values.
|
|
// It returns the URI of the new record.
|
|
Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
|
|
|
try {
|
|
// Now get a handle to the file for that record, and save the data into it.
|
|
// sourceBitmap is a Bitmap object representing the file to save to the database.
|
|
OutputStream outStream = getContentResolver().openOutputStream(uri);
|
|
sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
|
|
outStream.close();
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "exception while writing image", e);
|
|
}
|
|
</pre>
|
|
|
|
<h3>Deleting a Record <a name="deletingrecord" id="deletingrecord"></a></h3>
|
|
|
|
<p>To delete a single record, call {@link
|
|
android.content.ContentResolver#delete(android.net.Uri,java.lang.String,java.lang.String[]) ContentResolver.delete()}
|
|
with the URI of a specific row.</p>
|
|
|
|
<p>To delete multiple rows, call ContentResolver.delete() with the URI of the
|
|
type of record to delete (for example,
|
|
android.provider.Contacts.People.CONTENT_URI) and a SQL WHERE clause defining
|
|
which rows to delete (<em>Warning</em>: be sure to include a valid WHERE
|
|
clause if deleting a general type using ContentResolver.delete(), or else you
|
|
risk deleting more records than you intended!).</p>
|
|
|
|
<h2>Creating a Content Provider<a name="creatingacontentprovider"
|
|
id="creatingacontentprovider"></a> </h2> <p>Here is how to create your own
|
|
content provider to act as a public source for reading and writing a new data
|
|
type:</p>
|
|
<ol>
|
|
<li>Extend
|
|
{@link android.content.ContentProvider ContentProvider}.</li>
|
|
<li>Define a <code>public static final {@link android.net.Uri Uri} </code>named
|
|
CONTENT_URI. This is the string that represents the full "content://" URI
|
|
that your content provider handles. You must define a unique string for this
|
|
value; the best solution is to use the fully-qualified class name of your
|
|
content provider (lowercase). So, for example: <br>
|
|
|
|
<code>public static final Uri CONTENT_URI = Uri.parse(
|
|
"content://com.google.codelab.rssprovider");</code></li>
|
|
<li>Create your system for storing data. Most content providers store their
|
|
data using Android's file storage methods or SQLite databases, but you can
|
|
store your data any way you want, so long as you follow the calling and return
|
|
value conventions.</li>
|
|
<li>Define the column names that you will return to your clients. If you are
|
|
using an underlying database, these column names are typically identical
|
|
to the SQL database column names they represent. In any case, you should include
|
|
an integer column named <code>_id</code> to
|
|
define a specific record number. If using the SQLite database, this should
|
|
be type <code>INTEGER
|
|
PRIMARY KEY AUTOINCREMENT</code>.
|
|
The <code>AUTOINCREMENT</code> descriptor
|
|
is optional, but by default, SQLite
|
|
autoincrements an ID counter field to the next number above the largest
|
|
existing number in the table. If you delete the last row, the next row added
|
|
will have the same ID as the deleted row. To avoid this by having SQLite
|
|
increment to the next largest value whether deleted or not, then assign your
|
|
ID column the following type: INTEGER PRIMARY KEY AUTOINCREMENT. (<strong>Note</strong> You
|
|
should have a unique _id field whether or not you have another field (such
|
|
as a URL) that is also unique among all records.) Android provides the
|
|
{@link android.database.sqlite.SQLiteOpenHelper SQLiteOpenHelper}
|
|
|
|
class to help you create and manage versions of your database. </li>
|
|
<li>If you are exposing byte data, such as a bitmap file, the field that stores
|
|
this data should actually be a string field with a content:// URI for that
|
|
specific file. This is the field that clients will call to retrieve this
|
|
data. The content provider for that content type (it can be the same content
|
|
provider or another content provider — for example, if you're storing a photo
|
|
you would use the media content provider) should implement a field named
|
|
_data for that record. The _data field lists the exact file path on the device
|
|
for that file. This field is not intended to be read by the client, but by
|
|
the ContentResolver. The client will call {@link
|
|
android.content.ContentResolver#openOutputStream(android.net.Uri) ContentResolver.openOutputStream()} on the user-facing field holding the URI
|
|
for the item (for example, the column named photo might have a value content://media/images/4453).
|
|
The ContentResolver will request the _data field for that record, and because
|
|
it has higher permissions than a client, it should be able to access
|
|
that file directly and return a read wrapper for that file to the client. </li>
|
|
<li>Declare public static
|
|
Strings that clients can use to specify which columns to return, or to specify
|
|
field values from the cursor. Carefully document the data type of each
|
|
field. Remember that file fields, such as audio or bitmap fields, are typically
|
|
returned as string path values </li>
|
|
<li>Return a {@link android.database.Cursor Cursor} object over a recordset in
|
|
reply to a query. This means implementing the query(), update(), insert(),
|
|
and delete() methods. As a courtesy, you might want to call {@link android.content.ContentResolver#notifyChange(android.net.Uri,android.database.ContentObserver) ContentResolver.notifyChange()} to notify
|
|
listeners about updated information. </li>
|
|
|
|
<li>Add a <code><provider></code> tag to AndroidManifest.xml, and use its
|
|
<em>authorities</em> attribute to define the authority part of the content type it should
|
|
handle. For example, if your content type is content://com.example.autos/auto
|
|
to request a list of all autos, then <em>authorities</em> would be <code>com.example.autos</code>.
|
|
Set the <em>multiprocess</em> attribute to true if data does not need to
|
|
be synchronized between multiple running versions of the content provider. </li>
|
|
|
|
<li>If you are handling a new data type, you must define a new MIME type to return
|
|
for your implementation of {@link android.content.ContentProvider#getType(android.net.Uri) android.ContentProvider.getType(url)}. This type corresponds to the <code>content://</code> URI
|
|
submitted to getType(), which will be one of the content types handled by
|
|
the provider. The MIME type for each content type has two forms: one for
|
|
a specific record, and one for multiple records. Use the {@link android.net.Uri Uri} methods to help determine what is being requested. Here is
|
|
the general format for each:
|
|
<ul>
|
|
<li><code>vnd.android.cursor.item/vnd.<em>yourcompanyname.contenttype</em></code>
|
|
for a single row. For example, a request for train record 122 using
|
|
<pre>content://com.example.transportationprovider/trains/122</pre>
|
|
might return the MIME type
|
|
<code>vnd.android.cursor.item/vnd.example.rail</code>
|
|
</li>
|
|
<li><code>vnd.android.cursor.dir/vnd.<em>yourcompanyname.contenttype</em></code>
|
|
for multiple rows. For example, a request for all train records using
|
|
<pre>content://com.example.transportationprovider/trains</pre>
|
|
might return the MIME type
|
|
<code>vnd.android.cursor.dir/vnd.example.rail</code>
|
|
</li>
|
|
</ul>
|
|
|
|
</li>
|
|
</ol>
|
|
<p>For an example of a private content provider implementation, see the NodePadProvider
|
|
class in the notepad sample application that ships with the SDK. </p>
|
|
<p>Here is a recap of the important parts of a content URI:</p>
|
|
<p><img src="../../images/content_uri.png" alt="Elements of a content URI" height="80" width="528"> </p>
|
|
<ol type="A">
|
|
<li>Standard required prefix. Never modified. </li>
|
|
<li>Authority part. For third-party applications, this should be a fully-qualified
|
|
class to ensure uniqueness. This corresponds to the value in
|
|
the <code><provider></code> element's <em>authorities</em> attribute:
|
|
<code><provider class="TransportationProvider"
|
|
authorities="com.example.transportationprovider"
|
|
/></code> </li>
|
|
|
|
<li>The path that the content provider uses to determine what kind of data is
|
|
being requested. This can be zero or more segments: if the content provider
|
|
exposes only one type of data (only trains, for example), this can be absent.
|
|
If it provides several types, including subtypes, this can be several elements
|
|
long: e.g., "<code>land/bus</code>, <code>land/train</code>, <code>sea/ship</code>,
|
|
and <code>sea/submarine</code>" to give four possibilities.</li>
|
|
<li>A specific record being requested, if any. This is the _id value of a specific
|
|
record being requested. If all records of a specific type are being requested,
|
|
omit this and the trailing slash: <code>content://com.example.transportationprovider/trains</code> </li>
|
|
</ol>
|
|
|