blob: 5f868cacf5aea33b0b795e2e405cfa7de0c01a12 [file] [log] [blame]
page.title=Ni dung Cơ bn v Trình cung cp Ni dung
@jd:body
<div id="qv-wrapper">
<div id="qv">
<!-- In this document -->
<h2>Trong tài liu này</h2>
<ol>
<li>
<a href="#Basics">Tng quan</a>
<ol>
<li>
<a href="#ClientProvider">Truy cp mt trình cung cp</a>
</li>
<li>
<a href="#ContentURIs">URI Ni dung</a>
</li>
</ol>
</li>
<li>
<a href="#SimpleQuery">Truy xut D liu t Trình cung cp</a>
<ol>
<li>
<a href="#RequestPermissions">Yêu cu quyn truy cp đọc</a>
</li>
<li>
<a href="#Query">Xây dng truy vn</a>
</li>
<li>
<a href="#DisplayResults">Hin th các kết qu truy vn</a>
</li>
<li>
<a href="#GettingResults">Ly d liu t các kết qu truy vn</a>
</li>
</ol>
</li>
<li>
<a href="#Permissions">Quyn ca Trình cung cp Ni dung</a>
</li>
<li>
<a href="#Modifications">Chèn, Cp nht, và Xóa D liu</a>
<ol>
<li>
<a href="#Inserting">Chèn d liu</a>
</li>
<li>
<a href="#Updating">Cp nht d liu</a>
</li>
<li>
<a href="#Deleting">Xóa d liu</a>
</li>
</ol>
</li>
<li>
<a href="#DataTypes">Các Kiu D liu ca Trình cung cp</a>
</li>
<li>
<a href="#AltForms">Các Hình thc Truy cp Trình cung cp Thay thế</a>
<ol>
<li>
<a href="#Batch">Truy cp hàng lot</a>
</li>
<li>
<a href="#Intents">Truy cp d liu thông qua ý định</a>
</li>
</ol>
</li>
<li>
<a href="#ContractClasses">Các Lp Hp đồng</a>
</li>
<li>
<a href="#MIMETypeReference">Tham kho Kiu MIME</a>
</li>
</ol>
<!-- Key Classes -->
<h2>Lp khóa</h2>
<ol>
<li>
{@link android.content.ContentProvider}
</li>
<li>
{@link android.content.ContentResolver}
</li>
<li>
{@link android.database.Cursor}
</li>
<li>
{@link android.net.Uri}
</li>
</ol>
<!-- Related Samples -->
<h2>Các Mu Liên quan</h2>
<ol>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
Con chy (Danh bạ)</a>
</li>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
Con chy in thoi)</a>
</li>
</ol>
<!-- See also -->
<h2>Xem thêm</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
To mt Trình cung cp Ni dung</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/calendar-provider.html">
Trình cung cp Lch</a>
</li>
</ol>
</div>
</div>
<!-- Intro paragraphs -->
<p>
Trình cung cp ni dung qun lý truy cp vào mt kho d liu tp trung. Trình cung cp
là b phn ca mt ng dng Android, nó thường cung cp UI ca chính mình để làm vic cùng
d liu. Tuy nhiên, trình cung cp ni dung được thiết kế ch yếu cho các ng dng khác
s dng, giúp truy cp trình cung cp bng cách s dng mt đối tượng máy khách cung cp. Cùng nhau, trình cung cp
và máy khách cung cp s mang đến mt giao din nht quán, tiêu chun cho d liu, giao din này
cũng đồng thi x lý truyn thông liên tiến trình và bo mt truy cp d liu.
</p>
<p>
Ch đề này đề cp đến nhng ni dung cơ bn sau đây:
</p>
<ul>
<li>Cách trình cung cp ni dung hot động.</li>
<li>API bn s dng để truy xut d liu t mt trình cung cp ni dung.</li>
<li>API bn s dng để chèn, cp nht, hoc xóa d liu trong mt trình cung cp ni dung.</li>
<li>Các tính năng API khác to điu kin làm vic cùng các trình cung cp.</li>
</ul>
<!-- Basics -->
<h2 id="Basics">Tng quan</h2>
<p>
Trình cung cp ni dung trình bày d liu cho các ng dng bên ngoài dưới dng mt hoc nhiu bng tương t
như các bng được tìm thy trong mt cơ s d liu quan hệ. Mi hàng th hin mt thc th ca mt s kiu d liu
mà trình cung cp thu thp, và mi ct trong hàng th hin mt phn riêng bit ca d liu được thu thp
đối vi mt thc thể.
</p>
<p>
Ví dụ, mt trong các trình cung cp tích hp trong nn tng Android đó là t đin người dùng, nó
lưu gi chính t ca nhng t phi tiêu chun mà người dùng mun gi li. Bng 1 minh ha
cách mà d liu có th được trình bày trong bng ca trình cung cp này:
</p>
<p class="table-caption">
<strong>Bng 1:</strong> Bng t đin người dùng mu.
</p>
<table id="table1" style="width: 50%;">
<tr>
<th style="width:20%" align="center" scope="col">từ</th>
<th style="width:20%" align="center" scope="col">id ng dng</th>
<th style="width:20%" align="center" scope="col">tn sut</th>
<th style="width:20%" align="center" scope="col">bn địa</th>
<th style="width:20%" align="center" scope="col">_ID</th>
</tr>
<tr>
<td align="center" scope="row">mapreduce</td>
<td align="center">user1</td>
<td align="center">100</td>
<td align="center">en_US</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center" scope="row">precompiler</td>
<td align="center">user14</td>
<td align="center">200</td>
<td align="center">fr_FR</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center" scope="row">applet</td>
<td align="center">user2</td>
<td align="center">225</td>
<td align="center">fr_CA</td>
<td align="center">3</td>
</tr>
<tr>
<td align="center" scope="row">const</td>
<td align="center">user1</td>
<td align="center">255</td>
<td align="center">pt_BR</td>
<td align="center">4</td>
</tr>
<tr>
<td align="center" scope="row">int</td>
<td align="center">user5</td>
<td align="center">100</td>
<td align="center">en_UK</td>
<td align="center">5</td>
</tr>
</table>
<p>
Trong bng 1, mi hàng th hin mt thc th ca mt t mà có th không thy có
trong t đin chun. Mi ct th hin mt s d liu cho t đó, chng hn như
t bn địa được dùng ln đầu cho t đó. Tiêu đề ct là các tên ct được lưu gi trong
trình cung cp. Để tham kho ti bn địa ca mt hàng, bn tham kho ti ct <code>locale</code> ca hàng đó. Đối vi
trình cung cp này, ct <code>_ID</code> đóng vai trò là ct "khóa chính" mà
trình cung cp t động duy trì.
</p>
<p class="note">
<strong>Lưu ý:</strong> Trình cung cp không bt buc phi có mt khóa chính, và không bt buc phi
s dng <code>_ID</code> làm tên ct ca mt khóa chính nếu có khóa. Tuy nhiên,
nếu bn mun gn kết d liu t mt trình cung cp vi mt {@link android.widget.ListView}, mt trong các
tên ct s phi là <code>_ID</code>. Yêu cu này được gii thích chi tiết hơn trong
phn <a href="#DisplayResults">Hin th các kết qu truy vn</a>.
</p>
<h3 id="ClientProvider">Truy cp mt trình cung cp</h3>
<p>
Mt ng dng truy cp d liu t mt trình cung cp ni dung bng
mt đối tượng máy khách {@link android.content.ContentResolver}. Đối tượng này có các phương pháp để gi
nhng phương pháp có tên ging nhau trong đối tượng trình cung cp, mt thc th ca mt trong nhng lp con
c th ca {@link android.content.ContentProvider}. Các phương pháp
{@link android.content.ContentResolver} cung cp các chc năng
"CRUD" (to, truy xut, cp nht, và xóa) cơ bn ca thiết b lưu tr liên tc.
</p>
<p>
Đối tượng {@link android.content.ContentResolver} trong tiến trình
ca ng dng máy khách và đối tượng {@link android.content.ContentProvider} trong ng dng mà s hu
trình cung cp s t động x lý truyn thông liên tiến trình.
{@link android.content.ContentProvider} cũng đóng vai trò như mt lp rút gn gia kho d liu
ca nó và biu din bên ngoài ca d liu dưới dng bng.
</p>
<p class="note">
<strong>Lưu ý:</strong> Để truy cp mt trình cung cp, ng dng ca bn thường phi yêu cu các quyn
c th trong tp bn kê khai ca mình. Điu này được mô t chi tiết hơn trong phn
<a href="#Permissions">Quyn ca Trình cung cp Ni dung</a>
</p>
<p>
Ví dụ, để có mt danh sách các t và ni dung bn địa ca chúng t Trình cung cp T đin Người dùng,
bn hãy gi {@link android.content.ContentResolver#query ContentResolver.query()}.
Phương pháp {@link android.content.ContentResolver#query query()} sẽ gọi phương pháp
{@link android.content.ContentProvider#query ContentProvider.query()} được định nghĩa bởi
Trình cung cp T đin Người dùng. Các dòng mã sau th hin mt lnh gi
{@link android.content.ContentResolver#query ContentResolver.query()}:
<p>
<pre>
// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
mProjection, // The columns to return for each row
mSelectionClause // Selection criteria
mSelectionArgs, // Selection criteria
mSortOrder); // The sort order for the returned rows
</pre>
<p>
Bng 2 cho biết các tham đối ti
{@link android.content.ContentResolver#query
query(Uri,projection,selection,selectionArgs,sortOrder)} khp vi mt câu lnh SQL SELECT như thế nào:
</p>
<p class="table-caption">
<strong>Bng 2:</strong> Query() so vi truy vn SQL.
</p>
<table id="table2" style="width: 75%;">
<tr>
<th style="width:25%" align="center" scope="col">tham đối query()</th>
<th style="width:25%" align="center" scope="col">T khóa/tham s SELECT</th>
<th style="width:50%" align="center" scope="col">Lưu ý</th>
</tr>
<tr>
<td align="center"><code>Uri</code></td>
<td align="center"><code>FROM <em>table_name</em></code></td>
<td><code>Uri</code> ánh xạ tới bảng trong trình cung cấp có tên <em>table_name</em>.</td>
</tr>
<tr>
<td align="center"><code>projection</code></td>
<td align="center"><code><em>col,col,col,...</em></code></td>
<td>
<code>projection</code> là mt mng gm các ct nên được đưa vào đối vi mi hàng
được truy xut.
</td>
</tr>
<tr>
<td align="center"><code>selection</code></td>
<td align="center"><code>WHERE <em>col</em> = <em>value</em></code></td>
<td><code>selection</code> quy định các tiêu chí để lựa chọn hàng.</td>
</tr>
<tr>
<td align="center"><code>selectionArgs</code></td>
<td align="center">
(Không có s tương đương chính xác. Các tham đối la chn s thay thế các ch dành sn <code>?</code> trong
mnh đề la chn.)
</td>
</tr>
<tr>
<td align="center"><code>sortOrder</code></td>
<td align="center"><code>ORDER BY <em>col,col,...</em></code></td>
<td>
<code>sortOrder</code> quy định th t các hàng xut hin trong
{@link android.database.Cursor} được tr về.
</td>
</tr>
</table>
<h3 id="ContentURIs">URI Ni dung</h3>
<p>
<strong>URI ni dung</strong> là mt URI xác định d liu trong mt trình cung cp. URI ni dung
bao gm tên biu tượng ca toàn b trình cung cp (<strong>quyn</strong> ca nó) và mt
tên tr đến mt bng (<strong>đường dn</strong>). Khi bn gi
mt phương pháp máy khách để truy cp mt bng trong mt trình cung cp, URI ni dung cho bng là mt trong các
tham đối.
</p>
<p>
Trong các dòng mã trước, hng s
{@link android.provider.UserDictionary.Words#CONTENT_URI} chứa URI nội dung của
bng "từ" ca t đin người dùng. Đối tượng {@link android.content.ContentResolver}
s phân tích quyn ca URI, và s dng nó để "giải quyết" trình cung cp bng cách
so sánh quyn vi mt bng h thng ca các trình cung cp đã biết. Khi đó,
{@link android.content.ContentResolver} có th phân phi các tham đối truy vn ti đúng
trình cung cp.
</p>
<p>
{@link android.content.ContentProvider} s dng phn đường dn ca URI ni dung nhm chn
bng để truy cp. Trình cung cp thường có mt <strong>đường dn</strong> cho mi bng mà nó hin ra.
</p>
<p>
Trong các dòng mã trước, URI đầy đủ cho bng "từ" là:
</p>
<pre>
content://user_dictionary/words
</pre>
<p>
trong đó xâu <code>user_dictionary</code> là quyn ca trình cung cp, và
xâu <code>words</code> là đường dn ca bng. Xâu
<code>content://</code> (<strong>lược đồ</strong>) sẽ luôn có mặt,
và xác định đây là mt URI ni dung.
</p>
<p>
Nhiu trình cung cp cho phép bn truy cp mt hàng đơn l trong mt bng bng cách ni mt giá tr ID
vi đuôi ca URI. Ví dụ, để truy xut mt hàng có <code>_ID</code> là
<code>4</code> t mt t đin người dùng, bn có th s dng URI ni dung này:
</p>
<pre>
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
</pre>
<p>
Bn thường s dng các giá tr id khi bn đã truy xut mt tp hp các hàng, sau đó mun cp nht hoc xóa
mt trong s chúng.
</p>
<p class="note">
<strong>Lưu ý:</strong> Các lp {@link android.net.Uri} và {@link android.net.Uri.Builder}
cha các phương pháp thun tin để xây dng đối tượng URI định dng tt t các xâu.
{@link android.content.ContentUris} cha các phương pháp thun tin để ni các giá tr id vi
mt URI. Đon mã HTML trước s dng {@link android.content.ContentUris#withAppendedId
withAppendedId()} để ni mt id vi URI ni dung T đin Người dùng.
</p>
<!-- Retrieving Data from the Provider -->
<h2 id="SimpleQuery">Truy xut D liu t Trình cung cp</h2>
<p>
Phn này mô t cách truy xut d liu t mt trình cung cp bng cách s dng Trình cung cp T đin Người dùng
làm ví dụ.
</p>
<p class="note">
Để gii thích rõ, đon mã HTML trong phn này gi
{@link android.content.ContentResolver#query ContentResolver.query()} trên "luồng UI"". Tuy nhiên, trong
mã thc sự, bn nên thc hin các truy vn không đồng b trên mt lung riêng. Mt cách để làm
điu này đó là s dng lp {@link android.content.CursorLoader}, nó được mô t chi tiết hơn
trong hướng dn <a href="{@docRoot}guide/components/loaders.html">
Trình ti</a>. Bênh cnh đó, các dòng mã ch là đon mã HTML; chúng không th hin mt ng dng
hoàn chnh.
</p>
<p>
Để truy xut d liu t mt trình cung cp, hãy làm theo các bước cơ bn sau:
</p>
<ol>
<li>
Yêu cu quyn truy cp đọc cho trình cung cp.
</li>
<li>
Định nghĩa mã để gi mt truy vn ti trình cung cp.
</li>
</ol>
<h3 id="RequestPermissions">Yêu cu quyn truy cp đọc</h3>
<p>
Để truy xut d liu t mt trình cung cp, ng dng ca bn cn "quyền truy cập đọc" cho
trình cung cp. Bn không th yêu cu quyn này trong thi gian chy; thay vào đó, bn phi ch định rng
bn cn quyn này trong bn kê khai ca mình bng cách s dng phn t
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
và tên quyn chính xác được định nghĩa bi
trình cung cp. Khi bn ch định phn t này trong bn kê khai ca mình, bn đang thc tế hóa "yêu cầu" quyn
này cho ng dng ca mình. Khi người dùng cài đặt ng dng ca bn, h ngm hiu cp
yêu cu này.
</p>
<p>
Để tìm tên chính xác ca quyn truy cp đọc cho trình cung cp bn đang s dng, cũng như
tên cho các quyn truy cp khác được s dng bi trình truy cp, hãy xem trong tài liu
ca trình cung cp.
</p>
<p>
Vai trò ca quyn trong vic truy cp các trình cung cp được mô t chi tiết hơn trong phn
<a href="#Permissions">Quyn ca Trình cung cp Ni dung</a>.
</p>
<p>
Trình cung cp T đin Người dùng s định nghĩa quyn
<code>android.permission.READ_USER_DICTIONARY</code> trong tp bn kê khai ca nó, vì vy mt
ng dng mun đọc t trình cung cp s phi yêu cu quyn này.
</p>
<!-- Constructing the query -->
<h3 id="Query">Xây dng truy vn</h3>
<p>
Bước tiếp theo trong vic truy xut d liu t mt trình cung cp đó là xây dng mt truy vn. Đon mã HTML đầu tiên
này định nghĩa mt s biến cho vic truy cp Trình cung cp T đin Người dùng:
</p>
<pre class="prettyprint">
// A "projection" defines the columns that will be returned for each row
String[] mProjection =
{
UserDictionary.Words._ID, // Contract class constant for the _ID column name
UserDictionary.Words.WORD, // Contract class constant for the word column name
UserDictionary.Words.LOCALE // Contract class constant for the locale column name
};
// Defines a string to contain the selection clause
String mSelectionClause = null;
// Initializes an array to contain selection arguments
String[] mSelectionArgs = {""};
</pre>
<p>
Đon mã HTML tiếp theo cho biết cách s dng
{@link android.content.ContentResolver#query ContentResolver.query()}, bằng cách sử dụng Trình cung cấp Từ điển
Người dùng như mt ví dụ. Truy vn máy khách trình cung cp tương t như mt truy vn SQL, và nó cha mt
tp hp các ct để tr về, mt tp hp các tiêu chí la chn, và mt th t sp xếp.
</p>
<p>
Tp hp các ct mà truy vn cn tr v được gi là <strong>d tho</strong>
(biến <code>mProjection</code>).
</p>
<p>
Biu thc để ch định các hàng cn truy xut s được chia thành mt mnh đề la chn và
tham đối la chn. Mnh đề la chn là s kết hp gia các biu thc lô-gic và biu thc Boolean,
tên ct, và giá tr (biến <code>mSelectionClause</code>). Nếu bn ch định
tham s thay thế được <code>?</code> thay vì mt giá trị, phương pháp truy vn s truy xut giá tr
t mng tham đối la chn (biến <code>mSelectionArgs</code>).
</p>
<p>
Trong đon mã HTML tiếp theo, nếu người dùng không đin t thì mnh đề la chn được đặt thành
<code>null</code>, và truy vn tr v tt c các t trong trình cung cp. Nếu người dùng nhp
mt từ, mnh đề la chn được đặt thành <code>UserDictionary.Words.WORD + " = ?"</code> và
phn t đầu tiên ca mng tham đối la chn được đặt thành t mà người dùng đã nhp.
</p>
<pre class="prettyprint">
/*
* This defines a one-element String array to contain the selection argument.
*/
String[] mSelectionArgs = {""};
// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();
// Remember to insert code here to check for invalid or malicious input.
// If the word is the empty string, gets everything
if (TextUtils.isEmpty(mSearchString)) {
// Setting the selection clause to null will return all words
mSelectionClause = null;
mSelectionArgs[0] = "";
} else {
// Constructs a selection clause that matches the word that the user entered.
mSelectionClause = UserDictionary.Words.WORD + " = ?";
// Moves the user's input string to the selection arguments.
mSelectionArgs[0] = mSearchString;
}
// Does a query against the table and returns a Cursor object
mCursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
mProjection, // The columns to return for each row
mSelectionClause // Either null, or the word the user entered
mSelectionArgs, // Either empty, or the string the user entered
mSortOrder); // The sort order for the returned rows
// Some providers return null if an error occurs, others throw an exception
if (null == mCursor) {
/*
* Insert code here to handle the error. Be sure not to use the cursor! You may want to
* call android.util.Log.e() to log this error.
*
*/
// If the Cursor is empty, the provider found no matches
} else if (mCursor.getCount() &lt; 1) {
/*
* Insert code here to notify the user that the search was unsuccessful. This isn't necessarily
* an error. You may want to offer the user the option to insert a new row, or re-type the
* search term.
*/
} else {
// Insert code here to do something with the results
}
</pre>
<p>
Truy vn này tương t như câu lnh SQL:
</p>
<pre>
SELECT _ID, word, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
</pre>
<p>
Trong câu lnh SQL này, tên ct thc tế được s dng thay vì các hng s lp hp đồng.
</p>
<h4 id="Injection">Bo v trước mc nhp độc hi</h4>
<p>
Nếu d liu được qun lý bi trình cung cp ni dung nm trong mt cơ s d liu SQL, vic đin d liu không được tin cy t bên ngoài
vào các câu lnh SQL thô có th dn đến tiêm li SQL.
</p>
<p>
Hãy xét mnh đề la chn sau:
</p>
<pre>
// Constructs a selection clause by concatenating the user's input to the column name
String mSelectionClause = "var = " + mUserInput;
</pre>
<p>
Nếu bn làm vy, bn đang cho phép người dùng ghép ni SQL độc hi lên câu lnh SQL ca mình.
Ví dụ, người dùng có th đin "nothing; DROP TABLE *;" cho <code>mUserInput</code>, làm vy
s dn đến mnh đề la chn <code>var = nothing; DROP TABLE *;</code>. Do
mnh đề la chn được coi như mt câu lnh SQL, điu này có th khiến trình cung cp xóa tt c
bng trong cơ s d liu SQLite cơ bn (tr khi trình cung cp được thiết lp để bt nhng ln th
<a href="http://en.wikipedia.org/wiki/SQL_injection">tiêm li SQL</a>).
</p>
<p>
Để tránh vn đề này, hãy s dng mt mnh đề la chn mà s dng <code>?</code> làm tham s
thay thế được và mt mng các tham đối la chn riêng. Khi bn làm như vy, mc nhp ca người dùng
được gn kết trc tiếp vi truy vn thay vì được gii nghĩa như mt phn ca câu lnh SQL.
Vì nó không được coi như SQL, mc nhp ca người dùng không th tiêm li SQL độc hi. Thay vì s dng
ghép ni để đin mc nhp ca người dùng, hãy s dng mnh đề la chn này:
</p>
<pre>
// Constructs a selection clause with a replaceable parameter
String mSelectionClause = "var = ?";
</pre>
<p>
Thiết lp mng các tham đối la chn như sau:
</p>
<pre>
// Defines an array to contain the selection arguments
String[] selectionArgs = {""};
</pre>
<p>
Đặt mt giá tr trong mng các tham đối la chn như sau:
</p>
<pre>
// Sets the selection argument to the user's input
selectionArgs[0] = mUserInput;
</pre>
<p>
Mnh đề la chn mà s dng <code>?</code> như mt tham s thay thế được và mt mng
các tham đối la chn là cách được ưu tiên để ch định mt la chn, ngay c khi trình cung cp không
được da trên cơ s d liu SQL.
</p>
<!-- Displaying the results -->
<h3 id="DisplayResults">Hin th các kết qu truy vn</h3>
<p>
Phương pháp máy khách {@link android.content.ContentResolver#query ContentResolver.query()} luôn trả về
mt {@link android.database.Cursor} cha các ct được ch định bi d tho ca
truy vn cho các hàng khp vi các tiêu chí la chn ca truy vn. Mt đối tượng
{@link android.database.Cursor} cung cp truy cp đọc ngu nhiên vào các hàng và ct mà nó
cha. Bng cách s dng phương pháp {@link android.database.Cursor}, bn có th lp li các hàng trong
kết quả, xác định kiu d liu ca tng ct, ly d liu ra khi ct, và kim tra các tính cht khác
ca kết quả. Mt s trin khai {@link android.database.Cursor} s t động
cp nht đối tượng khi d liu ca trình cung cp thay đổi, hoc kích khi các phương pháp trong mt đối tượng quan sát
khi {@link android.database.Cursor} thay đổi, hoc c hai.
</p>
<p class="note">
<strong>Lưu ý:</strong> Mt trình cung cp có th hn chế truy cp vào các ct da trên tính cht ca
đối tượng thc hin truy vn. Ví dụ, Trình cung cp Danh b hn chế truy cp đối vi mt s ct cho
các trình điu hp đồng bộ, vì thế nó s không tr chúng v mt hot động hay dch vụ.
</p>
<p>
Nếu không hàng nào khp vi các tiêu chí la chn, trình cung cp
s tr v mt đối tượng {@link android.database.Cursor} mà trong đó
{@link android.database.Cursor#getCount Cursor.getCount()} bằng 0 (con chạy trống).
</p>
<p>
Nếu xy ra mt li ni bộ, các kết qu ca truy vn s ph thuc vào trình cung cp c thể. Nó có th
chn tr v <code>null</code>, hoc nó có th đưa ra mt li {@link java.lang.Exception}.
</p>
<p>
Do {@link android.database.Cursor} là mt "danh sách" hàng, mt cách hay để hin th
ni dung ca mt {@link android.database.Cursor} đó là liên kết nó vi mt {@link android.widget.ListView}
thông qua mt {@link android.widget.SimpleCursorAdapter}.
</p>
<p>
Đon mã HTML sau tiếp tc t đon mã HTML trước. Nó to mt đối tượng
{@link android.widget.SimpleCursorAdapter} cha {@link android.database.Cursor}
được truy xut bi truy vn, và đặt đối tượng này thành trình điu hp cho mt
{@link android.widget.ListView}:
</p>
<pre class="prettyprint">
// Defines a list of columns to retrieve from the Cursor and load into an output row
String[] mWordListColumns =
{
UserDictionary.Words.WORD, // Contract class constant containing the word column name
UserDictionary.Words.LOCALE // Contract class constant containing the locale column name
};
// Defines a list of View IDs that will receive the Cursor columns for each row
int[] mWordListItems = { R.id.dictWord, R.id.locale};
// Creates a new SimpleCursorAdapter
mCursorAdapter = new SimpleCursorAdapter(
getApplicationContext(), // The application's Context object
R.layout.wordlistrow, // A layout in XML for one row in the ListView
mCursor, // The result from the query
mWordListColumns, // A string array of column names in the cursor
mWordListItems, // An integer array of view IDs in the row layout
0); // Flags (usually none are needed)
// Sets the adapter for the ListView
mWordList.setAdapter(mCursorAdapter);
</pre>
<p class="note">
<strong>Lưu ý:</strong> Để lùi {@link android.widget.ListView} bng mt
{@link android.database.Cursor}, con chy phi cha mt ct có tên <code>_ID</code>.
Vì điu này, truy vn được hin lúc trước truy xut ct <code>_ID</code> cho
bng "từ" mc dù {@link android.widget.ListView} không hin th nó.
Hn chế này cũng gii thích lý do ti sao phn ln trình cung cp đều có mt ct <code>_ID</code> cho mi
bng ca nó.
</p>
<!-- Getting data from query results -->
<h3 id="GettingResults">Ly d liu t các kết qu truy vn</h3>
<p>
Thay vì ch hin th các kết qu truy vn, bn có th s dng chúng cho các tác v khác. Ví
dụ, bn có th truy xut chính t t mt t đin người dùng, ri sau đó tìm kiếm t đó trong
các trình cung cp khác. Để làm điu này, bn lp li các hàng trong {@link android.database.Cursor}:
</p>
<pre class="prettyprint">
// Determine the column index of the column named "word"
int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);
/*
* Only executes if the cursor is valid. The User Dictionary Provider returns null if
* an internal error occurs. Other providers may throw an Exception instead of returning null.
*/
if (mCursor != null) {
/*
* Moves to the next row in the cursor. Before the first movement in the cursor, the
* "row pointer" is -1, and if you try to retrieve data at that position you will get an
* exception.
*/
while (mCursor.moveToNext()) {
// Gets the value from the column.
newWord = mCursor.getString(index);
// Insert code here to process the retrieved word.
...
// end of while loop
}
} else {
// Insert code here to report an error if the cursor is null or the provider threw an exception.
}
</pre>
<p>
Trin khai {@link android.database.Cursor} s cha mt vài phương pháp get" để
truy xuất các kiểu dữ liệu khác nhau từ đối tượng. Ví dụ, đoạn mã HTML trước
sử dụng {@link android.database.Cursor#getString getString()}. Chúng cũng có một phương pháp
{@link android.database.Cursor#getType getType()} để trả về một giá trị cho biết
kiểu dữ liệu của cột.
</p>
<!-- Requesting permissions -->
<h2 id="Permissions">Quyền của Trình cung cấp Nội dung</h2>
<p>
Ứng dụng của một trình cung cấp có thể chỉ định các quyền mà ứng dụng khác có thể có để
truy cập dữ liệu của trình cung cấp đó. Những quyền này đảm bảo rằng người dùng biết một ứng dụng
sẽ cố gắng truy cập dữ liệu nào. Dựa trên các yêu cầu của trình cung cấp, các ứng dụng khác
yêu cầu quyền mà chúng cần để truy cập trình dữ liệu. Người dùng cuối thấy các quyền
được yêu cầu khi họ cài đặt ứng dụng.
</p>
<p>
Nếu ứng dụng của một trình cung cấp không chỉ định bất kỳ quyền nào, khi đó các ứng dụng khác không có
quyền truy cập dữ liệu của trình cung cấp. Tuy nhiên, các thành phần trong ứng dụng của trình cung cấp luôn có
đầy đủ quyền truy nhập đọc và ghi, không phụ thuộc vào các quyền được chỉ định.
</p>
<p>
Như đã lưu ý, Trình cung cấp Từ điển Người dùng sẽ yêu cầu
quyền <code>android.permission.READ_USER_DICTIONARY</code> để truy xuất dữ liệu từ nó.
Trình cung cấp có quyền <code>android.permission.WRITE_USER_DICTIONARY</code>
riêng để chèn, cập nhật, hoặc xóa dữ liệu.
</p>
<p>
Để nhận các quyền cần để truy cập một trình cung cấp, ứng dụng yêu cầu chúng bằng một phần tử
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
trong tệp bản kê khai của nó. Khi Trình quản lý Gói Android cài đặt các ứng dụng, người dùng
phải phê chuẩn tất cả quyền mà ứng dụng yêu cầu. Nếu người dùng phê chuẩn tất cả quyền, khi đó
Trình quản lý Gói sẽ tiếp tục cài đặt; nếu người dùng không phê chuẩn chúng, Trình quản lý Gói sẽ
hủy bỏ việc cài đặt.
</p>
<p>
Phần tử
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
sau yêu cầu quyền truy cập đọc vào Trình cung cấp Từ điển Người dùng:
</p>
<pre>
&lt;uses-permission android:name="android.permission.READ_USER_DICTIONARY"&gt;
</pre>
<p>
Tác động của các quyền tới việc truy cập trình cung cấp được giải thích chi tiết hơn trong
hướng dẫn <a href="{@docRoot}guide/topics/security/security.html">Bảo mật và Quyền</a>.
</p>
<!-- Inserting, Updating, and Deleting Data -->
<h2 id="Modifications">Chèn, Cập nhật, và Xóa Dữ liệu</h2>
<p>
Giống như cách bạn truy xuất dữ liệu từ một trình cung cấp, bạn cũng có thể sử dụng tương tác giữa
một máy khách cung cấp và {@link android.content.ContentProvider} của trình cung cấp để sửa đổi dữ liệu.
Bạn gọi một phương pháp {@link android.content.ContentResolver} với các tham đối được chuyển sang
phương pháp {@link android.content.ContentProvider} tương ứng. Trình cung cấp và
máy khách cung cấp sẽ tự động xử lý bảo mật và truyền thông liên tiến trình.
</p>
<h3 id="Inserting">Chèn dữ liệu</h3>
<p>
Để chèn dữ liệu vào một trình cung cấp, bạn gọi phương pháp
{@link android.content.ContentResolver#insert ContentResolver.insert()}
. Phương pháp này chèn một hàng mới vào trình cung cấp và trả về một URI nội dung cho hàng đó.
Đoạn mã HTML này cho biết cách chèn một từ mới vào Trình cung cấp Từ điển Người dùng:
</p>
<pre class="prettyprint">
// Defines a new Uri object that receives the result of the insertion
Uri mNewUri;
...
// Defines an object to contain the new values to insert
ContentValues mNewValues = new ContentValues();
/*
* Sets the values of each column and inserts the word. The arguments to the "put"
* method are "column name" and "value"
*/
mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
mNewValues.put(UserDictionary.Words.WORD, "insert");
mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
mNewUri = getContentResolver().insert(
UserDictionary.Word.CONTENT_URI, // the user dictionary content URI
mNewValues // the values to insert
);
</pre>
<p>
Dữ liệu cho hàng mới đi vào trong một đối tượng {@link android.content.ContentValues} đơn lẻ, đối tượng này
có dạng tương tự như con chạy một hàng. Các cột trong đối tượng này không cần có
cùng kiểu dữ liệu, và nếu hoàn toàn không muốn chỉ định một giá trị, bạn có thể đặt một cột
thành <code>null</code> bằng cách sử dụng {@link android.content.ContentValues#putNull ContentValues.putNull()}.
</p>
<p>
Đoạn mã HTML không thêm cột <code>_ID</code> vì cột này được tự động
duy trì. Trình cung cấp sẽ gán một giá trị duy nhất <code>_ID</code> cho mỗi hàng được
thêm. Các trình cung cấp thường sử dụng giá trị này làm khóa chính của bảng.
</p>
<p>
URI nội dung được trả về trong <code>newUri</code> sẽ xác định hàng mới thêm, có
định dạng như sau:
</p>
<pre>
content://user_dictionary/words/&lt;id_value&gt;
</pre>
<p>
<code>&lt;id_value&gt;</code> là nội dung của <code>_ID</code> cho hàng mới.
Hầu hết các trình cung cấp đều có thể tự động phát hiện dạng URI nội dung này rồi thực hiện thao tác được yêu cầu
trên hàng cụ thể đó.
</p>
<p>
Để nhận giá trị <code>_ID</code> từ {@link android.net.Uri} được trả về, hãy gọi
{@link android.content.ContentUris#parseId ContentUris.parseId()}.
</p>
<h3 id="Updating">Cập nhật dữ liệu</h3>
<p>
Để cập nhật một hàng, bạn sử dụng một đối tượng {@link android.content.ContentValues} với các giá trị
được cập nhật giống như cách bạn làm với việc chèn, và các tiêu chí lựa chọn giống như cách bạn làm với truy vấn.
Phương pháp máy khách mà bạn sử dụng là
{@link android.content.ContentResolver#update ContentResolver.update()}. Bạn chỉ cần thêm
các giá trị vào đối tượng {@link android.content.ContentValues} cho các cột mà bạn đang cập nhật. Nếu bạn
muốn xóa các nội dung của một cột, hãy đặt giá trị thành <code>null</code>.
</p>
<p>
Đoạn mã HTML sau thay đổi tất cả hàng với cột bản địa có ngôn ngữ "en" thành cột
có bản địa là <code>null</code>. Giá trị trả về là số hàng đã được cập nhật:
</p>
<pre>
// Defines an object to contain the updated values
ContentValues mUpdateValues = new ContentValues();
// Defines selection criteria for the rows you want to update
String mSelectionClause = UserDictionary.Words.LOCALE + "LIKE ?";
String[] mSelectionArgs = {"en_%"};
// Defines a variable to contain the number of updated rows
int mRowsUpdated = 0;
...
/*
* Sets the updated value and updates the selected words.
*/
mUpdateValues.putNull(UserDictionary.Words.LOCALE);
mRowsUpdated = getContentResolver().update(
UserDictionary.Words.CONTENT_URI, // the user dictionary content URI
mUpdateValues // the columns to update
mSelectionClause // the column to select on
mSelectionArgs // the value to compare to
);
</pre>
<p>
Bạn cũng nên thanh lọc thông tin đầu vào của người dùng khi gọi
{@link android.content.ContentResolver#update ContentResolver.update()}. Để tìm hiểu thêm về
điều này, hãy đọc phần <a href="#Injection">Bảo vệ trước mục nhập độc hại</a>.
</p>
<h3 id="Deleting">Xóa d liu</h3>
<p>
Xóa hàng tương t như truy xut d liu hàng: bn ch định các tiêu chí la chn cho hàng
mà bn mun xóa và phương pháp máy khách tr v s hàng được xóa.
Đon mã HTML sau xóa các hàng có appid khp vi "user". Phương pháp s tr v
s hàng được xóa.
</p>
<pre>
// Defines selection criteria for the rows you want to delete
String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";
String[] mSelectionArgs = {"user"};
// Defines a variable to contain the number of rows deleted
int mRowsDeleted = 0;
...
// Deletes the words that match the selection criteria
mRowsDeleted = getContentResolver().delete(
UserDictionary.Words.CONTENT_URI, // the user dictionary content URI
mSelectionClause // the column to select on
mSelectionArgs // the value to compare to
);
</pre>
<p>
Bn cũng nên thanh lc thông tin đầu vào ca người dùng khi gi
{@link android.content.ContentResolver#delete ContentResolver.delete()}. Để tìm hiểu thêm về
điu này, hãy đọc phn <a href="#Injection">Bo v trước mc nhp độc hi</a>.
</p>
<!-- Provider Data Types -->
<h2 id="DataTypes">Các Kiu D liu ca Trình cung cp</h2>
<p>
Trình cung cp ni dung có th cung cp nhiu kiu d liu khác nhau. Trình cung cp T đin Người dùng ch cung cp
văn bn, nhưng trình cung cp cũng có th cung cp các định dng sau:
</p>
<ul>
<li>
integer
</li>
<li>
long integer (long)
</li>
<li>
floating point
</li>
<li>
long floating point (double)
</li>
</ul>
<p>
Mt kiu d liu khác mà các trình cung cp thường s dng đó là Binary Large OBject (BLOB) được trin khai như mt
mng 64KB byte. Bn có th xem các kiu d liu có sn bng cách xem các phương pháp "get" lp
{@link android.database.Cursor}.
</p>
<p>
Kiu d liu đối vi mi ct trong mt trình cung cp thường được lit kê trong tài liu ca trình cung cp đó.
Các kiu d liu dành cho Trình cung cp T đin Người dùng được lit kê trong tài liu tham kho
cho lp hp đồng {@link android.provider.UserDictionary.Words} ca nó (lp hp đồng được
mô t trong phn <a href="#ContractClasses">Các Lp Hp đồng</a>).
Bn cũng có th xác định kiu d liu bng cách gi {@link android.database.Cursor#getType
Cursor.getType()}.
</p>
<p>
Trình cung cp cũng duy trì thông tin v kiu d liu MIME cho mi URI ni dung mà chúng định nghĩa. Bn có th
s dng thông tin v kiu MIME để tìm hiu xem ng dng ca mình có th x lý d liu mà
trình cung cp đưa ra hay không, hoc để chn mt kiu x lý da trên kiu MIME. Bn thường cn kiu
MIME khi đang làm vic vi mt trình cung cp cha các cu trúc hoc tp
d liu phc tp. Ví dụ, bng {@link android.provider.ContactsContract.Data}
trong Trình cung cp Danh b s dng các kiu MIME để dán nhãn kiu d liu liên lc được lưu tr trong tng
hàng. Để nhn được kiu MIME tương ng vi mt URI ni dung, hãy gi
{@link android.content.ContentResolver#getType ContentResolver.getType()}.
</p>
<p>
Phn <a href="#MIMETypeReference">Tham kho Kiu MIME</a> mô t
cú pháp ca c kiu MIME tiêu chun ln tùy chnh.
</p>
<!-- Alternative Forms of Provider Access -->
<h2 id="AltForms">Các Hình thc Truy cp Trình cung cp Thay thế</h2>
<p>
Có ba hình thc truy cp trình cung cp thay thế quan trng trong phát trin ng dng:
</p>
<ul>
<li>
<a href="#Batch">Truy cp hàng lot</a>: Bn có th to mt lot lnh gi truy cp bng các phương pháp trong
lp {@link android.content.ContentProviderOperation}, ri sau đó áp dng chúng vi
{@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}.
</li>
<li>
Truy vn không đồng bộ: Bn nên thc hin các truy vn trong mt lung riêng. Mt cách để làm điu này đó là
s dng mt đối tượng {@link android.content.CursorLoader}. Các ví d trong
hướng dn <a href="{@docRoot}guide/components/loaders.html">Trình ti</a> s minh ha
cách làm điu này.
</li>
<li>
<a href="#Intents">Truy cp d liu thông qua ý định</a>: Mc dù không th gi mt ý định
trc tiếp ti mt trình cung cp, bn có th gi mt ý định ti ng dng ca trình cung cp đó,
đây thường là cách tt nht để sa đổi d liu ca trình cung cp.
</li>
</ul>
<p>
Truy cp hàng lot và sa đổi thông qua ý định được mô t trong các phn sau.
</p>
<h3 id="Batch">Truy cp hàng lot</h3>
<p>
Truy cp hàng lot vào mt trình cung cp là cách hu ích để chèn nhiu hàng, hoc để chèn
các hàng vào nhiu bng trong cùng lnh gi phương pháp, hoc nhìn chung để thc hin mt tp hp
thao tác qua các ranh gii tiến trình như mt giao tác (thao tác nguyên tử).
</p>
<p>
Để truy cp mt trình cung cp trong "chế độ hàng loạt",
bn to mt mng đối tượng {@link android.content.ContentProviderOperation} ri
phân phi chúng ti mt trình cung cp ni dung bng
{@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Bạn chuyển
<em>quyn</em> ca trình cung cp ni dung cho phương pháp này thay vì mt URI ni dung c thể.
Điu này cho phép đối tượng {@link android.content.ContentProviderOperation} trong mng có tác dng
đối vi mt bng khác. Mt lnh gi ti {@link android.content.ContentResolver#applyBatch
ContentResolver.applyBatch()} tr v mt mng kết quả.
</p>
<p>
Mô t lp hp đồng {@link android.provider.ContactsContract.RawContacts}
bao gm mt đon mã HTML th hin vic chèn hàng lot. ng dng mu
<a href="{@docRoot}resources/samples/ContactManager/index.html">Trình qun lý Danh bạ</a>
có mt ví d v truy cp hàng lot trong tp ngun <code>ContactAdder.java</code>
ca nó.
</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Hin th d liu bng cách s dng mt ng dng trình tr giúp.</h2>
<p>
Nếu ng dng ca bn <em>có</em> quyn truy cp, bn vn có th cn s dng mt
ý định để hin th d liu trong mt ng dng khác. Ví dụ, ng dng Lch chp nhn mt
ý định {@link android.content.Intent#ACTION_VIEW}, nhằm hiển thị một ngày hoặc sự kiện cụ thể.
Điu này cho phép bn hin th thông tin lch mà không phi to UI ca chính mình.
Để tìm hiu thêm v tính năng này, hãy xem
hướng dn <a href="{@docRoot}guide/topics/providers/calendar-provider.html">Trình cung cp Lch</a>.
</p>
<p>
ng dng mà bn gi ý định đến không nht thiết phi là ng dng
được liên kết vi trình cung cp. Ví dụ, bn có th truy xut mt liên lc t
Trình cung cp Danh bạ, ri gi mt ý định {@link android.content.Intent#ACTION_VIEW}
cha URI ni dung cho hình nh liên lc ti mt trình xem nh.
</p>
</div>
</div>
<h3 id="Intents">Truy cp d liu thông qua ý định</h3>
<p>
Ý định có th cho phép truy cp gián tiếp vào mt trình cung cp ni dung. Bn cho phép người dùng truy cp
d liu trong mt trình cung cp ngay c khi ng dng ca bn không có quyn truy cp, hoc bng cách
nhn li mt ý định kết qu t mt ng dng có quyn, hoc bng cách kích hot mt
ng dng có phép và cho phép người dùng được làm vic trong nó.
</p>
<h4>Được truy cp vi các quyn tm thi</h4>
<p>
Bn có th truy cp d liu trong mt trình cung cp ni dung, ngay c khi bn không có quyn
truy nhp phù hp, bng cách gi mt ý định ti mt ng dng có quyn và
nhn li mt ý định kết qu cha quyn "URI".
Đây là nhng quyn cho mt URI ni dung c th kéo dài ti khi hot động nhn chúng
được hoàn thành. ng dng có quyn lâu dài s cp quyn tm thi
bng cách đặt mt c trong ý định kết quả:
</p>
<ul>
<li>
<strong>Quyn đọc:</strong>
{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}
</li>
<li>
<strong>Quyn ghi:</strong>
{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}
</li>
</ul>
<p class="note">
<strong>Lưu ý:</strong> Nhng c này không cp quyn truy cp đọc và ghi nói chung cho trình cung cp
mà có quyn được cha trong URI ni dung. Quyn truy cp này ch áp dng cho chính URI đó.
</p>
<p>
Trình cung cp s định nghĩa quyn URI cho các URI ni dung trong bn kê khai ca nó, bng cách s dng thuc tính
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code>
ca phn t
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
cũng như phn t con
<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
ca phn t
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
. Cơ chế cp quyn URI này được gii thích chi tiết hơn trong
hướng dn <a href="{@docRoot}guide/topics/security/security.html">Bo mt và Quyn</a>,
trong phn "Quyền URI".
</p>
<p>
Ví dụ, bn có th truy xut d liu cho mt liên lc trong Trình cung cp Danh bạ, ngay c khi bn không
có quyn {@link android.Manifest.permission#READ_CONTACTS}. Bạn có thể muốn thực hiện điều này
trong mt ng dng gi thip mng đin t ti mt liên lc vào ngày sinh nht ca người đó. Thay vì
yêu cu {@link android.Manifest.permission#READ_CONTACTS}, là nơi cấp cho bạn quyền truy cập tất cả liên lạc
ca người dùng và tt c thông tin ca họ, bn nên cho phép người dùng kim soát nhng liên lc
nào được s dng bi ng dng ca bn. Để làm điu này, bn s dng tiến trình sau:
</p>
<ol>
<li>
ng dng ca bn gi mt ý định cha hành động
{@link android.content.Intent#ACTION_PICK} và kiểu MIME "danh bạ"
{@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}, bằng cách sử dụng
phương pháp {@link android.app.Activity#startActivityForResult
startActivityForResult()}.
</li>
<li>
Vì ý định này khp vi b lc ý định cho hot động
"lựa chọn" ca ng dng Danh bạ, hot động s đi đến tin cnh.
</li>
<li>
Trong hot động la chn, người dùng chn mt
liên lc để cp nht. Khi điu này xy ra, hot động la chn s gi
{@link android.app.Activity#setResult setResult(resultcode, intent)}
để thiết lp mt ý định nhm gi li ng dng ca bn. Ý định cha URI ni dung
ca liên lc mà người dùng đã chn, và các c "phụ thêm"
{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. Những cờ này cấp quyền URI
cho ng dng ca bn để đọc d liu cho liên lc được tr đến bi
URI ni dung. Sau đó, hot động la chn gi {@link android.app.Activity#finish()} để
tr kim soát v ng dng ca bn.
</li>
<li>
Hot động ca bn tr v tin cnh, và h thng s gi phương pháp
{@link android.app.Activity#onActivityResult onActivityResult()}
ca hot động ca bn. Phương pháp này nhn được ý định kết qu do hot động la chn to trong
ng dng Danh bạ.
</li>
<li>
Vi URI ni dung t ý định kết quả, bn có th đọc d liu ca liên lc
t Trình cung cp Danh bạ, ngay c khi bn không yêu cu quyn truy cp đọc lâu dài
vào trình cung cp trong bn kê khai ca mình. Sau đó, bn có th nhn thông tin ngày sinh ca liên lc
hoc địa ch e-mail ca người đó ri gi thip mng đin tử.
</li>
</ol>
<h4>S dng mt ng dng khác</h4>
<p>
Mt cách đơn gin để cho phép người dùng sa đổi d liu mà bn không có quyn truy cp đó là
kích hot mt ng dng có quyn và cho phép người dùng làm vic đó.
</p>
<p>
Ví dụ, ng dng Lch chp nhn mt
ý định {@link android.content.Intent#ACTION_INSERT}, nó cho phép bạn kích hoạt UI chèn
ca ng dng. Bn có th chuyn d liu "phụ thêm" trong ý định này mà được ng dng s dng
để đin trước vào UI. Vì các s kin định k có cú pháp phc tp, cách
ưu tiên để chèn s kin vào Trình cung cp Lch đó là kích hot ng dng Lch vi mt
{@link android.content.Intent#ACTION_INSERT} rồi để người dùng chèn sự kiện tại đó.
</p>
<!-- Contract Classes -->
<h2 id="ContractClasses">Các Lp Hp đồng</h2>
<p>
Lp hp đồng định nghĩa các hng s s giúp ng dng hot động vi các URI ni dung, tên
ct, hành động ý định, và các tính năng khác ca mt trình cung cp ni dung. Các lp hp đồng không
được t động đưa vào cùng mt trình cung cp; nhà phát trin ca trình cung cp phi định nghĩa chúng ri
cung cp chúng cho các nhà phát trin khác. Nhiu trình cung cp được bao gm cùng vi nn tng
Android có các lp hp đồng tương ng trong gói {@link android.provider}.
</p>
<p>
Ví dụ, Trình cung cp T đin Người dùng có mt lp hp đồng
{@link android.provider.UserDictionary} cha các hng s URI ni dung và tên ct. URI ni dung
đối vi bng "từ" được định nghĩa trong hng s
{@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI}.
Lp {@link android.provider.UserDictionary.Words} cũng cha các hng s tên ct,
chúng được s dng trong đon mã HTML mu trong hướng dn này. Ví dụ, mt d tho truy vn có th được
định nghĩa là:
</p>
<pre>
String[] mProjection =
{
UserDictionary.Words._ID,
UserDictionary.Words.WORD,
UserDictionary.Words.LOCALE
};
</pre>
<p>
Mt lp hp đồng khác là {@link android.provider.ContactsContract} dành cho Trình cung cp Danh bạ.
Tài liu tham kho cho lp này bao gm các đon mã HTML mu. Mt trong s các
lp con ca nó, {@link android.provider.ContactsContract.Intents.Insert}, là mt lp hp đồng
cha các hng s cho ý định và d liu ý định.
</p>
<!-- MIME Type Reference -->
<h2 id="MIMETypeReference">Tham kho Kiu MIME</h2>
<p>
Trình cung cp ni dung có th tr v các kiu phương tin MIME tiêu chun, hoc xâu kiu MIME tùy chnh, hoc c hai.
</p>
<p>
Các kiu MIME có định dng
</p>
<pre>
<em>type</em>/<em>subtype</em>
</pre>
<p>
Ví dụ, kiu MIME thông dng <code>text/html</code> có kiểu <code>text</code> và
kiu con <code>html</code>. Nếu trình cung cp tr v loi này cho mt URI, điu đó có nghĩa rng mt
truy vn đang s dng URI đó s tr v văn bn cha th HTML.
</p>
<p>
Các xâu kiu MIME tùy chnh, còn gi là kiu MIME "theo nhà cung cấp", có các giá tr
<em>kiu</em> và <em>kiểu con</em> phc tp hơn. Giá tr <em>kiu</em> luôn luôn
</p>
<pre>
vnd.android.cursor.<strong>dir</strong>
</pre>
<p>
áp dng cho nhiu hàng, hoc
</p>
<pre>
vnd.android.cursor.<strong>item</strong>
</pre>
<p>
áp dng cho mt hàng.
</p>
<p>
Giá tr <em>kiu con</em> áp dng theo trình cung cp. Các trình cung cp được tích hp trong Android thường có mt kiu con
đơn gin. Ví dụ, khi ng dng Danh b to mt hàng cho mt s đin thoi,
nó đặt kiu MIME sau trong hàng:
</p>
<pre>
vnd.android.cursor.item/phone_v2
</pre>
<p>
Để ý rng giá tr kiu con đơn gin là <code>phone_v2</code>.
</p>
<p>
Các nhà phát trin trình cung cp khác có th to mu hình kiu con ca riêng mình da trên quyn
và tên bng ca trình cung cp. Ví dụ, xét mt trình cung cp cha các biu thi gian lch tàu.
Quyn ca trình cung cp là <code>com.example.trains</code>, và nó cha các bng
Line1, Line2, và Line3. Để phn hi li URI ni dung
</p>
<p>
<pre>
content://com.example.trains/Line1
</pre>
<p>
đối vi bng Line1, trình cung cp tr v kiu MIME
</p>
<pre>
vnd.android.cursor.<strong>dir</strong>/vnd.example.line1
</pre>
<p>
Để phn hi li URI ni dung
</p>
<pre>
content://com.example.trains/Line2/5
</pre>
<p>
đối vi hàng 5 trong bng Line2, trình cung cp tr v kiu MIME
</p>
<pre>
vnd.android.cursor.<strong>item</strong>/vnd.example.line2
</pre>
<p>
Hu hết các trình cung cp ni dung đều định nghĩa hng s lp hp đồng cho các kiu MIME mà chúng s dng. Ví d như lp hp đồng
ca Trình cung cp Danh b {@link android.provider.ContactsContract.RawContacts},
s định nghĩa hng s
{@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} cho kiểu MIME của
mt hàng liên lc thô duy nht.
</p>
<p>
Các URI ni dung đối vi hàng duy nht được mô t trong phn
<a href="#ContentURIs">URI ni dung</a>.
</p>