• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Tạo một Trình cung cấp Nội dung
2@jd:body
3<div id="qv-wrapper">
4<div id="qv">
5
6
7<h2>Trong tài liệu này</h2>
8<ol>
9    <li>
10        <a href="#DataStorage">Thiết kế Kho lưu trữ Dữ liệu</a>
11    </li>
12    <li>
13        <a href="#ContentURI">Thiết kế URI Nội dung</a>
14    </li>
15    <li>
16        <a href="#ContentProvider">Triển khai Lớp Trình cung cấp Nội dung</a>
17        <ol>
18            <li>
19                <a href="#RequiredAccess">Phương pháp được Yêu cầu</a>
20            </li>
21            <li>
22                <a href="#Query">Triển khai phương pháp query()</a>
23            </li>
24            <li>
25                <a href="#Insert">Triển khai phương pháp insert()</a>
26            </li>
27            <li>
28                <a href="#Delete">Triển khai phương pháp delete()</a>
29            </li>
30            <li>
31                <a href="#Update">Triển khai phương pháp update()</a>
32            </li>
33            <li>
34                <a href="#OnCreate">Triển khai phương pháp onCreate()</a>
35            </li>
36        </ol>
37    </li>
38    <li>
39        <a href="#MIMETypes">Triển khai Kiểu MIME của Trình cung cấp Nội dung</a>
40        <ol>
41            <li>
42                <a href="#TableMIMETypes">Kiểu MIME cho bảng</a>
43            </li>
44            <li>
45                <a href="#FileMIMETypes">Kiểu MIME cho tệp</a>
46            </li>
47        </ol>
48    </li>
49    <li>
50        <a href="#ContractClass">Triển khai một Lớp Hợp đồng</a>
51    </li>
52    <li>
53        <a href="#Permissions">Triển khai Quyền của Trình cung cấp Nội dung</a>
54    </li>
55    <li>
56        <a href="#ProviderElement">Phần tử &lt;provider&gt;</a>
57    </li>
58    <li>
59        <a href="#Intents">Ý định và Truy cập Dữ liệu</a>
60    </li>
61</ol>
62<h2>Lớp khóa</h2>
63    <ol>
64        <li>
65            {@link android.content.ContentProvider}
66        </li>
67        <li>
68            {@link android.database.Cursor}
69        </li>
70        <li>
71            {@link android.net.Uri}
72        </li>
73    </ol>
74<h2>Các Mẫu Liên quan</h2>
75    <ol>
76        <li>
77            <a href="{@docRoot}resources/samples/NotePad/index.html">
78                Ứng dụng mẫu Note Pad
79            </a>
80        </li>
81    </ol>
82<h2>Xem thêm</h2>
83    <ol>
84        <li>
85            <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
86            Nội dung Cơ bản về Trình cung cấp Nội dung</a>
87        </li>
88        <li>
89            <a href="{@docRoot}guide/topics/providers/calendar-provider.html">
90            Trình cung cấp Lịch</a>
91        </li>
92    </ol>
93</div>
94</div>
95
96
97<p>
98    Trình cung cấp nội dung quản lý truy cập vào một kho dữ liệu tập trung. Bạn triển khai một
99    trình cung cấp thành một hoặc nhiều lớp trong một ứng dụng Android, bên cạnh các phần tử trong
100    tệp bản kê khai. Một trong các lớp của bạn triển khai một lớp con
101    {@link android.content.ContentProvider}, đây là giao diện giữa trình cung cấp của bạn và
102    các ứng dụng khác. Mặc dù mục đích của các trình cung cấp nội dung khác là cung cấp dữ liệu có sẵn cho các
103    ứng dụng khác, dĩ nhiên bạn có thể ra lệnh cho các hoạt động trong ứng dụng của mình
104    truy vấn và sửa đổi dữ liệu được quản lý bởi trình cung cấp của bạn.
105</p>
106<p>
107    Phần còn lại của chủ đề này là một danh sách cơ bản về các bước để xây dựng một trình cung cấp nội dung và một danh sách
108    các API để sử dụng.
109</p>
110
111
112<!-- Before You Start Building -->
113<h2 id="BeforeYouStart">Trước khi Bạn Bắt đầu Xây dựng</h2>
114<p>
115    Trước khi bạn bắt đầu xây dựng một trình cung cấp, hãy làm việc sau:
116</p>
117<ol>
118    <li>
119        <strong>Quyết định xem bạn có cần một trình cung cấp nội dung không</strong>. Bạn cần xây dựng một trình cung cấp
120        nội dung nếu muốn cung cấp một hoặc nhiều tính năng sau đây:
121        <ul>
122            <li>Bạn muốn cung cấp dữ liệu hoặc tệp phức tạp cho các ứng dụng khác.</li>
123            <li>Bạn muốn cho phép người dùng sao chép dữ liệu phức tạp từ ứng dụng của bạn vào các ứng dụng khác.</li>
124            <li>Bạn muốn cung cấp các gợi ý tìm kiếm tùy chỉnh bằng cách sử dụng khuôn khổ tìm kiếm.</li>
125        </ul>
126    <p>
127        Bạn <em>không</em> cần trình cung cấp phải sử dụng một cơ sở dữ liệu SQLite nếu việc sử dụng hoàn toàn
128        diễn ra trong ứng dụng của bạn.
129    </p>
130    </li>
131    <li>
132        Nếu bạn chưa làm như vậy, hãy đọc chủ đề
133        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
134        Nội dung Cơ bản về Trình cung cấp Nội dung</a> để tìm hiểu thêm về trình cung cấp.
135    </li>
136</ol>
137<p>
138    Tiếp theo, hãy làm theo những bước sau để xây dựng trình cung cấp của bạn:
139</p>
140<ol>
141    <li>
142        Thiết kế kho lưu trữ thô cho dữ liệu của bạn. Một trình cung cấp nội dung sẽ cung cấp dữ liệu theo hai cách:
143        <dl>
144            <dt>
145                Dữ liệu tệp
146            </dt>
147            <dd>
148                Dữ liệu mà thường đến các tệp chẳng hạn như
149                ảnh, âm thanh, hoặc video. Lưu trữ các tệp ở không gian
150                riêng tư trong ứng dụng của bạn. Để hồi đáp lại một yêu cầu tệp từ một ứng dụng khác, trình cung cấp
151                của bạn có thể cung cấp một núm điều tác cho tệp.
152            </dd>
153            <dt>
154                Dữ liệu "cấu trúc"
155            </dt>
156            <dd>
157                Dữ liệu mà thường đến một cơ sở dữ liệu, mảng, hoặc cấu trúc tương tự.
158                Lưu trữ dữ liệu dưới dạng tương thích với các bảng hàng cột. Hàng
159                biểu diễn một đối tượng, chẳng hạn như một người hoặc khoản mục trong kiểm kê. Cột biểu diễn
160                một số dữ liệu cho đối tượng, chẳng hạn như tên của một người hoặc giá của một khoản mục. Một cách thường dùng để
161                lưu trữ loại dữ liệu này đó là trong cơ sở dữ liệu SQLite, nhưng bạn có thể sử dụng bất kỳ loại
162                kho lưu trữ lâu dài nào. Để tìm hiểu thêm về các loại kho lưu trữ có sẵn trong
163                hệ thống Android, hãy xem phần <a href="#DataStorage">
164                Thiết kế Kho lưu trữ Dữ liệu</a>.
165            </dd>
166        </dl>
167    </li>
168    <li>
169        Định nghĩa một triển khai cụ thể của lớp {@link android.content.ContentProvider} và
170        các phương pháp được yêu cầu của nó. Lớp này là giao diện giữa dữ liệu của bạn và phần còn lại của
171        hệ thống Android. Để biết thêm thông tin về lớp này, hãy xem phần
172        <a href="#ContentProvider">Triển khai Lớp ContentProvider</a>.
173    </li>
174    <li>
175        Định nghĩa xâu thẩm quyền của trình cung cấp, URI nội dung của nó, và các tên cột. Nếu bạn muốn
176        ứng dụng của trình cung cấp xử lý các ý định, hãy định nghĩa các hành động ý định, dữ liệu phụ thêm,
177        và cờ. Đồng thời, hãy định nghĩa các quyền mà bạn sẽ yêu cầu cho những ứng dụng muốn
178        truy cập dữ liệu của bạn. Bạn nên cân nhắc định nghĩa tất cả những giá trị này là hằng số trong một
179        lớp riêng; sau đó, bạn có thể cho hiện lớp này ra với các nhà phát triển khác. Để biết thêm
180        thông tin về URI nội dung, hãy xem
181        phần <a href="#ContentURI">Thiết kế URI Nội dung</a>.
182        Để biết thêm thông tin về ý định, hãy xem
183        phần <a href="#Intents">Ý định và Truy cập Dữ liệu</a>.
184    </li>
185    <li>
186        Thêm các nội dung tùy chọn khác, chẳng hạn như dữ liệu mẫu hoặc triển
187        khai {@link android.content.AbstractThreadedSyncAdapter} mà có thể đồng bộ hoá dữ liệu giữa
188        trình cung cấp và dữ liệu nền đám mây.
189    </li>
190</ol>
191
192
193<!-- Designing Data Storage -->
194<h2 id="DataStorage">Thiết kế Kho lưu trữ Dữ liệu</h2>
195<p>
196    Trình cung cấp nội dung là giao diện đối với dữ liệu được lưu theo một định dạng cấu trúc. Trước khi tạo
197    giao diện, bạn phải quyết định cách lưu trữ dữ liệu. Bạn có thể lưu trữ dữ liệu theo bất kỳ dạng nào
198    mà bạn muốn rồi thiết kế giao diện để đọc và ghi dữ liệu nếu cần thiết.
199</p>
200<p>
201    Có một số công nghệ lưu trữ dữ liệu có sẵn trong Android:
202</p>
203<ul>
204    <li>
205        Hệ thống Android bao gồm một API cơ sở dữ liệu SQLite mà các trình cung cấp của chính Androi sử dụng
206        để lưu trữ dữ liệu theo định hướng bảng. Lớp
207        {@link android.database.sqlite.SQLiteOpenHelper} giúp bạn tạo cơ sở dữ liệu, và lớp
208        {@link android.database.sqlite.SQLiteDatabase} là lớp cơ bản để đánh giá
209        các cơ sở dữ liệu.
210        <p>
211            Nhớ rằng bạn không phải sử dụng một cơ sở dữ liệu để triển khai kho lưu giữ của mình. Bề ngoài, một trình cung cấp
212            có dạng như là một tập hợp bảng, tương tự như một cơ sở dữ liệu quan hệ, nhưng đây
213            không phải là một yêu cầu đối với việc triển khai nội bộ của trình cung cấp.
214        </p>
215    </li>
216    <li>
217        Để lưu trữ dữ liệu tệp, Android có nhiều API định hướng tệp khác nhau.
218        Để tìm hiểu thêm về lưu trữ tệp, hãy đọc chủ đề
219        <a href="{@docRoot}guide/topics/data/data-storage.html">Kho lưu trữ Dữ liệu</a>. Nếu bạn
220        đang thiết kế một trình cung cấp dữ liệu liên quan tới phương tiện chẳng hạn như nhạc hay video, bạn có thể
221        có một trình cung cấp cho phép kết hợp dữ liệu bảng và các tệp.
222    </li>
223    <li>
224        Để làm việc với dữ liệu trên nền mạng, hãy sử dụng các lớp trong {@link java.net} và
225        {@link android.net}. Bạn cũng có thể đồng bộ hoá dữ liệu trên nền mạng với một kho lưu trữ dữ liệu cục bộ
226        chẳng hạn như một cơ sở dữ liệu, rồi cung cấp dữ liệu dưới dạng bảng hoặc tệp.
227        Ứng dụng mẫu <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
228        Trình điều hợp Đồng bộ Mẫu</a> minh họa loại đồng bộ hoá này.
229    </li>
230</ul>
231<h3 id="DataDesign">
232    Những nội dung cần xem xét khi thiết kế dữ liệu
233</h3>
234<p>
235    Sau đây là một số mẹo để thiết kế cấu trúc dữ liệu cho trình cung cấp của bạn:
236</p>
237<ul>
238    <li>
239        Dữ liệu bảng nên luôn có một cột "khóa chính" mà trình cung cấp duy trì
240        như một giá trị số duy nhất cho mỗi hàng. Bạn có thể sử dụng giá trị này để liên kết hàng với các hàng
241        có liên quan trong các bảng khác (sử dụng nó làm "khóa ngoại"). Mặc dù bạn có thể sử dụng bất kỳ tên gọi nào
242       cho cột này, sử dụng {@link android.provider.BaseColumns#_ID BaseColumns._ID} là lựa chọn tốt nhất
243        vì việc liên kết các kết quả của một truy vấn trình cung cấp với
244        {@link android.widget.ListView} đòi hỏi một trong các cột được truy xuất phải có tên
245        <code>_ID</code>.
246    </li>
247    <li>
248        Nếu bạn muốn cung cấp các hình ảnh bitmap hoặc nội dung dữ liệu định hướng tệp rất lớn khác, hãy lưu trữ
249        dữ liệu vào một tệp rồi cung cấp nó gián tiếp thay vì lưu trữ nó trực tiếp trong một
250        bảng. Nếu làm vậy, bạn cần báo cho người dùng trình cung cấp của bạn rằng họ cần sử dụng một phương pháp tệp
251        {@link android.content.ContentResolver} để truy cập dữ liệu.
252    </li>
253    <li>
254        Sử dụng kiểu dữ liệu Binary Large OBject (BLOB) để lưu trữ dữ liệu có kích cỡ khác nhau hoặc có một
255        cấu trúc thay đổi. Ví dụ, bạn có thể sử dụng cột BLOB để lưu trữ một
256        <a href="http://code.google.com/p/protobuf">bộ đệm giao thức</a> hay
257        <a href="http://www.json.org">cấu trúc JSON</a>.
258        <p>
259            Bạn cũng có thể sử dụng một BLOB để triển khai một bảng <em>độc lập với sơ đồ</em>. Trong
260            kiểu bảng này, bạn định nghĩa một cột khóa chính, một cột kiểu MIME, và một hoặc
261            nhiều cột chung là BLOB. Ý nghĩa của dữ liệu trong cột BLOB được thể hiện
262            bởi giá trị trong cột kiểu MIME. Điều này cho phép bạn lưu trữ các kiểu hàng khác nhau trong
263            cùng bảng. Bảng "dữ liệu"
264            {@link android.provider.ContactsContract.Data} của Trình cung cấp Danh bạ là một ví dụ về bảng
265            độc lập với sơ đồ.
266        </p>
267    </li>
268</ul>
269<!-- Designing Content URIs -->
270<h2 id="ContentURI">Thiết kế URI Nội dung</h2>
271<p>
272    <strong>URI nội dung</strong> là một URI xác định dữ liệu trong một trình cung cấp. URI nội dung bao gồm
273    tên mang tính biểu tượng của toàn bộ trình cung cấp (<strong>quyền</strong> của nó) và một
274    tên trỏ đến một bảng hoặc tệp (<strong>đường dẫn</strong>). Phần id tùy chọn chỉ đến một
275    hàng riêng lẻ trong một bảng. Mọi phương thức truy cập dữ liệu
276    {@link android.content.ContentProvider} đều có một URI nội dung là một tham đối; điều này cho phép bạn
277    xác định bảng, hàng, hoặc tệp để truy cập.
278</p>
279<p>
280    Nội dung cơ bản của URI nội dung được mô tả trong chủ đề
281    <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
282    Nội dung Cơ bản về Trình cung cấp Nội dung</a>.
283</p>
284<h3>Thiết kế một thẩm quyền</h3>
285<p>
286    Một trình cung cấp thường có một thẩm quyền duy nhất, đóng vai trò là tên nội bộ Android của nó. Để
287    tránh xung đột với các trình cung cấp khác, bạn nên sử dụng quyền sở hữu miền Internet (đảo ngược)
288    làm cơ sở cho thẩm quyền của trình cung cấp của mình. Vì đề xuất này cũng đúng đối với tên gói
289    Android, bạn có thể định nghĩa thẩm quyền trình cung cấp của mình là phần mở rộng của tên
290    gói chứa trình cung cấp. Ví dụ, nếu tên gói Android là
291    <code>com.example.&lt;appname&gt;</code>, bạn nên cấp cho trình cung cấp của mình
292    thẩm quyền <code>com.example.&lt;appname&gt;.provider</code>.
293</p>
294<h3>Thiết kế một cấu trúc đường dẫn</h3>
295<p>
296    Nhà phát triển thường tạo URI nội dung từ thẩm quyền bằng cách nối các đường dẫn trỏ đến
297    các bảng riêng lẻ. Ví dụ, nếu bạn có hai bảng <em>table1</em> và
298    <em>table2</em>, bạn kết hợp thẩm quyền từ ví dụ trước để tạo ra
299    các URI nội dung
300    <code>com.example.&lt;appname&gt;.provider/table1</code> và
301    <code>com.example.&lt;appname&gt;.provider/table2</code>. Các đường dẫn
302    không bị giới hạn ở một phân đoạn duy nhất, và không cần phải có một bảng cho từng cấp của đường dẫn.
303</p>
304<h3>Xử lý ID URI nội dung</h3>
305<p>
306    Theo quy ước, các trình cung cấp cho phép truy cập một hàng đơn trong một bảng bằng cách chấp nhận một URI nội dung
307    có một giá trị ID cho hàng đó ở cuối URI. Cũng theo quy ước, các trình cung cấp sẽ so khớp
308    giá trị ID với cột <code>_ID</code> của bảng, và thực hiện truy cập yêu cầu đối với
309    hàng trùng khớp.
310</p>
311<p>
312    Quy ước này tạo điều kiện cho một kiểu mẫu thiết kế chung cho các ứng dụng truy cập một trình cung cấp. Ứng dụng
313    tiến hành truy vấn đối với trình cung cấp và hiển thị kết quả {@link android.database.Cursor}
314    trong một {@link android.widget.ListView} bằng cách sử dụng {@link android.widget.CursorAdapter}.
315    Định nghĩa {@link android.widget.CursorAdapter} yêu cầu một trong các cột trong
316    {@link android.database.Cursor} phải là <code>_ID</code>
317</p>
318<p>
319    Sau đó, người dùng chọn một trong các hàng được hiển thị từ UI để xem hoặc sửa đổi
320    dữ liệu. Ứng dụng sẽ nhận được hàng tương ứng từ {@link android.database.Cursor} làm nền cho
321    {@link android.widget.ListView}, nhận giá trị <code>_ID</code> cho hàng này, nối nó với
322    URI nội dung, và gửi yêu cầu truy cập tới trình cung cấp. Sau đó, trình cung cấp có thể thực hiện
323    truy vấn hoặc sửa đổi đối với chính xác hàng mà người dùng đã chọn.
324</p>
325<h3>Kiểu mẫu URI nội dung</h3>
326<p>
327    Để giúp bạn chọn hành động nào sẽ thực hiện cho URI nội dung đến, API của trình cung cấp sẽ bao gồm
328    lớp thuận tiện {@link android.content.UriMatcher}, nó ánh xạ "kiểu mẫu" URI nội dung với
329    các giá trị số nguyên. Bạn có thể sử dụng các giá trị số nguyên trong một câu lệnh <code>switch</code> mà chọn
330    hành động mong muốn cho URI nội dung hoặc URI mà khớp với một kiểu mẫu cụ thể.
331</p>
332<p>
333    Kiểu mẫu URI nội dung sẽ so khớp các URI nội dung bằng cách sử dụng ký tự đại diện:
334</p>
335    <ul>
336        <li>
337            <strong><code>*</code>:</strong> Khớp một xâu ký tự hợp lệ bất kỳ với chiều dài bất kỳ.
338        </li>
339        <li>
340            <strong><code>#</code>:</strong> Khớp một xâu ký tự số có chiều dài bất kỳ.
341        </li>
342    </ul>
343<p>
344    Lấy một ví dụ về thiết kế và tạo mã xử lý URI nội dung, hãy xét một trình cung cấp có
345    thẩm quyền <code>com.example.app.provider</code> mà nhận ra các URI nội dung
346    trỏ đến các bảng sau:
347</p>
348<ul>
349    <li>
350        <code>content://com.example.app.provider/table1</code>: Một bảng gọi là <code>table1</code>.
351    </li>
352    <li>
353        <code>content://com.example.app.provider/table2/dataset1</code>: Một bảng gọi là
354        <code>dataset1</code>.
355    </li>
356    <li>
357        <code>content://com.example.app.provider/table2/dataset2</code>: Một bảng gọi là
358        <code>dataset2</code>.
359    </li>
360    <li>
361        <code>content://com.example.app.provider/table3</code>: Một bảng gọi là <code>table3</code>.
362    </li>
363</ul>
364<p>
365    Trình cung cấp cũng nhận ra những URI nội dung này nếu chúng có một ID hàng được nối kèm, như
366    ví dụ <code>content://com.example.app.provider/table3/1</code> đối với hàng được nhận biết bởi
367    <code>1</code> trong <code>table3</code>.
368</p>
369<p>
370    Sẽ có thể có các kiểu mẫu URI nội dung sau:
371</p>
372<dl>
373    <dt>
374        <code>content://com.example.app.provider/*</code>
375    </dt>
376    <dd>
377        Khớp với bất kỳ URI nội dung nào trong trình cung cấp.
378    </dd>
379    <dt>
380        <code>content://com.example.app.provider/table2/*</code>:
381    </dt>
382    <dd>
383        Khớp với một URI nội dung cho các bảng <code>dataset1</code>
384        và <code>dataset2</code>, nhưng không khớp với URI nội dung cho <code>table1</code> hoặc
385        <code>table3</code>.
386    </dd>
387    <dt>
388        <code>content://com.example.app.provider/table3/#</code>: Khớp với một URI nội dung
389        cho các hàng đơn trong <code>table3</code>, chẳng hạn như
390        <code>content://com.example.app.provider/table3/6</code> đối với hàng được xác định bởi
391        <code>6</code>.
392    </dt>
393</dl>
394<p>
395    Đoạn mã HTML sau cho biết cách hoạt động của các phương pháp trong {@link android.content.UriMatcher}.
396    Đoạn mã này xử lý các URI cho toàn bộ một bảng khác với URI cho một
397    hàng đơn, bằng cách sử dụng mẫu hình URI nội dung
398    <code>content://&lt;authority&gt;/&lt;path&gt;</code> cho các bảng, và
399    <code>content://&lt;authority&gt;/&lt;path&gt;/&lt;id&gt;</code> cho các hàng đơn.
400</p>
401<p>
402    Phương pháp {@link android.content.UriMatcher#addURI(String, String, int) addURI()} ánh xạ một
403    thẩm quyền và đường dẫn tới một giá trị số nguyên. Phương pháp {@link android.content.UriMatcher#match(Uri)
404    match()} trả về giá trị số nguyên cho một URI. Câu lệnh <code>switch</code> sẽ chọn
405    giữa truy vấn toàn bộ bảng và truy vấn cho một bản ghi đơn:
406</p>
407<pre class="prettyprint">
408public class ExampleProvider extends ContentProvider {
409...
410    // Creates a UriMatcher object.
411    private static final UriMatcher sUriMatcher;
412...
413    /*
414     * The calls to addURI() go here, for all of the content URI patterns that the provider
415     * should recognize. For this snippet, only the calls for table 3 are shown.
416     */
417...
418    /*
419     * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used
420     * in the path
421     */
422    sUriMatcher.addURI("com.example.app.provider", "table3", 1);
423
424    /*
425     * Sets the code for a single row to 2. In this case, the "#" wildcard is
426     * used. "content://com.example.app.provider/table3/3" matches, but
427     * "content://com.example.app.provider/table3 doesn't.
428     */
429    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
430...
431    // Implements ContentProvider.query()
432    public Cursor query(
433        Uri uri,
434        String[] projection,
435        String selection,
436        String[] selectionArgs,
437        String sortOrder) {
438...
439        /*
440         * Choose the table to query and a sort order based on the code returned for the incoming
441         * URI. Here, too, only the statements for table 3 are shown.
442         */
443        switch (sUriMatcher.match(uri)) {
444
445
446            // If the incoming URI was for all of table3
447            case 1:
448
449                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
450                break;
451
452            // If the incoming URI was for a single row
453            case 2:
454
455                /*
456                 * Because this URI was for a single row, the _ID value part is
457                 * present. Get the last path segment from the URI; this is the _ID value.
458                 * Then, append the value to the WHERE clause for the query
459                 */
460                selection = selection + "_ID = " uri.getLastPathSegment();
461                break;
462
463            default:
464            ...
465                // If the URI is not recognized, you should do some error handling here.
466        }
467        // call the code to actually do the query
468    }
469</pre>
470<p>
471    Một lớp khác, {@link android.content.ContentUris}, sẽ cung cấp các phương pháp thuận tiện để làm việc
472    với phần <code>id</code> của URI nội dung. Các lớp {@link android.net.Uri} và
473    {@link android.net.Uri.Builder} bao gồm các phương pháp thuận tiện cho việc phân tích các đối tượng
474    {@link android.net.Uri} hiện có và xây dựng các đối tượng mới.
475</p>
476
477<!-- Implementing the ContentProvider class -->
478<h2 id="ContentProvider">Triển khai Lớp Trình cung cấp Nội dung</h2>
479<p>
480    Thực thể  {@link android.content.ContentProvider} quản lý truy cập vào
481    một tập dữ liệu cấu trúc bằng cách xử lý yêu cầu từ các ứng dụng khác. Tất cả các dạng
482    truy cập cuối cùng đều gọi {@link android.content.ContentResolver}, sau đó nó gọi ra một phương pháp
483    cụ thể của {@link android.content.ContentProvider} để lấy quyền truy cập.
484</p>
485<h3 id="RequiredAccess">Phương pháp được yêu cầu</h3>
486<p>
487    Lớp tóm tắt {@link android.content.ContentProvider} sẽ định nghĩa sáu phương pháp tóm tắt
488    mà bạn phải triển khai như một phần lớp con cụ thể của mình. Tất cả những phương pháp này ngoại trừ
489    {@link android.content.ContentProvider#onCreate() onCreate()} đều được gọi ra bởi một ứng dụng máy khách
490    đang cố truy cập trình cung cấp nội dung của bạn:
491</p>
492<dl>
493    <dt>
494        {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
495        query()}
496    </dt>
497    <dd>
498        Truy xuất dữ liệu từ trình cung cấp của bạn. Sử dụng các tham đối để chọn bảng để
499        truy vấn, các hàng và cột để trả về, và thứ tự sắp xếp của kết quả.
500        Trả về dữ liệu như một đối tượng {@link android.database.Cursor}.
501    </dd>
502    <dt>
503        {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}
504    </dt>
505    <dd>
506        Chèn một hàng mới vào trình cung cấp của bạn. Sử dụng các tham đối để lựa chọn
507        bảng đích và nhận các giá trị cột để sử dụng. Trả về một URI nội dung cho
508        hàng mới chèn.
509    </dd>
510    <dt>
511        {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
512        update()}
513    </dt>
514    <dd>
515        Cập nhật các hàng hiện tại trong trình cung cấp của bạn. Sử dụng các tham đối để lựa chọn bảng và hàng
516        để cập nhật và nhận các giá trị cột được cập nhật. Trả về số hàng được cập nhật.
517    </dd>
518    <dt>
519        {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
520    </dt>
521    <dd>
522        Xóa hàng khỏi trình cung cấp của bạn. Sử dụng các tham đối để lựa chọn bảng và các hàng
523        cần xóa. Trả về số hàng được xóa.
524    </dd>
525    <dt>
526        {@link android.content.ContentProvider#getType(Uri) getType()}
527    </dt>
528    <dd>
529        Trả về kiểu MIME tương ứng với một URI nội dung. Phương pháp này được mô tả chi tiết hơn
530        trong phần <a href="#MIMETypes">Triển khai Kiểu MIME của Trình cung cấp Nội dung</a>.
531    </dd>
532    <dt>
533        {@link android.content.ContentProvider#onCreate() onCreate()}
534    </dt>
535    <dd>
536        Khởi tạo trình cung cấp của bạn. Hệ thống Android sẽ gọi ra phương pháp này ngay lập tức sau khi nó
537        tạo trình cung cấp của bạn. Để ý rằng trình cung cấp của bạn không được tạo cho đến khi đối tượng
538        {@link android.content.ContentResolver} cố truy cập nó.
539    </dd>
540</dl>
541<p>
542    Để ý rằng những phương pháp này có cùng chữ ký như các phương pháp
543    {@link android.content.ContentResolver} được đặt tên như nhau.
544</p>
545<p>
546    Việc bạn triển khai những phương pháp này nên xét tới các nội dung sau:
547</p>
548<ul>
549    <li>
550        Tất cả phương pháp này ngoại trừ {@link android.content.ContentProvider#onCreate() onCreate()}
551        đều có thể được gọi đồng thời bằng nhiều luồng, vì thế chúng phải an toàn đối với luồng. Để tìm hiểu
552        thêm về nhiều luồng, hãy xem chủ đề
553        <a href="{@docRoot}guide/components/processes-and-threads.html">
554        Tiến trình và Luồng</a>.
555    </li>
556    <li>
557        Tránh thực hiện những thao tác dài trong {@link android.content.ContentProvider#onCreate()
558        onCreate()}. Hoãn các tác vụ khởi tạo tới khi chúng thực sự cần thiết.
559        Phần <a href="#OnCreate">Triển khai phương pháp onCreate()</a>
560        sẽ bàn kỹ hơn về vấn đề này.
561    </li>
562    <li>
563        Mặc dù bạn phải triển khai những phương pháp này, mã của bạn không nhất thiết phải làm gì ngoại trừ việc
564        trả về kiểu dữ liệu kỳ vọng. Ví dụ, bạn có thể muốn ngăn những ứng dụng khác
565        chèn dữ liệu vào một số bảng. Để làm điều này, bạn có thể bỏ qua lệnh gọi tới
566        {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} và trả về
567        0.
568    </li>
569</ul>
570<h3 id="Query">Triển khai phương pháp query()</h3>
571<p>
572    Phương pháp
573    {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
574    ContentProvider.query()} phải trả về một đối tượng {@link android.database.Cursor}, nếu không nó sẽ thất bại
575, đưa ra một lỗi {@link java.lang.Exception}. Nếu bạn đang sử dụng một cơ sở dữ liệu SQLite làm kho lưu trữ dữ liệu của mình
576, bạn có thể chỉ cần trả về {@link android.database.Cursor} được trả về bởi một trong các phương pháp
577    <code>query()</code> của lớp {@link android.database.sqlite.SQLiteDatabase}.
578    Nếu truy vấn không khớp với bất kỳ hàng nào, bạn nên trả về một thực thể  {@link android.database.Cursor}
579    có phương pháp {@link android.database.Cursor#getCount()} trả về 0.
580    Bạn chỉ nên trả về <code>null</code> nếu đã xảy ra một lỗi nội bộ trong tiến trình truy vấn.
581</p>
582<p>
583    Nếu bạn không đang sử dụng một cơ sở dữ liệu SQLite làm kho lưu trữ dữ liệu của mình, hãy sử dụng một trong các lớp con cụ thể
584    của {@link android.database.Cursor}. Ví dụ, lớp {@link android.database.MatrixCursor} sẽ triển khai
585    một con chạy trong đó mỗi hàng là một mảng của {@link java.lang.Object}. Với lớp này,
586    hãy sử dụng {@link android.database.MatrixCursor#addRow(Object[]) addRow()} để thêm một hàng mới.
587</p>
588<p>
589    Nhớ rằng hệ thống Android phải có thể giao tiếp với {@link java.lang.Exception}
590    qua các ranh giới tiến trình. Android có thể làm vậy cho những trường hợp ngoại lệ sau, điều này có thể hữu ích
591    trong xử lý lỗi truy vấn:
592</p>
593<ul>
594    <li>
595        {@link java.lang.IllegalArgumentException} (Bạn có thể chọn đưa ra lỗi này nếu trình cung cấp của bạn
596        nhận một URI nội dung không hợp lệ)
597    </li>
598    <li>
599        {@link java.lang.NullPointerException}
600    </li>
601</ul>
602<h3 id="Insert">Triển khai phương pháp insert()</h3>
603<p>
604    Phương pháp {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} sẽ thêm một
605    hàng mới vào bảng phù hợp bằng cách sử dụng các giá trị trong tham đối {@link android.content.ContentValues}
606. Nếu tên cột không nằm trong tham đối {@link android.content.ContentValues}, bạn có thể
607    muốn cung cấp một giá trị mặc định cho nó hoặc trong mã trình cung cấp của bạn hoặc trong sơ đồ
608    cơ sở dữ liệu của bạn.
609</p>
610<p>
611    Phương pháp này sẽ trả về URI nội dung cho hàng mới. Để xây dựng điều này, hãy nối
612    giá trị <code>_ID</code> của hàng mới (hay khóa chính khác) với URI nội dung của bảng bằng cách sử dụng
613    {@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()}.
614</p>
615<h3 id="Delete">Triển khai phương pháp delete()</h3>
616<p>
617    Phương pháp {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()}
618    không cần phải xóa hàng thực chất khỏi kho lưu trữ dữ liệu của bạn. Nếu bạn đang sử dụng một trình điều hợp đồng bộ
619    với trình cung cấp của mình, bạn nên cân nhắc đánh dấu một hàng đã xóa
620    bằng cờ "xóa" thay vì gỡ bỏ hàng một cách hoàn toàn. Trình điều hợp đồng bộ có thể
621    kiểm tra các hàng đã xóa và gỡ bỏ chúng khỏi máy chủ trước khi xóa chúng khỏi trình cung cấp.
622</p>
623<h3 id="Update">Triển khai phương pháp update()</h3>
624<p>
625    Phương pháp {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[])
626    update()} lấy cùng tham đối {@link android.content.ContentValues} được sử dụng bởi
627    {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}, và
628    cùng tham đối <code>selection</code> và <code>selectionArgs</code> được sử dụng bởi
629    {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} và
630    {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
631    ContentProvider.query()}. Điều này có thể cho phép bạn sử dụng lại mã giữa những phương pháp này.
632</p>
633<h3 id="OnCreate">Triển khai phương pháp onCreate()</h3>
634<p>
635    Hệ thống Android sẽ gọi {@link android.content.ContentProvider#onCreate()
636    onCreate()} khi nó khởi động trình cung cấp. Bạn chỉ nên thực hiện các tác vụ khởi tạo chạy nhanh
637    trong phương pháp này, và hoãn việc tạo cơ sở dữ liệu và nạp dữ liệu tới khi trình cung cấp thực sự
638    nhận được yêu cầu cho dữ liệu. Nếu bạn thực hiện các tác vụ dài trong
639    {@link android.content.ContentProvider#onCreate() onCreate()}, bạn sẽ làm chậm lại
640    quá trình khởi động của trình cung cấp. Đến lượt mình, điều này sẽ làm chậm hồi đáp từ trình cung cấp đối với các
641    ứng dụng khác.
642</p>
643<p>
644    Ví dụ, nếu bạn đang sử dụng một cơ sở dữ liệu SQLite, bạn có thể tạo
645    một đối tượng {@link android.database.sqlite.SQLiteOpenHelper} mới trong
646    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()},
647    rồi tạo các bảng SQL lần đầu tiên khi bạn mở cơ sở dữ liệu. Để tạo điều kiện cho điều này,
648    lần đầu tiên bạn gọi {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase
649    getWritableDatabase()}, nó sẽ tự động gọi ra phương pháp
650    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
651    SQLiteOpenHelper.onCreate()}.
652</p>
653<p>
654    Hai đoạn mã HTML sau minh họa tương tác giữa
655    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} và
656    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
657    SQLiteOpenHelper.onCreate()}. Đoạn mã HTML đầu tiên là triển khai
658    {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}:
659</p>
660<pre class="prettyprint">
661public class ExampleProvider extends ContentProvider
662
663    /*
664     * Defines a handle to the database helper object. The MainDatabaseHelper class is defined
665     * in a following snippet.
666     */
667    private MainDatabaseHelper mOpenHelper;
668
669    // Defines the database name
670    private static final String DBNAME = "mydb";
671
672    // Holds the database object
673    private SQLiteDatabase db;
674
675    public boolean onCreate() {
676
677        /*
678         * Creates a new helper object. This method always returns quickly.
679         * Notice that the database itself isn't created or opened
680         * until SQLiteOpenHelper.getWritableDatabase is called
681         */
682        mOpenHelper = new MainDatabaseHelper(
683            getContext(),        // the application context
684            DBNAME,              // the name of the database)
685            null,                // uses the default SQLite cursor
686            1                    // the version number
687        );
688
689        return true;
690    }
691
692    ...
693
694    // Implements the provider's insert method
695    public Cursor insert(Uri uri, ContentValues values) {
696        // Insert code here to determine which table to open, handle error-checking, and so forth
697
698        ...
699
700        /*
701         * Gets a writeable database. This will trigger its creation if it doesn't already exist.
702         *
703         */
704        db = mOpenHelper.getWritableDatabase();
705    }
706}
707</pre>
708<p>
709    Đoạn mã HTML tiếp theo là triển khai
710    {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase)
711    SQLiteOpenHelper.onCreate()}, bao gồm một lớp trình trợ giúp:
712</p>
713<pre class="prettyprint">
714...
715// A string that defines the SQL statement for creating a table
716private static final String SQL_CREATE_MAIN = "CREATE TABLE " +
717    "main " +                       // Table's name
718    "(" +                           // The columns in the table
719    " _ID INTEGER PRIMARY KEY, " +
720    " WORD TEXT"
721    " FREQUENCY INTEGER " +
722    " LOCALE TEXT )";
723...
724/**
725 * Helper class that actually creates and manages the provider's underlying data repository.
726 */
727protected static final class MainDatabaseHelper extends SQLiteOpenHelper {
728
729    /*
730     * Instantiates an open helper for the provider's SQLite data repository
731     * Do not do database creation and upgrade here.
732     */
733    MainDatabaseHelper(Context context) {
734        super(context, DBNAME, null, 1);
735    }
736
737    /*
738     * Creates the data repository. This is called when the provider attempts to open the
739     * repository and SQLite reports that it doesn't exist.
740     */
741    public void onCreate(SQLiteDatabase db) {
742
743        // Creates the main table
744        db.execSQL(SQL_CREATE_MAIN);
745    }
746}
747</pre>
748
749
750<!-- Implementing ContentProvider MIME Types -->
751<h2 id="MIMETypes">Triển khai Kiểu MIME của Trình cung cấp Nội dung</h2>
752<p>
753    Lớp {@link android.content.ContentProvider} có hai phương pháp để trả về các kiểu MIME:
754</p>
755<dl>
756    <dt>
757        {@link android.content.ContentProvider#getType(Uri) getType()}
758    </dt>
759    <dd>
760        Một trong các phương pháp được yêu cầu mà bạn phải triển khai cho bất kỳ trình cung cấp nào.
761    </dd>
762    <dt>
763        {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
764    </dt>
765    <dd>
766        Một phương pháp mà bạn được dự tính sẽ triển khai nếu trình cung cấp của bạn cung cấp tệp.
767    </dd>
768</dl>
769<h3 id="TableMIMETypes">Kiểu MIME cho bảng</h3>
770<p>
771    Phương pháp {@link android.content.ContentProvider#getType(Uri) getType()} trả về một
772    {@link java.lang.String} theo định dạng MIME mà mô tả kiểu dữ liệu được trả về bởi tham đối
773    URI nội dung. Tham đối {@link android.net.Uri} có thể là một mẫu hình thay vì một URI cụ thể;
774    trong trường hợp này, bạn nên trả về kiểu dữ liệu được liên kết với các URI nội dung mà khớp với
775    mẫu hình đó.
776</p>
777<p>
778    Đối với các kiểu dữ liệu phổ biến như văn bản, HTML, hay JPEG,
779    {@link android.content.ContentProvider#getType(Uri) getType()} sẽ trả về
780    kiểu MIME tiêu chuẩn cho dữ liệu đó. Một danh sách đầy đủ về những kiểu tiêu chuẩn này có sẵn trên trang web
781    <a href="http://www.iana.org/assignments/media-types/index.htm">IANA MIME Media Types</a>
782.
783</p>
784<p>
785    Đối với các URI nội dung mà trỏ tới một hàng hoặc các hàng của bảng dữ liệu,
786    {@link android.content.ContentProvider#getType(Uri) getType()} sẽ trả về
787    một kiểu MIME theo định dạng MIME riêng cho nhà cung cấp của Android:
788</p>
789<ul>
790    <li>
791        Bộ phận kiểu: <code>vnd</code>
792    </li>
793    <li>
794        Bộ phận kiểu con:
795        <ul>
796            <li>
797    Nếu mẫu hình URI áp dụng cho một hàng đơn: <code>android.cursor.<strong>item</strong>/</code>
798            </li>
799            <li>
800    Nếu mẫu hình URI áp dụng cho nhiều hơn một hàng: <code>android.cursor.<strong>dir</strong>/</code>
801            </li>
802        </ul>
803    </li>
804    <li>
805        Bộ phận riêng theo trình cung cấp: <code>vnd.&lt;name&gt;</code>.<code>&lt;type&gt;</code>
806        <p>
807            Bạn cung cấp <code>&lt;name&gt;</code> và <code>&lt;type&gt;</code>.
808            Giá trị <code>&lt;name&gt;</code> nên là giá trị duy nhất toàn cục,
809            và giá trị <code>&lt;type&gt;</code> nên là giá trị duy nhất đối với mẫu hình
810            URI tương ứng. Một lựa chọn hay cho <code>&lt;name&gt;</code> đó là tên công ty của bạn hoặc
811            một thành phần nào đó trong tên gói Android cho ứng dụng của bạn. Một lựa chọn hay cho
812            <code>&lt;type&gt;</code> đó là một xâu xác định bảng được liên kết với
813            URI.
814        </p>
815
816    </li>
817</ul>
818<p>
819    Ví dụ, nếu thẩm quyền của một trình cung cấp là
820    <code>com.example.app.provider</code>, và nó làm hiện ra một bảng có tên
821    <code>table1</code> thì kiểu MIME cho nhiều hàng trong <code>table1</code> là:
822</p>
823<pre>
824vnd.android.cursor.<strong>dir</strong>/vnd.com.example.provider.table1
825</pre>
826<p>
827    Đối với một hàng đơn của <code>table1</code>, kiểu MIME là:
828</p>
829<pre>
830vnd.android.cursor.<strong>item</strong>/vnd.com.example.provider.table1
831</pre>
832<h3 id="FileMIMETypes">Kiểu MIME cho tệp</h3>
833<p>
834    Nếu trình cung cấp của bạn cung cấp tệp, hãy triển khai
835    {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}.
836    Phương pháp này sẽ trả về một mảng {@link java.lang.String} của kiểu MIME đối với các tệp mà trình cung cấp của bạn
837    có thể trả về cho một URI nội dung cho trước. Bạn nên lọc các kiểu MIME mà mình cung cấp bằng tham đối bộ lọc
838    kiểu MIME, sao cho bạn chỉ trả về những kiểu MIME mà máy khách muốn xử lý.
839</p>
840<p>
841    Ví dụ, xét một trình cung cấp hình ảnh dưới dạng tệp có định dạng <code>.jpg</code>,
842    <code>.png</code> và <code>.gif</code>.
843    Nếu một ứng dụng gọi {@link android.content.ContentResolver#getStreamTypes(Uri, String)
844    ContentResolver.getStreamTypes()} bằng xâu bộ lọc <code>image/*</code> (
845    mà là một "hình ảnh"),
846    khi đó phương pháp {@link android.content.ContentProvider#getStreamTypes(Uri, String)
847    ContentProvider.getStreamTypes()} sẽ trả về mảng:
848</p>
849<pre>
850{ &quot;image/jpeg&quot;, &quot;image/png&quot;, &quot;image/gif&quot;}
851</pre>
852<p>
853    Nếu ứng dụng chỉ quan tâm đến các tệp <code>.jpg</code>, vậy nó có thể gọi
854    {@link android.content.ContentResolver#getStreamTypes(Uri, String)
855    ContentResolver.getStreamTypes()} bằng xâu bộ lọc <code>*\/jpeg</code>, và
856    {@link android.content.ContentProvider#getStreamTypes(Uri, String)
857    ContentProvider.getStreamTypes()} sẽ trả về:
858<pre>
859{&quot;image/jpeg&quot;}
860</pre>
861<p>
862    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,
863    {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}
864    sẽ trả về <code>null</code>.
865</p>
866
867
868<!--  Implementing a Contract Class -->
869<h2 id="ContractClass">Triển khai một Lớp Hợp đồng</h2>
870<p>
871    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
872    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
873    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
874    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,
875    v.v.
876</p>
877<p>
878    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,
879    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
880    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ư
881    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
882    hằng số đó.
883</p>
884<p>
885    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ể
886    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.
887</p>
888<p>
889    Lớp {@link android.provider.ContactsContract} và các lớp lồng nhau của nó là các ví dụ về
890    lớp hợp đồng.
891</p>
892<h2 id="Permissions">Triển khai Quyền của Trình cung cấp Nội dung</h2>
893<p>
894    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
895    chủ đề <a href="{@docRoot}guide/topics/security/security.html">Bảo mật và Quyền</a>.
896    Chủ đề <a href="{@docRoot}guide/topics/data/data-storage.html">Kho lưu trữ Dữ liệu</a> cũng
897    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.
898    Nói tóm lại, các điểm quan trọng là:
899</p>
900<ul>
901    <li>
902        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ư
903        đối với ứng dụng và trình cung cấp của bạn.
904    </li>
905    <li>
906        Các cơ sở dữ liệu {@link android.database.sqlite.SQLiteDatabase} mà bạn tạo là dữ liệu riêng tư
907        đối với ứng dụng và trình cung cấp của bạn.
908    </li>
909    <li>
910        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à
911        <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
912        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.
913    </li>
914    <li>
915        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
916        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
917        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
918        "đọ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
919        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
920        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.
921    </li>
922</ul>
923<p>
924    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
925    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ụ,
926    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.
927</p>
928<h3>Triển khai quyền</h3>
929<p>
930    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
931    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,
932    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ử
933    con của phần tử <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
934    &lt;provider&gt;</a></code>. Bạn có thể đặt quyền áp dụng cho toàn bộ trình cung cấp,
935    hoặc cho một số bảng, hoặc thậm chí cho một số bản ghi, hoặc cả ba.
936</p>
937<p>
938    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ử
939    <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">
940    &lt;permission&gt;</a></code> trong tệp bản kê khai của bạn. Để
941    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
942    <code><a href="{@docRoot}guide/topics/manifest/permission-element.html#nm">
943    android:name</a></code>. Ví dụ, đặt tên quyền đọc
944    <code>com.example.app.provider.permission.READ_PROVIDER</code>.
945
946</p>
947<p>
948    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
949    á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.
950    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:
951</p>
952<dl>
953    <dt>
954        Quyền đọc-ghi đơn lẻ ở cấp trình cung cấp
955    </dt>
956    <dd>
957        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
958        bằng thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
959        android:permission</a></code> của phần tử
960        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
961        &lt;provider&gt;</a></code>.
962    </dd>
963    <dt>
964        Quyền đọc ghi tách riêng ở cấp độ trình cung cấp
965    </dt>
966    <dd>
967        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
968        bằng các thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
969        android:readPermission</a></code> và
970        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
971        android:writePermission</a></code> của phần tử
972        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
973        &lt;provider&gt;</a></code>. Chúng được ưu tiên so với quyền được yêu cầu bởi
974        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
975        android:permission</a></code>.
976    </dd>
977    <dt>
978        Quyền ở cấp đường dẫn
979    </dt>
980    <dd>
981        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
982        từng URI mà bạn muốn kiểm soát bằng một phần tử con
983        <code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html">
984        &lt;path-permission&gt;</a></code> của phần tử
985        <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
986        &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
987        quyền đọc/ghi, quyền đọc, hoặc quyền ghi, hoặc cả ba. Quyền đọc và
988        quyền ghi được ưu tiên so với quyền đọc/ghi. Đồng thời, quyền ở cấp độ đường dẫn
989        sẽ được ưu tiên so với quyền ở cấp độ trình cung cấp.
990    </dd>
991    <dt>
992        Quyền tạm thời
993    </dt>
994    <dd>
995        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
996        không có các quyền thường được yêu cầu. Tính năng truy cập
997        tạm thời làm giảm số quyền mà một ứng dụng phải yêu cầu trong
998        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
999        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ả
1000        dữ liệu của bạn.
1001        <p>
1002            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
1003            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
1004            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,
1005            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
1006            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
1007            của ảnh và cờ cho phép tới trình xem ảnh. Trình xem ảnh khi đó có thể
1008            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
1009            có quyền đọc bình thường cho trình cung cấp của bạn.
1010        </p>
1011        <p>
1012            Để sử dụng các quyền tạm thời, hoặc đặt thuộc tính
1013            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
1014            android:grantUriPermissions</a></code> của phần tử
1015            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1016            &lt;provider&gt;</a></code> hoặc thêm một hoặc nhiều phần tử con
1017            <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
1018            &lt;grant-uri-permission&gt;</a></code> vào phần tử
1019            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1020            &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
1021            {@link android.content.Context#revokeUriPermission(Uri, int)
1022            Context.revokeUriPermission()} bất cứ khi nào bạn gỡ bỏ hỗ trợ cho một URI nội dung khỏi
1023            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.
1024        </p>
1025        <p>
1026            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.
1027            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
1028            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
1029            quyền ở cấp độ trình cung cấp hoặc cấp độ đường dẫn của bạn.
1030        </p>
1031        <p>
1032            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
1033            <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
1034            &lt;grant-uri-permission&gt;</a></code> vào phần tử
1035            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1036            &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
1037            các URI mà truy cập tạm thời được cấp cho.
1038        </p>
1039        <p>
1040            Để ủy quyền truy cập tạm thời cho một ứng dụng, ý định phải chứa
1041            cờ {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} hoặc cờ
1042            {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, hoặc cả hai. Những quyền
1043            này được đặt bằng phương pháp {@link android.content.Intent#setFlags(int) setFlags()}.
1044        </p>
1045        <p>
1046            Nếu thuộc tính <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
1047            android:grantUriPermissions</a></code> không có mặt, giả sử rằng nó là
1048            <code>false</code>.
1049        </p>
1050    </dd>
1051</dl>
1052
1053
1054
1055<!-- The Provider Element -->
1056<h2 id="ProviderElement">Phần tử &lt;provider&gt;</h2>
1057<p>
1058    Như các thành phần {@link android.app.Activity} và {@link android.app.Service},
1059    một lớp con của {@link android.content.ContentProvider}
1060    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ử
1061    <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1062    &lt;provider&gt;</a></code>. Hệ thống Android nhận thông tin sau từ
1063    phần tử:
1064<dl>
1065    <dt>
1066        Thẩm quyền
1067        (<a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">{@code
1068        android:authorities}</a>)
1069    </dt>
1070    <dd>
1071        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
1072        này được mô tả chi tiết hơn trong phần
1073        <a href="#ContentURI">Thiết kế URI Nội dung</a>.
1074    </dd>
1075    <dt>
1076        Tên lớp của trình cung cấp
1077        (<code>
1078<a href="{@docRoot}guide/topics/manifest/provider-element.html#nm">android:name</a>
1079        </code>)
1080    </dt>
1081    <dd>
1082        Lớp triển khai {@link android.content.ContentProvider}. Lớp này
1083        được mô tả chi tiết hơn trong phần
1084        <a href="#ContentProvider">Triển khai Lớp Trình cung cấp Nội dung</a>.
1085    </dd>
1086    <dt>
1087        Quyền
1088    </dt>
1089    <dd>
1090        Những thuộc tính quy định quyền mà các ứng dụng khác phải có để truy cập
1091        dữ liệu của trình cung cấp:
1092        <ul>
1093            <li>
1094                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
1095                android:grantUriPermssions</a></code>: Cờ quyền tạm thời.
1096            </li>
1097            <li>
1098                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">
1099                android:permission</a></code>: Quyền đọc/ghi đơn lẻ đối với toàn bộ trình cung cấp.
1100            </li>
1101            <li>
1102                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">
1103                android:readPermission</a></code>: Quyền đọc đối với toàn bộ trình cung cấp.
1104            </li>
1105            <li>
1106                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">
1107                android:writePermission</a></code>: Quyền ghi đối với toàn bộ trình cung cấp.
1108            </li>
1109        </ul>
1110        <p>
1111            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
1112            phần
1113            <a href="#Permissions">Triển khai Quyền của Trình cung cấp Nội dung</a>.
1114        </p>
1115    </dd>
1116    <dt>
1117        Thuộc tính khởi động và kiểm soát
1118    </dt>
1119    <dd>
1120        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
1121        đặ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:
1122        <ul>
1123            <li>
1124                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#enabled">
1125                android:enabled</a></code>: Cờ cho phép hệ thống khởi động trình cung cấp.
1126            </li>
1127              <li>
1128                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
1129                android:exported</a></code>: Cờ cho phép các ứng dụng sử dụng trình cung cấp này.
1130            </li>
1131            <li>
1132                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#init">
1133                android:initOrder</a></code>: Thứ tự mà trình cung cấp nên được khởi động,
1134                so với các trình cung cấp khác trong cùng tiến trình.
1135            </li>
1136            <li>
1137                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#multi">
1138                android:multiProcess</a></code>: Cờ cho phép hệ thống khởi động trình cung cấp
1139                trong cùng tiến trình như máy khách gọi.
1140            </li>
1141            <li>
1142                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#proc">
1143                android:process</a></code>: Tên của tiến trình mà trình cung cấp
1144                nên chạy trong đó.
1145            </li>
1146            <li>
1147                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#sync">
1148                android:syncable</a></code>: Cờ cho biết rằng dữ liệu của trình cung cấp sẽ được
1149                đồng bộ với dữ liệu trên một máy chủ.
1150            </li>
1151        </ul>
1152        <p>
1153            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ử
1154            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1155            &lt;provider&gt;</a></code>
1156.
1157        </p>
1158    </dd>
1159    <dt>
1160        Các thuộc tính thông tin
1161    </dt>
1162    <dd>
1163        Một biểu tượng tùy chọn và nhãn cho trình cung cấp:
1164        <ul>
1165            <li>
1166                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#icon">
1167                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.
1168                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
1169                <em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
1170            </li>
1171            <li>
1172                <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#label">
1173                android:label</a></code>: Một nhãn thông tin mô tả trình cung cấp hoặc dữ liệu
1174                của nó, hoặc cả hai. Nhãn xuất hiện trong danh sách ứng dụng trong
1175                <em>Settings</em> &gt; <em>Apps</em> &gt; <em>All</em>.
1176            </li>
1177        </ul>
1178        <p>
1179            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ử
1180            <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">
1181            &lt;provider&gt;</a></code>.
1182        </p>
1183    </dd>
1184</dl>
1185
1186<!-- Intent Access -->
1187<h2 id="Intents">Ý định và Truy cập Dữ liệu</h2>
1188<p>
1189    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}.
1190    Ứng dụng không gọi bất kỳ phương pháp nào của {@link android.content.ContentResolver} hoặc
1191    {@link android.content.ContentProvider}. Thay vào đó, nó sẽ gửi một ý định để bắt đầu một hoạt động,
1192    đâ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
1193    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
1194    đí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.
1195    Một ý định cũng có thể chứa dữ liệu "phụ thêm" mà hoạt động đích hiển thị
1196    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
1197    dữ liệu trong trình cung cấp.
1198</p>
1199<p>
1200
1201</p>
1202<p>
1203    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
1204    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
1205    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
1206    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ỹ.
1207    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
1208    dữ liệu bằng mã của họ.
1209</p>
1210<p>
1211    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
1212    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ủ đề
1213    <a href="{@docRoot}guide/components/intents-filters.html">Ý định và Bộ lọc Ý định</a>.
1214</p>
1215