blob: fcc9b0eb60ef01a6e7aec80eda21a9e4092f79bf [file] [log] [blame]
page.title=To mt Trình cung cp Ni dung
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Trong tài liu này</h2>
<ol>
<li>
<a href="#DataStorage">Thiết kế Kho lưu tr D liu</a>
</li>
<li>
<a href="#ContentURI">Thiết kế URI Ni dung</a>
</li>
<li>
<a href="#ContentProvider">Trin khai Lp Trình cung cp Ni dung</a>
<ol>
<li>
<a href="#RequiredAccess">Phương pháp được Yêu cu</a>
</li>
<li>
<a href="#Query">Trin khai phương pháp query()</a>
</li>
<li>
<a href="#Insert">Trin khai phương pháp insert()</a>
</li>
<li>
<a href="#Delete">Trin khai phương pháp delete()</a>
</li>
<li>
<a href="#Update">Trin khai phương pháp update()</a>
</li>
<li>
<a href="#OnCreate">Trin khai phương pháp onCreate()</a>
</li>
</ol>
</li>
<li>
<a href="#MIMETypes">Trin khai Kiu MIME ca Trình cung cp Ni dung</a>
<ol>
<li>
<a href="#TableMIMETypes">Kiu MIME cho bng</a>
</li>
<li>
<a href="#FileMIMETypes">Kiu MIME cho tp</a>
</li>
</ol>
</li>
<li>
<a href="#ContractClass">Trin khai mt Lp Hp đồng</a>
</li>
<li>
<a href="#Permissions">Trin khai Quyn ca Trình cung cp Ni dung</a>
</li>
<li>
<a href="#ProviderElement">Phn t &lt;provider&gt;</a>
</li>
<li>
<a href="#Intents" định và Truy cp D liu</a>
</li>
</ol>
<h2>Lp khóa</h2>
<ol>
<li>
{@link android.content.ContentProvider}
</li>
<li>
{@link android.database.Cursor}
</li>
<li>
{@link android.net.Uri}
</li>
</ol>
<h2>Các Mu Liên quan</h2>
<ol>
<li>
<a href="{@docRoot}resources/samples/NotePad/index.html">
ng dng mu Note Pad
</a>
</li>
</ol>
<h2>Xem thêm</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Ni dung Cơ bn v 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>
<p>
Trình cung cp ni dung qun lý truy cp vào mt kho d liu tp trung. Bn trin khai mt
trình cung cp thành mt hoc nhiu lp trong mt ng dng Android, bên cnh các phn t trong
tp bn kê khai. Mt trong các lp ca bn trin khai mt lp con
{@link android.content.ContentProvider}, đây là giao din gia trình cung cp ca bn và
các ng dng khác. Mc dù mc đích ca các trình cung cp ni dung khác là cung cp d liu có sn cho các
ng dng khác, dĩ nhiên bn có th ra lnh cho các hot động trong ng dng ca mình
truy vn và sa đổi d liu được qun lý bi trình cung cp ca bn.
</p>
<p>
Phn còn li ca ch đề này là mt danh sách cơ bn v các bước để xây dng mt trình cung cp ni dung và mt danh sách
các API để s dng.
</p>
<!-- Before You Start Building -->
<h2 id="BeforeYouStart">Trước khi Bn Bt đầu Xây dng</h2>
<p>
Trước khi bn bt đầu xây dng mt trình cung cp, hãy làm vic sau:
</p>
<ol>
<li>
<strong>Quyết định xem bn có cn mt trình cung cp ni dung không</strong>. Bn cn xây dng mt trình cung cp
ni dung nếu mun cung cp mt hoc nhiu tính năng sau đây:
<ul>
<li>Bn mun cung cp d liu hoc tp phc tp cho các ng dng khác.</li>
<li>Bn mun cho phép người dùng sao chép d liu phc tp t ng dng ca bn vào các ng dng khác.</li>
<li>Bn mun cung cp các gi ý tìm kiếm tùy chnh bng cách s dng khuôn kh tìm kiếm.</li>
</ul>
<p>
Bn <em>không</em> cn trình cung cp phi s dng mt cơ s d liu SQLite nếu vic s dng hoàn toàn
din ra trong ng dng ca bn.
</p>
</li>
<li>
Nếu bn chưa làm như vy, hãy đọc ch đề
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Ni dung Cơ bn v Trình cung cp Ni dung</a> để tìm hiu thêm v trình cung cp.
</li>
</ol>
<p>
Tiếp theo, hãy làm theo nhng bước sau để xây dng trình cung cp ca bn:
</p>
<ol>
<li>
Thiết kế kho lưu tr thô cho d liu ca bn. Mt trình cung cp ni dung s cung cp d liu theo hai cách:
<dl>
<dt>
D liu tp
</dt>
<dd>
D liu mà thường đến các tp chng hn như
nh, âm thanh, hoc video. Lưu tr các tp không gian
riêng tư trong ng dng ca bn. Để hi đáp li mt yêu cu tp t mt ng dng khác, trình cung cp
ca bn có th cung cp mt núm điu tác cho tp.
</dd>
<dt>
D liu "cấu trúc"
</dt>
<dd>
D liu mà thường đến mt cơ s d liu, mng, hoc cu trúc tương tự.
Lưu tr d liu dưới dng tương thích vi các bng hàng ct. Hàng
biu din mt đối tượng, chng hn như mt người hoc khon mc trong kim kê. Ct biu din
mt s d liu cho đối tượng, chng hn như tên ca mt người hoc giá ca mt khon mc. Mt cách thường dùng để
lưu tr loi d liu này đó là trong cơ s d liu SQLite, nhưng bn có th s dng bt k loi
kho lưu tr lâu dài nào. Để tìm hiu thêm v các loi kho lưu tr có sn trong
h thng Android, hãy xem phn <a href="#DataStorage">
Thiết kế Kho lưu tr D liu</a>.
</dd>
</dl>
</li>
<li>
Định nghĩa mt trin khai c th ca lp {@link android.content.ContentProvider} và
các phương pháp được yêu cu ca nó. Lp này là giao din gia d liu ca bn và phn còn li ca
h thng Android. Để biết thêm thông tin v lp này, hãy xem phn
<a href="#ContentProvider">Trin khai Lp ContentProvider</a>.
</li>
<li>
Định nghĩa xâu thm quyn ca trình cung cp, URI ni dung ca nó, và các tên ct. Nếu bn mun
ng dng ca trình cung cp x lý các ý định, hãy định nghĩa các hành động ý định, d liu ph thêm,
và cờ. Đồng thi, hãy định nghĩa các quyn mà bn s yêu cu cho nhng ng dng mun
truy cp d liu ca bn. Bn nên cân nhc định nghĩa tt c nhng giá tr này là hng s trong mt
lp riêng; sau đó, bn có th cho hin lp này ra vi các nhà phát trin khác. Để biết thêm
thông tin v URI ni dung, hãy xem
phn <a href="#ContentURI">Thiết kế URI Ni dung</a>.
Để biết thêm thông tin v ý định, hãy xem
phn <a href="#Intents" định và Truy cp D liu</a>.
</li>
<li>
Thêm các ni dung tùy chn khác, chng hn như d liu mu hoc trin
khai {@link android.content.AbstractThreadedSyncAdapter} mà có th đồng b hoá d liu gia
trình cung cp và d liu nn đám mây.
</li>
</ol>
<!-- Designing Data Storage -->
<h2 id="DataStorage">Thiết kế Kho lưu tr D liu</h2>
<p>
Trình cung cp ni dung là giao din đối vi d liu được lưu theo mt định dng cu trúc. Trước khi to
giao din, bn phi quyết định cách lưu tr d liu. Bn có th lưu tr d liu theo bt k dng nào
mà bn mun ri thiết kế giao din để đọc và ghi d liu nếu cn thiết.
</p>
<p>
Có mt s công ngh lưu tr d liu có sn trong Android:
</p>
<ul>
<li>
H thng Android bao gm mt API cơ s d liu SQLite mà các trình cung cp ca chính Androi s dng
để lưu tr d liu theo định hướng bng. Lp
{@link android.database.sqlite.SQLiteOpenHelper} giúp bn to cơ s d liu, và lp
{@link android.database.sqlite.SQLiteDatabase} là lp cơ bn để đánh giá
các cơ s d liu.
<p>
Nh rng bn không phi s dng mt cơ s d liu để trin khai kho lưu gi ca mình. B ngoài, mt trình cung cp
có dng như là mt tp hp bng, tương t như mt cơ s d liu quan hệ, nhưng đây
không phi là mt yêu cu đối vi vic trin khai ni b ca trình cung cp.
</p>
</li>
<li>
Để lưu tr d liu tp, Android có nhiu API định hướng tp khác nhau.
Để tìm hiu thêm v lưu tr tp, hãy đọc ch đề
<a href="{@docRoot}guide/topics/data/data-storage.html">Kho lưu tr D liu</a>. Nếu bn
đang thiết kế mt trình cung cp d liu liên quan ti phương tin chng hn như nhc hay video, bn có th
có mt trình cung cp cho phép kết hp d liu bng và các tp.
</li>
<li>
Để làm vic vi d liu trên nn mng, hãy s dng các lp trong {@link java.net} và
{@link android.net}. Bn cũng có th đồng b hoá d liu trên nn mng vi mt kho lưu tr d liu cc b
chng hn như mt cơ s d liu, ri cung cp d liu dưới dng bng hoc tp.
ng dng mu <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
Trình điu hp Đồng b Mu</a> minh ha loi đồng b hoá này.
</li>
</ul>
<h3 id="DataDesign">
Nhng ni dung cn xem xét khi thiết kế d liu
</h3>
<p>
Sau đây là mt s mo để thiết kế cu trúc d liu cho trình cung cp ca bn:
</p>
<ul>
<li>
D liu bng nên luôn có mt ct "khóa chính" mà trình cung cp duy trì
như mt giá tr s duy nht cho mi hàng. Bn có th s dng giá tr này để liên kết hàng vi các hàng
có liên quan trong các bng khác (s dng nó làm "khóa ngoại"). Mc dù bn có th s dng bt k tên gi nào
cho ct này, s dng {@link android.provider.BaseColumns#_ID BaseColumns._ID} là lựa chọn tốt nhất
vì vic liên kết các kết qu ca mt truy vn trình cung cp vi
{@link android.widget.ListView} đòi hi mt trong các ct được truy xut phi có tên
<code>_ID</code>.
</li>
<li>
Nếu bn mun cung cp các hình nh bitmap hoc ni dung d liu định hướng tp rt ln khác, hãy lưu tr
d liu vào mt tp ri cung cp nó gián tiếp thay vì lưu tr nó trc tiếp trong mt
bng. Nếu làm vy, bn cn báo cho người dùng trình cung cp ca bn rng h cn s dng mt phương pháp tp
{@link android.content.ContentResolver} để truy cp d liu.
</li>
<li>
S dng kiu d liu Binary Large OBject (BLOB) để lưu tr d liu có kích c khác nhau hoc có mt
cu trúc thay đổi. Ví dụ, bn có th s dng ct BLOB để lưu tr mt
<a href="http://code.google.com/p/protobuf">b đệm giao thc</a> hay
<a href="http://www.json.org">cu trúc JSON</a>.
<p>
Bn cũng có th s dng mt BLOB để trin khai mt bng <em>độc lp vi sơ đồ</em>. Trong
kiu bng này, bn định nghĩa mt ct khóa chính, mt ct kiu MIME, và mt hoc
nhiu ct chung là BLOB. Ý nghĩa ca d liu trong ct BLOB được th hin
bi giá tr trong ct kiu MIME. Điu này cho phép bn lưu tr các kiu hàng khác nhau trong
cùng bng. Bng "dữ liệu"
{@link android.provider.ContactsContract.Data} ca Trình cung cp Danh b là mt ví d v bng
độc lp vi sơ đồ.
</p>
</li>
</ul>
<!-- Designing Content URIs -->
<h2 id="ContentURI">Thiết kế URI Ni dung</h2>
<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 mang tính biu tượng ca toàn b trình cung cp (<strong>quyn</strong> ca nó) và mt
tên tr đến mt bng hoc tp (<strong>đường dn</strong>). Phn id tùy chn ch đến mt
hàng riêng l trong mt bng. Mi phương thc truy cp d liu
{@link android.content.ContentProvider} đều có mt URI ni dung là mt tham đối; điu này cho phép bn
xác định bng, hàng, hoc tp để truy cp.
</p>
<p>
Ni dung cơ bn ca URI ni dung được mô t trong ch đề
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Ni dung Cơ bn v Trình cung cp Ni dung</a>.
</p>
<h3>Thiết kế mt thm quyn</h3>
<p>
Mt trình cung cp thường có mt thm quyn duy nht, đóng vai trò là tên ni b Android ca nó. Để
tránh xung đột vi các trình cung cp khác, bn nên s dng quyn s hu min Internet (đảo ngược)
làm cơ s cho thm quyn ca trình cung cp ca mình. Vì đề xut này cũng đúng đối vi tên gói
Android, bn có th định nghĩa thm quyn trình cung cp ca mình là phn m rng ca tên
gói cha trình cung cp. Ví dụ, nếu tên gói Android là
<code>com.example.&lt;appname&gt;</code>, bn nên cp cho trình cung cp ca mình
thm quyn <code>com.example.&lt;appname&gt;.provider</code>.
</p>
<h3>Thiết kế mt cu trúc đường dn</h3>
<p>
Nhà phát trin thường to URI ni dung t thm quyn bng cách ni các đường dn tr đến
các bng riêng lẻ. Ví dụ, nếu bn có hai bng <em>table1</em> và
<em>table2</em>, bn kết hp thm quyn t ví d trước để to ra
các URI ni dung
<code>com.example.&lt;appname&gt;.provider/table1</code> và
<code>com.example.&lt;appname&gt;.provider/table2</code>. Các đường dn
không b gii hn mt phân đon duy nht, và không cn phi có mt bng cho tng cp ca đường dn.
</p>
<h3>X lý ID URI ni dung</h3>
<p>
Theo quy ước, các trình cung cp cho phép truy cp mt hàng đơn trong mt bng bng cách chp nhn mt URI ni dung
có mt giá tr ID cho hàng đó cui URI. Cũng theo quy ước, các trình cung cp s so khp
giá tr ID vi ct <code>_ID</code> ca bng, và thc hin truy cp yêu cu đối vi
hàng trùng khp.
</p>
<p>
Quy ước này to điu kin cho mt kiu mu thiết kế chung cho các ng dng truy cp mt trình cung cp. ng dng
tiến hành truy vn đối vi trình cung cp và hin th kết qu {@link android.database.Cursor}
trong mt {@link android.widget.ListView} bng cách s dng {@link android.widget.CursorAdapter}.
Định nghĩa {@link android.widget.CursorAdapter} yêu cu mt trong các ct trong
{@link android.database.Cursor} phi là <code>_ID</code>
</p>
<p>
Sau đó, người dùng chn mt trong các hàng được hin th t UI để xem hoc sa đổi
d liu. ng dng s nhn được hàng tương ng t {@link android.database.Cursor} làm nn cho
{@link android.widget.ListView}, nhn giá tr <code>_ID</code> cho hàng này, ni nó vi
URI ni dung, và gi yêu cu truy cp ti trình cung cp. Sau đó, trình cung cp có th thc hin
truy vn hoc sa đổi đối vi chính xác hàng mà người dùng đã chn.
</p>
<h3>Kiu mu URI ni dung</h3>
<p>
Để giúp bn chn hành động nào s thc hin cho URI ni dung đến, API ca trình cung cp s bao gm
lp thun tin {@link android.content.UriMatcher}, nó ánh x "kiểu mẫu" URI ni dung vi
các giá tr s nguyên. Bn có th s dng các giá tr s nguyên trong mt câu lnh <code>switch</code> mà chn
hành động mong mun cho URI ni dung hoc URI mà khp vi mt kiu mu c thể.
</p>
<p>
Kiu mu URI ni dung s so khp các URI ni dung bng cách s dng ký t đại din:
</p>
<ul>
<li>
<strong><code>*</code>:</strong> Khp mt xâu ký t hp l bt k vi chiu dài bt kỳ.
</li>
<li>
<strong><code>#</code>:</strong> Khớp một xâu ký tự số có chiều dài bất kỳ.
</li>
</ul>
<p>
Ly mt ví d v thiết kế và to mã x lý URI ni dung, hãy xét mt trình cung cp có
thm quyn <code>com.example.app.provider</code> mà nhn ra các URI ni dung
tr đến các bng sau:
</p>
<ul>
<li>
<code>content://com.example.app.provider/table1</code>: Một bảng gọi là <code>table1</code>.
</li>
<li>
<code>content://com.example.app.provider/table2/dataset1</code>: Một bảng gọi là
<code>dataset1</code>.
</li>
<li>
<code>content://com.example.app.provider/table2/dataset2</code>: Một bảng gọi là
<code>dataset2</code>.
</li>
<li>
<code>content://com.example.app.provider/table3</code>: Một bảng gọi là <code>table3</code>.
</li>
</ul>
<p>
Trình cung cp cũng nhn ra nhng URI ni dung này nếu chúng có mt ID hàng được ni kèm, như
ví d <code>content://com.example.app.provider/table3/1</code> đối với hàng được nhận biết bởi
<code>1</code> trong <code>table3</code>.
</p>
<p>
S có th có các kiu mu URI ni dung sau:
</p>
<dl>
<dt>
<code>content://com.example.app.provider/*</code>
</dt>
<dd>
Khp vi bt k URI ni dung nào trong trình cung cp.
</dd>
<dt>
<code>content://com.example.app.provider/table2/*</code>:
</dt>
<dd>
Khp vi mt URI ni dung cho các bng <code>dataset1</code>
và <code>dataset2</code>, nhưng không khớp với URI nội dung cho <code>table1</code> hoc
<code>table3</code>.
</dd>
<dt>
<code>content://com.example.app.provider/table3/#</code>: Khớp với một URI nội dung
cho các hàng đơn trong <code>table3</code>, chng hn như
<code>content://com.example.app.provider/table3/6</code> đối với hàng được xác định bởi
<code>6</code>.
</dt>
</dl>
<p>
Đon mã HTML sau cho biết cách hot động ca các phương pháp trong {@link android.content.UriMatcher}.
Đon mã này x lý các URI cho toàn b mt bng khác vi URI cho mt
hàng đơn, bng cách s dng mu hình URI ni dung
<code>content://&lt;authority&gt;/&lt;path&gt;</code> cho các bảng, và
<code>content://&lt;authority&gt;/&lt;path&gt;/&lt;id&gt;</code> cho các hàng đơn.
</p>
<p>
Phương pháp {@link android.content.UriMatcher#addURI(String, String, int) addURI()} ánh xạ một
thm quyn và đường dn ti mt giá tr s nguyên. Phương pháp {@link android.content.UriMatcher#match(Uri)
match()} tr v giá tr s nguyên cho mt URI. Câu lnh <code>switch</code> s chn
gia truy vn toàn b bng và truy vn cho mt bn ghi đơn:
</p>
<pre class="prettyprint">
public class ExampleProvider extends ContentProvider {
...
// Creates a UriMatcher object.
private static final UriMatcher sUriMatcher;
...
/*
* The calls to addURI() go here, for all of the content URI patterns that the provider
* should recognize. For this snippet, only the calls for table 3 are shown.
*/
...
/*
* Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used
* in the path
*/
sUriMatcher.addURI("com.example.app.provider", "table3", 1);
/*
* Sets the code for a single row to 2. In this case, the "#" wildcard is
* used. "content://com.example.app.provider/table3/3" matches, but
* "content://com.example.app.provider/table3 doesn't.
*/
sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
...
// Implements ContentProvider.query()
public Cursor query(
Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder) {
...
/*
* Choose the table to query and a sort order based on the code returned for the incoming
* URI. Here, too, only the statements for table 3 are shown.
*/
switch (sUriMatcher.match(uri)) {
// If the incoming URI was for all of table3
case 1:
if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
break;
// If the incoming URI was for a single row
case 2:
/*
* Because this URI was for a single row, the _ID value part is
* present. Get the last path segment from the URI; this is the _ID value.
* Then, append the value to the WHERE clause for the query
*/
selection = selection + "_ID = " uri.getLastPathSegment();
break;
default:
...
// If the URI is not recognized, you should do some error handling here.
}
// call the code to actually do the query
}
</pre>
<p>
Mt lp khác, {@link android.content.ContentUris}, s cung cp các phương pháp thun tin để làm vic
vi phn <code>id</code> ca URI ni dung. Các lp {@link android.net.Uri} và
{@link android.net.Uri.Builder} bao gm các phương pháp thun tin cho vic phân tích các đối tượng
{@link android.net.Uri} hin có và xây dng các đối tượng mi.
</p>
<!-- Implementing the ContentProvider class -->
<h2 id="ContentProvider">Trin khai Lp Trình cung cp Ni dung</h2>
<p>
Thc th {@link android.content.ContentProvider} qun lý truy cp vào
mt tp d liu cu trúc bng cách x lý yêu cu t các ng dng khác. Tt c các dng
truy cp cui cùng đều gi {@link android.content.ContentResolver}, sau đó nó gi ra mt phương pháp
c th ca {@link android.content.ContentProvider} để ly quyn truy cp.
</p>
<h3 id="RequiredAccess">Phương pháp được yêu cu</h3>
<p>
Lp tóm tt {@link android.content.ContentProvider} s định nghĩa sáu phương pháp tóm tt
mà bn phi trin khai như mt phn lp con c th ca mình. Tt c nhng phương pháp này ngoi tr
{@link android.content.ContentProvider#onCreate() onCreate()} đều được gọi ra bởi một ứng dụng máy khách
đang c truy cp trình cung cp ni dung ca bn:
</p>
<dl>
<dt>
{@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
query()}
</dt>
<dd>
Truy xut d liu t trình cung cp ca bn. S dng các tham đối để chn bng để
truy vn, các hàng và ct để tr về, và th t sp xếp ca kết quả.
Tr v d liu như mt đối tượng {@link android.database.Cursor}.
</dd>
<dt>
{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}
</dt>
<dd>
Chèn mt hàng mi vào trình cung cp ca bn. S dng các tham đối để la chn
bng đích và nhn các giá tr ct để s dng. Tr v mt URI ni dung cho
hàng mi chèn.
</dd>
<dt>
{@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
update()}
</dt>
<dd>
Cp nht các hàng hin ti trong trình cung cp ca bn. S dng các tham đối để la chn bng và hàng
để cp nht và nhn các giá tr ct được cp nhật. Tr v s hàng được cp nht.
</dd>
<dt>
{@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
</dt>
<dd>
Xóa hàng khi trình cung cp ca bn. S dng các tham đối để la chn bng và các hàng
cn xóa. Tr v s hàng được xóa.
</dd>
<dt>
{@link android.content.ContentProvider#getType(Uri) getType()}
</dt>
<dd>
Tr v kiu MIME tương ng vi mt URI ni dung. Phương pháp này được mô t chi tiết hơn
trong phn <a href="#MIMETypes">Trin khai Kiu MIME ca Trình cung cp Ni dung</a>.
</dd>
<dt>
{@link android.content.ContentProvider#onCreate() onCreate()}
</dt>
<dd>
Khi to trình cung cp ca bn. H thng Android s gi ra phương pháp này ngay lp tc sau khi nó
to trình cung cp ca bn. Để ý rng trình cung cp ca bn không được to cho đến khi đối tượng
{@link android.content.ContentResolver} c truy cp nó.
</dd>
</dl>
<p>
Để ý rng nhng phương pháp này có cùng ch ký như các phương pháp
{@link android.content.ContentResolver} được đặt tên như nhau.
</p>
<p>
Vic bn trin khai nhng phương pháp này nên xét ti các ni dung sau:
</p>
<ul>
<li>
Tt c phương pháp này ngoi tr {@link android.content.ContentProvider#onCreate() onCreate()}
đều có th được gi đồng thi bng nhiu lung, vì thế chúng phi an toàn đối vi lung. Để tìm hiu
thêm v nhiu lung, hãy xem ch đề
<a href="{@docRoot}guide/components/processes-and-threads.html">
Tiến trình và Lung</a>.
</li>
<li>
Tránh thc hin nhng thao tác dài trong {@link android.content.ContentProvider#onCreate()
onCreate()}. Hoãn các tác v khi to ti khi chúng thc s cn thiết.
Phn <a href="#OnCreate">Trin khai phương pháp onCreate()</a>
s bàn k hơn v vn đề này.
</li>
<li>
Mc dù bn phi trin khai nhng phương pháp này, mã ca bn không nht thiết phi làm gì ngoi tr vic
tr v kiu d liu k vng. Ví dụ, bn có th mun ngăn nhng ng dng khác
chèn d liu vào mt s bng. Để làm điu này, bn có th b qua lnh gi ti
{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} và trả về
0.
</li>
</ul>
<h3 id="Query">Trin khai phương pháp query()</h3>
<p>
Phương pháp
{@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
ContentProvider.query()} phi tr v mt đối tượng {@link android.database.Cursor}, nếu không nó s tht bi
, đưa ra mt li {@link java.lang.Exception}. Nếu bn đang s dng mt cơ s d liu SQLite làm kho lưu tr d liu ca mình
, bn có th ch cn tr v {@link android.database.Cursor} được tr v bi mt trong các phương pháp
<code>query()</code> ca lp {@link android.database.sqlite.SQLiteDatabase}.
Nếu truy vn không khp vi bt k hàng nào, bn nên tr v mt thc th {@link android.database.Cursor}
có phương pháp {@link android.database.Cursor#getCount()} trả về 0.
Bn ch nên tr v <code>null</code> nếu đã xy ra mt li ni b trong tiến trình truy vn.
</p>
<p>
Nếu bn không đang s dng mt cơ s d liu SQLite làm kho lưu tr d liu ca mình, hãy s dng mt trong các lp con c th
ca {@link android.database.Cursor}. Ví dụ, lp {@link android.database.MatrixCursor} s trin khai
mt con chy trong đó mi hàng là mt mng ca {@link java.lang.Object}. Vi lp này,
hãy s dng {@link android.database.MatrixCursor#addRow(Object[]) addRow()} để thêm một hàng mới.
</p>
<p>
Nh rng h thng Android phi có th giao tiếp vi {@link java.lang.Exception}
qua các ranh gii tiến trình. Android có th làm vy cho nhng trường hp ngoi l sau, điu này có th hu ích
trong x lý li truy vn:
</p>
<ul>
<li>
{@link java.lang.IllegalArgumentException} (Bn có th chn đưa ra li này nếu trình cung cp ca bn
nhn mt URI ni dung không hp lệ)
</li>
<li>
{@link java.lang.NullPointerException}
</li>
</ul>
<h3 id="Insert">Trin khai phương pháp insert()</h3>
<p>
Phương pháp {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} sẽ thêm một
hàng mi vào bng phù hp bng cách s dng các giá tr trong tham đối {@link android.content.ContentValues}
. Nếu tên ct không nm trong tham đối {@link android.content.ContentValues}, bn có th
mun cung cp mt giá tr mc định cho nó hoc trong mã trình cung cp ca bn hoc trong sơ đồ
cơ s d liu ca bn.
</p>
<p>
Phương pháp này s tr v URI ni dung cho hàng mi. Để xây dng điu này, hãy ni
giá tr <code>_ID</code> ca hàng mi (hay khóa chính khác) vi URI ni dung ca bng bng cách s dng
{@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()}.
</p>
<h3 id="Delete">Trin khai phương pháp delete()</h3>
<p>
Phương pháp {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
không cn phi xóa hàng thc cht khi kho lưu tr d liu ca bn. Nếu bn đang s dng mt trình điu hp đồng b
vi trình cung cp ca mình, bn nên cân nhc đánh du mt hàng đã xóa
bng c "xóa" thay vì g b hàng mt cách hoàn toàn. Trình điu hp đồng b có th
kim tra các hàng đã xóa và g b chúng khi máy ch trước khi xóa chúng khi trình cung cp.
</p>
<h3 id="Update">Trin khai phương pháp update()</h3>
<p>
Phương pháp {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
update()} ly cùng tham đối {@link android.content.ContentValues} được s dng bi
{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}, và
cùng tham đối <code>selection</code> và <code>selectionArgs</code> được s dng bi
{@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} và
{@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
ContentProvider.query()}. Điu này có th cho phép bn s dng li mã gia nhng phương pháp này.
</p>
<h3 id="OnCreate">Trin khai phương pháp onCreate()</h3>
<p>
H thng Android s gi {@link android.content.ContentProvider#onCreate()
onCreate()} khi nó khi động trình cung cp. Bn ch nên thc hin các tác v khi to chy nhanh
trong phương pháp này, và hoãn vic to cơ s d liu và np d liu ti khi trình cung cp thc s
nhn được yêu cu cho d liu. Nếu bn thc hin các tác v dài trong
{@link android.content.ContentProvider#onCreate() onCreate()}, bạn sẽ làm chậm lại
quá trình khi động ca trình cung cp. Đến lượt mình, điu này s làm chm hi đáp t trình cung cp đối vi các
ng dng khác.
</p>
<p>
Ví dụ, nếu bn đang s dng mt cơ s d liu SQLite, bn có th to
mt đối tượng {@link android.database.sqlite.SQLiteOpenHelper} mi trong
{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()},
ri to các bng SQL ln đầu tiên khi bn m cơ s d liu. Để to điu kin cho điu này,
ln đầu tiên bn gi {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase
getWritableDatabase()}, nó s t động gi ra phương pháp
{@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
SQLiteOpenHelper.onCreate()}.
</p>
<p>
Hai đon mã HTML sau minh ha tương tác gia
{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} và
{@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
SQLiteOpenHelper.onCreate()}. Đon mã HTML đầu tiên là trin khai
{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}:
</p>
<pre class="prettyprint">
public class ExampleProvider extends ContentProvider
/*
* Defines a handle to the database helper object. The MainDatabaseHelper class is defined
* in a following snippet.
*/
private MainDatabaseHelper mOpenHelper;
// Defines the database name
private static final String DBNAME = "mydb";
// Holds the database object
private SQLiteDatabase db;
public boolean onCreate() {
/*
* Creates a new helper object. This method always returns quickly.
* Notice that the database itself isn't created or opened
* until SQLiteOpenHelper.getWritableDatabase is called
*/
mOpenHelper = new MainDatabaseHelper(
getContext(), // the application context
DBNAME, // the name of the database)
null, // uses the default SQLite cursor
1 // the version number
);
return true;
}
...
// Implements the provider's insert method
public Cursor insert(Uri uri, ContentValues values) {
// Insert code here to determine which table to open, handle error-checking, and so forth
...
/*
* Gets a writeable database. This will trigger its creation if it doesn't already exist.
*
*/
db = mOpenHelper.getWritableDatabase();
}
}
</pre>
<p>
Đon mã HTML tiếp theo là trin khai
{@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
SQLiteOpenHelper.onCreate()}, bao gm mt lp trình tr giúp:
</p>
<pre class="prettyprint">
...
// A string that defines the SQL statement for creating a table
private static final String SQL_CREATE_MAIN = "CREATE TABLE " +
"main " + // Table's name
"(" + // The columns in the table
" _ID INTEGER PRIMARY KEY, " +
" WORD TEXT"
" FREQUENCY INTEGER " +
" LOCALE TEXT )";
...
/**
* Helper class that actually creates and manages the provider's underlying data repository.
*/
protected static final class MainDatabaseHelper extends SQLiteOpenHelper {
/*
* Instantiates an open helper for the provider's SQLite data repository
* Do not do database creation and upgrade here.
*/
MainDatabaseHelper(Context context) {
super(context, DBNAME, null, 1);
}
/*
* Creates the data repository. This is called when the provider attempts to open the
* repository and SQLite reports that it doesn't exist.
*/
public void onCreate(SQLiteDatabase db) {
// Creates the main table
db.execSQL(SQL_CREATE_MAIN);
}
}
</pre>
<!-- Implementing ContentProvider MIME Types -->
<h2 id="MIMETypes">Trin khai Kiu MIME ca Trình cung cp Ni dung</h2>
<p>
Lp {@link android.content.ContentProvider} có hai phương pháp để tr v các kiu MIME:
</p>
<dl>
<dt>
{@link android.content.ContentProvider#getType(Uri) getType()}
</dt>
<dd>
Mt trong các phương pháp được yêu cu mà bn phi trin khai cho bt k trình cung cp nào.
</dd>
<dt>
{@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
</dt>
<dd>
Mt phương pháp mà bn được d tính s trin khai nếu trình cung cp ca bn cung cp tp.
</dd>
</dl>
<h3 id="TableMIMETypes">Kiu MIME cho bng</h3>
<p>
Phương pháp {@link android.content.ContentProvider#getType(Uri) getType()} trả về một
{@link java.lang.String} theo định dng MIME mà mô t kiu d liu được tr v bi tham đối
URI ni dung. Tham đối {@link android.net.Uri} có th là mt mu hình thay vì mt URI c thể;
trong trường hp này, bn nên tr v kiu d liu được liên kết vi các URI ni dung mà khp vi
mu hình đó.
</p>
<p>
Đối vi các kiu d liu ph biến như văn bn, HTML, hay JPEG,
{@link android.content.ContentProvider#getType(Uri) getType()} sẽ trả về
kiu MIME tiêu chun cho d liu đó. Mt danh sách đầy đủ v nhng kiu tiêu chun này có sn trên trang web
<a href="http://www.iana.org/assignments/media-types/index.htm">IANA MIME Media Types</a>
.
</p>
<p>
Đối vi các URI ni dung mà tr ti mt hàng hoc các hàng ca bng d liu,
{@link android.content.ContentProvider#getType(Uri) getType()} sẽ trả về
mt kiu MIME theo định dng MIME riêng cho nhà cung cp ca Android:
</p>
<ul>
<li>
B phn kiu: <code>vnd</code>
</li>
<li>
B phn kiu con:
<ul>
<li>
Nếu mu hình URI áp dng cho mt hàng đơn: <code>android.cursor.<strong>item</strong>/</code>
</li>
<li>
Nếu mu hình URI áp dng cho nhiu hơn mt hàng: <code>android.cursor.<strong>dir</strong>/</code>
</li>
</ul>
</li>
<li>
B phn riêng theo trình cung cp: <code>vnd.&lt;name&gt;</code>.<code>&lt;type&gt;</code>
<p>
Bn cung cp <code>&lt;name&gt;</code> và <code>&lt;type&gt;</code>.
Giá tr <code>&lt;name&gt;</code> nên là giá tr duy nht toàn cc,
và giá tr <code>&lt;type&gt;</code> nên là giá tr duy nht đối vi mu hình
URI tương ng. Mt la chn hay cho <code>&lt;name&gt;</code> đó là tên công ty ca bn hoc
mt thành phn nào đó trong tên gói Android cho ng dng ca bn. Mt la chn hay cho
<code>&lt;type&gt;</code> đó là mt xâu xác định bng được liên kết vi
URI.
</p>
</li>
</ul>
<p>
Ví dụ, nếu thm quyn ca mt trình cung cp là
<code>com.example.app.provider</code>, và nó làm hin ra mt bng có tên
<code>table1</code> thì kiểu MIME cho nhiều hàng trong <code>table1</code> là:
</p>
<pre>
vnd.android.cursor.<strong>dir</strong>/vnd.com.example.provider.table1
</pre>
<p>
Đối vi mt hàng đơn ca <code>table1</code>, kiu MIME là:
</p>
<pre>
vnd.android.cursor.<strong>item</strong>/vnd.com.example.provider.table1
</pre>
<h3 id="FileMIMETypes">Kiu MIME cho tp</h3>
<p>
Nếu trình cung cp ca bn cung cp tp, hãy trin khai
{@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}.
Phương pháp này s tr v mt mng {@link java.lang.String} ca kiu MIME đối vi các tp mà trình cung cp ca bn
có th tr v cho mt URI ni dung cho trước. Bn nên lc các kiu MIME mà mình cung cp bng tham đối b lc
kiu MIME, sao cho bn ch tr v nhng kiu MIME mà máy khách mun x lý.
</p>
<p>
Ví dụ, xét mt trình cung cp hình nh dưới dng tp có định dng <code>.jpg</code>,
<code>.png</code> và <code>.gif</code>.
Nếu mt ng dng gi {@link android.content.ContentResolver#getStreamTypes(Uri, String)
ContentResolver.getStreamTypes()} bng xâu b lc <code>image/*</code> (
mà là một "hình ảnh"),
khi đó phương pháp {@link android.content.ContentProvider#getStreamTypes(Uri, String)
ContentProvider.getStreamTypes()} sẽ trả về mảng:
</p>
<pre>
{ &quot;image/jpeg&quot;, &quot;image/png&quot;, &quot;image/gif&quot;}
</pre>
<p>
Nếu ứng dụng chỉ quan tâm đến các tệp <code>.jpg</code>, vậy nó có thể gọi
{@link android.content.ContentResolver#getStreamTypes(Uri, String)
ContentResolver.getStreamTypes()} bằng xâu bộ lọc <code>*\/jpeg</code>, và
{@link android.content.ContentProvider#getStreamTypes(Uri, String)
ContentProvider.getStreamTypes()} sẽ trả về:
<pre>
{&quot;image/jpeg&quot;}
</pre>
<p>
Nếu trình cung cấp của bạn không cung cấp bất kỳ kiểu MIME nào được yêu cầu trong xâu bộ lọc,
{@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
sẽ trả về <code>null</code>.
</p>
<!-- Implementing a Contract Class -->
<h2 id="ContractClass">Triển khai một Lớp Hợp đồng</h2>
<p>
Lớp hợp đồng là một lớp <code>public final</code> chứa các định nghĩa hằng số cho
URI, tên cột, kiểu MIME, và siêu dữ liệu khác liên quan tới trình cung cấp. Lớp này
sẽ thiết lập một hợp đồng giữa trình cung cấp và các ứng dụng khác bằng cách đảm bảo rằng trình cung cấp
có thể được truy cập đúng ngay cả khi có thay đổi về giá trị thực sự của URI, tên cột,
v.v.
</p>
<p>
Lớp hợp đồng cũng giúp các nhà phát triển vì chúng thường có tên dễ nhớ cho các hằng số của mình,
vì vậy các nhà phát triển ít có khả năng sử dụng các giá trị không đúng cho tên cột hay URI hơn. Do đó là một
lớp, nó có thể chứa tài liệu Javadoc. Các môi trường phát triển tích hợp như
Eclipse có thể tự động điền các tên hằng số từ lớp hợp đồng và hiển thị Javadoc cho các
hằng số đó.
</p>
<p>
Các nhà phát triển không thể truy cập tệp lớp của lớp hợp đồng từ ứng dụng của mình, nhưng họ có thể
lặng lẽ biên dịch nó vào ứng dụng của họ từ một tệp <code>.jar</code> mà bạn cung cấp.
</p>
<p>
Lớp {@link android.provider.ContactsContract} và các lớp lồng nhau của nó là các ví dụ về
lớp hợp đồng.
</p>
<h2 id="Permissions">Triển khai Quyền của Trình cung cấp Nội dung</h2>
<p>
Quyền và truy cập đối với tất cả khía cạnh trong hệ thống Android được mô tả chi tiết trong
chủ đề <a href="{@docRoot}guide/topics/security/security.html">Bảo mật và Quyền</a>.
Chủ đề <a href="{@docRoot}guide/topics/data/data-storage.html">Kho lưu trữ Dữ liệu</a> cũng
mô tả bảo mật và các quyền có hiệu lực cho nhiều loại kho lưu trữ khác nhau.
Nói tóm lại, các điểm quan trọng là:
</p>
<ul>
<li>
Theo mặc định, các tệp dữ liệu được lưu trữ trên bộ nhớ trong của thiết bị là dữ liệu riêng tư
đối với ứng dụng và trình cung cấp của bạn.
</li>
<li>
Các cơ sở dữ liệu {@link android.database.sqlite.SQLiteDatabase} mà bạn tạo là dữ liệu riêng tư
đối với ứng dụng và trình cung cấp của bạn.
</li>
<li>
Theo mặc định, các tệp dữ liệu mà bạn lưu vào bộ nhớ ngoài là dữ liệu <em>công khai</em> và
<em>đọc được công khai</em>. Bạn không thể sử dụng một trình cung cấp nội dung để hạn chế truy cập vào các tệp trong
bộ nhớ ngoài vì các ứng dụng khác có thể sử dụng lệnh gọi API khác để đọc và ghi chúng.
</li>
<li>
Các lệnh gọi phương pháp để mở hoặc tạo tệp hoặc cơ sở dữ liệu SQLite trên bộ nhớ trong
của thiết bị của bạn có thể cấp quyền truy cập đọc và ghi cho tất cả ứng dụng khác. Nếu bạn
sử dụng một tệp hoặc cơ sở dữ liệu nội bộ làm kho lưu giữ của trình cung cấp của mình, và bạn cấp quyền truy cập
"đọc được công khai" hoặc "ghi được công khai", quyền mà bạn đặt cho trình cung cấp của mình trong
bản kê khai của nó sẽ không bảo vệ dữ liệu của bạn. Quyền truy cập mặc định cho các tệp và cơ sở dữ liệu trong
bộ nhớ trong là "riêng tư", và đối với kho lưu giữ của trình cung cấp của mình, bạn không nên thay đổi điều này.
</li>
</ul>
<p>
Nếu bạn muốn sử dụng các quyền của trình cung cấp nội dung để kiểm soát truy cập vào dữ liệu của mình, khi đó bạn nên
lưu trữ dữ liệu của mình trong các tệp nội bộ, cơ sở dữ liệu SQLite, hoặc "đám mây" (ví dụ,
trên một máy chủ từ xa), và bạn nên giữ các tệp và cơ sở dữ liệu riêng tư cho ứng dụng của mình.
</p>
<h3>Triển khai quyền</h3>
<p>
Tất cả ứng dụng đều có thể đọc từ hoặc ghi vào trình cung cấp của bạn, ngay cả khi dữ liệu liên quan
là dữ liệu riêng tư, vì theo mặc định, trình cung cấp của bạn không được đặt quyền. Để thay đổi điều này,
hãy đặt quyền cho trình cung cấp của bạn trong tệp bản kê khai của bạn bằng cách sử dụng các thuộc tính hoặc phần tử
con của phần tử <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>. Bạn có thể đặt quyền áp dụng cho toàn bộ trình cung cấp,
hoặc cho một số bảng, hoặc thậm chí cho một số bản ghi, hoặc cả ba.
</p>
<p>
Bạn định nghĩa các quyền cho trình cung cấp của bạn bằng một hoặc nhiều phần tử
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">
&lt;permission&gt;</a></code> trong tệp bản kê khai của bạn. Để
quyền là duy nhất cho trình cung cấp của bạn, hãy sử dụng phạm vi kiểu Java cho thuộc tính
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#nm">
android:name</a></code>. Ví dụ, đặt tên quyền đọc
<code>com.example.app.provider.permission.READ_PROVIDER</code>.
</p>
<p>
Danh sách sau liệt kê phạm vi các quyền của trình cung cấp, bắt đầu với các quyền
áp dụng cho toàn bộ trình cung cấp rồi mới đến các quyền chi tiết hơn.
Các quyền chi tiết hơn được ưu tiên so với các quyền có phạm vi rộng hơn:
</p>
<dl>
<dt>
Quyền đọc-ghi đơn lẻ ở cấp trình cung cấp
</dt>
<dd>
Một quyền kiểm soát cả quyền truy cập đọc và ghi cho toàn bộ trình cung cấp, được quy định
bằng thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
android:permission</a></code> của phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>.
</dd>
<dt>
Quyền đọc ghi tách riêng ở cấp độ trình cung cấp
</dt>
<dd>
Một quyền đọc và một quyền ghi cho toàn bộ trình cung cấp. Bạn chỉ định chúng
bằng các thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
android:readPermission</a></code> và
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
android:writePermission</a></code> của phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>. Chúng được ưu tiên so với quyền được yêu cầu bởi
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
android:permission</a></code>.
</dd>
<dt>
Quyền ở cấp đường dẫn
</dt>
<dd>
Quyền đọc, ghi, hoặc đọc/ghi cho một URI nội dung trong trình cung cấp của bạn. Bạn chỉ định
từng URI mà bạn muốn kiểm soát bằng một phần tử con
<code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html">
&lt;path-permission&gt;</a></code> của phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>. Với mỗi một URI nội dung mà bạn chỉ định, bạn có thể chỉ định một
quyền đọc/ghi, quyền đọc, hoặc quyền ghi, hoặc cả ba. Quyền đọc và
quyền ghi được ưu tiên so với quyền đọc/ghi. Đồng thời, quyền ở cấp độ đường dẫn
sẽ được ưu tiên so với quyền ở cấp độ trình cung cấp.
</dd>
<dt>
Quyền tạm thời
</dt>
<dd>
Là cấp độ quyền cho phép truy cập tạm thời vào một ứng dụng, ngay cả khi ứng dụng
không có các quyền thường được yêu cầu. Tính năng truy cập
tạm thời làm giảm số quyền mà một ứng dụng phải yêu cầu trong
bản kê khai của mình. Khi bạn dùng đến các quyền tạm thời, những ứng dụng duy nhất mà cần
quyền "lâu dài" cho trình cung cấp của bạn là những ứng dụng liên tục truy cập tất cả
dữ liệu của bạn.
<p>
Xét các quyền bạn cần để triển khai một trình cung cấp và ứng dụng e-mail khi bạn
muốn cho phép một ứng dụng trình xem ảnh bên ngoài hiển thị các tài liệu đính kèm dạng ảnh từ trình cung cấp
của bạn. Để cấp cho trình xem ảnh quyền truy cập cần thiết mà không cần yêu cầu quyền,
hãy thiết lập các quyền tạm thời cho URI nội dung đối với ảnh. Thiết kế ứng dụng e-mail của bạn sao cho
khi người dùng muốn hiển thị một ảnh, ứng dụng sẽ gửi một ý định chứa URI nội dung
của ảnh và cờ cho phép tới trình xem ảnh. Trình xem ảnh khi đó có thể
truy vấn trình cung cấp e-mail của bạn để truy xuất ảnh, ngay cả khi trình xem không
có quyền đọc bình thường cho trình cung cấp của bạn.
</p>
<p>
Để sử dụng các quyền tạm thời, hoặc đặt thuộc tính
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
android:grantUriPermissions</a></code> của phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code> hoặc thêm một hoặc nhiều phần tử con
<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
&lt;grant-uri-permission&gt;</a></code> vào phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code> của bạn. Nếu bạn sử dụng các quyền tạm thời, bạn phải gọi
{@link android.content.Context#revokeUriPermission(Uri, int)
Context.revokeUriPermission()} bất cứ khi nào bạn gỡ bỏ hỗ trợ cho một URI nội dung khỏi
trình cung cấp của mình, và URI nội dung đó sẽ được liên kết với một quyền tạm thời.
</p>
<p>
Giá trị của thuộc tính sẽ xác định trình cung cấp của bạn được cho phép truy cập bao nhiêu.
Nếu thuộc tính được đặt thành <code>true</code>, khi đó hệ thống sẽ cấp quyền tạm thời
cho toàn bộ trình cung cấp của bạn, khống chế mọi quyền khác mà được yêu cầu bởi
quyền ở cấp độ trình cung cấp hoặc cấp độ đường dẫn của bạn.
</p>
<p>
Nếu cờ này được đặt thành <code>false</code>, khi đó bạn phải thêm các phần tử con
<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
&lt;grant-uri-permission&gt;</a></code> vào phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code> của mình. Mỗi phần tử con lại quy định URI nội dung hoặc
các URI mà truy cập tạm thời được cấp cho.
</p>
<p>
Để ủy quyền truy cập tạm thời cho một ứng dụng, ý định phải chứa
cờ {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} hoặc cờ
{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, hoặc cả hai. Những quyền
này được đặt bằng phương pháp {@link android.content.Intent#setFlags(int) setFlags()}.
</p>
<p>
Nếu thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
android:grantUriPermissions</a></code> không có mặt, giả sử rằng nó là
<code>false</code>.
</p>
</dd>
</dl>
<!-- The Provider Element -->
<h2 id="ProviderElement">Phần tử &lt;provider&gt;</h2>
<p>
Như các thành phần {@link android.app.Activity} và {@link android.app.Service},
một lớp con của {@link android.content.ContentProvider}
phải được định nghĩa trong tệp bản kê khai cho ứng dụng của nó bằng cách sử dụng phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>. Hệ thống Android nhận thông tin sau từ
phần tử:
<dl>
<dt>
Thẩm quyền
(<a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">{@code
android:authorities}</a>)
</dt>
<dd>
Các tên biểu tượng nhận biết toàn bộ trình cung cấp trong hệ thống. Thuộc tính
này được mô tả chi tiết hơn trong phần
<a href="#ContentURI">Thiết kế URI Nội dung</a>.
</dd>
<dt>
Tên lớp của trình cung cấp
(<code>
<a href="{@docRoot}guide/topics/manifest/provider-element.html#nm">android:name</a>
</code>)
</dt>
<dd>
Lớp triển khai {@link android.content.ContentProvider}. Lớp này
được mô tả chi tiết hơn trong phần
<a href="#ContentProvider">Triển khai Lớp Trình cung cấp Nội dung</a>.
</dd>
<dt>
Quyền
</dt>
<dd>
Những thuộc tính quy định quyền mà các ứng dụng khác phải có để truy cập
dữ liệu của trình cung cấp:
<ul>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
android:grantUriPermssions</a></code>: Cờ quyền tạm thời.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
android:permission</a></code>: Quyền đọc/ghi đơn lẻ đối với toàn bộ trình cung cấp.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
android:readPermission</a></code>: Quyền đọc đối với toàn bộ trình cung cấp.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
android:writePermission</a></code>: Quyền ghi đối với toàn bộ trình cung cấp.
</li>
</ul>
<p>
Các quyền và thuộc tính tương ứng của chúng được mô tả chi tiết hơn trong
phần
<a href="#Permissions">Triển khai Quyền của Trình cung cấp Nội dung</a>.
</p>
</dd>
<dt>
Thuộc tính khởi động và kiểm soát
</dt>
<dd>
Những thuộc tính này xác định cách và thời điểm hệ thống Android khởi động trình cung cấp, các
đặc tính tiến trình của trình cung cấp, và các thiết đặt về thời gian chạy:
<ul>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#enabled">
android:enabled</a></code>: Cờ cho phép hệ thống khởi động trình cung cấp.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
android:exported</a></code>: Cờ cho phép các ứng dụng sử dụng trình cung cấp này.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#init">
android:initOrder</a></code>: Thứ tự mà trình cung cấp nên được khởi động,
so với các trình cung cấp khác trong cùng tiến trình.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#multi">
android:multiProcess</a></code>: Cờ cho phép hệ thống khởi động trình cung cấp
trong cùng tiến trình như máy khách gọi.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#proc">
android:process</a></code>: Tên của tiến trình mà trình cung cấp
nên chạy trong đó.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#sync">
android:syncable</a></code>: Cờ cho biết rằng dữ liệu của trình cung cấp sẽ được
đồng bộ với dữ liệu trên một máy chủ.
</li>
</ul>
<p>
Các thuộc tính được lập tài liệu theo dõi đầy đủ trong chủ đề hướng dẫn nhà phát triển đối với phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>
.
</p>
</dd>
<dt>
Các thuộc tính thông tin
</dt>
<dd>
Một biểu tượng tùy chọn và nhãn cho trình cung cấp:
<ul>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#icon">
android:icon</a></code>: Một tài nguyên có thể vẽ chứa một biểu tượng cho trình cung cấp.
Biểu tượng xuất hiện bên cạnh nhãn của trình cung cấp trong danh sách ứng dụng trong
<em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
</li>
<li>
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#label">
android:label</a></code>: Một nhãn thông tin mô tả trình cung cấp hoặc dữ liệu
của nó, hoặc cả hai. Nhãn xuất hiện trong danh sách ứng dụng trong
<em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
</li>
</ul>
<p>
Các thuộc tính được lập tài liệu theo dõi đầy đủ trong chủ đề hướng dẫn nhà phát triển đối với phần tử
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
&lt;provider&gt;</a></code>.
</p>
</dd>
</dl>
<!-- Intent Access -->
<h2 id="Intents">Ý định và Truy cập Dữ liệu</h2>
<p>
Các ứng dụng có thể gián tiếp truy cập một trình cung cấp nội dung bằng một {@link android.content.Intent}.
Ứng dụng không gọi bất kỳ phương pháp nào của {@link android.content.ContentResolver} hoặc
{@link android.content.ContentProvider}. Thay vào đó, nó sẽ gửi một ý định để bắt đầu một hoạt động,
đây thường là một bộ phận trong ứng dụng của chính trình cung cấp. Hoạt động đích phụ trách
truy xuất và hiển thị dữ liệu trong UI của nó. Tùy vào hành động trong ý định, hoạt động
đích cũng có thể nhắc người dùng thực hiện sửa đổi dữ liệu của trình cung cấp.
Một ý định cũng có thể chứa dữ liệu "phụ thêm" mà hoạt động đích hiển thị
trong UI; khi đó người dùng có tùy chọn thay đổi dữ liệu này trước khi sử dụng nó để sửa đổi
dữ liệu trong trình cung cấp.
</p>
<p>
</p>
<p>
Bạn có thể muốn sử dụng truy cập ý định để giúp đảm bảo toàn vẹn dữ liệu. Trình cung cấp của bạn có thể phụ thuộc vào
việc chèn, cập nhật và xóa dữ liệu theo lô-gic nghiệp vụ được quy định chặt chẽ. Trong
trường hợp như vậy, việc cho phép các ứng dụng khác trực tiếp sửa đổi dữ liệu của bạn có thể dẫn đến dữ liệu
không hợp lệ. Nếu bạn muốn các nhà phát triển sử dụng truy cập ý định, hãy đảm bảo lập tài liệu theo dõi nó thật kỹ.
Giải thích với họ tại sao truy cập ý định sử dụng UI ứng dụng của chính bạn lại tốt hơn là cố gắng sửa đổi
dữ liệu bằng mã của họ.
</p>
<p>
Việc xử lý một ý định đến nhằm sửa đổi dữ liệu của trình cung cấp của bạn không khác với
việc xử lý các ý định khác. Bạn có thể tìm hiểu về việc sử dụng ý định bằng cách đọc chủ đề
<a href="{@docRoot}guide/components/intents-filters.html">Ý định và Bộ lọc Ý định</a>.
</p>