• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Preceitos do provedor de conteúdo
2@jd:body
3<div id="qv-wrapper">
4<div id="qv">
5<!-- In this document -->
6<h2>Neste documento</h2>
7<ol>
8    <li>
9        <a href="#Basics">Visão geral</a>
10        <ol>
11            <li>
12                <a href="#ClientProvider">Acesso a um provedor</a>
13            </li>
14            <li>
15                <a href="#ContentURIs">URIs de conteúdo</a>
16            </li>
17        </ol>
18    </li>
19    <li>
20        <a href="#SimpleQuery">Recuperação de dados do provedor</a>
21        <ol>
22            <li>
23                <a href="#RequestPermissions">Solicitação de permissão de acesso para leitura</a>
24            </li>
25            <li>
26                <a href="#Query">Construção da consulta</a>
27            </li>
28            <li>
29                <a href="#DisplayResults">Exibição dos resultados da consulta</a>
30            </li>
31            <li>
32                <a href="#GettingResults">Obtenção de dados de resultados da consulta</a>
33            </li>
34        </ol>
35    </li>
36    <li>
37        <a href="#Permissions">Permissões do provedor de conteúdo</a>
38    </li>
39    <li>
40        <a href="#Modifications">Inserção, atualização e exclusão de dados</a>
41        <ol>
42            <li>
43                <a href="#Inserting">Inserção de dados</a>
44            </li>
45            <li>
46                <a href="#Updating">Atualização de dados</a>
47            </li>
48            <li>
49                <a href="#Deleting">Exclusão de dados</a>
50            </li>
51        </ol>
52    </li>
53    <li>
54        <a href="#DataTypes">Tipos de dados do provedor</a>
55    </li>
56    <li>
57        <a href="#AltForms">Formas alternativas de acesso ao provedor</a>
58        <ol>
59            <li>
60                <a href="#Batch">Acesso em lote</a>
61            </li>
62            <li>
63                <a href="#Intents">Acesso a dados via intenções</a>
64            </li>
65        </ol>
66    </li>
67    <li>
68        <a href="#ContractClasses">Classes de contrato</a>
69    </li>
70    <li>
71        <a href="#MIMETypeReference">Referência de tipo MIME</a>
72    </li>
73</ol>
74
75    <!-- Key Classes -->
76<h2>Classes principais</h2>
77    <ol>
78        <li>
79            {@link android.content.ContentProvider}
80        </li>
81        <li>
82            {@link android.content.ContentResolver}
83        </li>
84        <li>
85            {@link android.database.Cursor}
86        </li>
87        <li>
88            {@link android.net.Uri}
89        </li>
90    </ol>
91
92    <!-- Related Samples -->
93<h2>Exemplos relacionados</h2>
94    <ol>
95        <li>
96        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
97        Cursor (Pessoas)</a>
98        </li>
99        <li>
100        <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
101        Cursor (Telefones)</a>
102        </li>
103    </ol>
104
105    <!-- See also -->
106<h2>Veja também</h2>
107    <ol>
108        <li>
109            <a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
110            Criação de um Provedor de conteúdo</a>
111        </li>
112        <li>
113            <a href="{@docRoot}guide/topics/providers/calendar-provider.html">
114            Provedor de agenda</a>
115        </li>
116    </ol>
117</div>
118</div>
119
120    <!-- Intro paragraphs -->
121<p>
122    O provedor de conteúdo gerencia o acesso a um repositório central de dados. Um provedor
123    é parte de um aplicativo do Android, que, em geral, fornece a própria IU para trabalhar com
124    os dados. Contudo, provedores de conteúdo destinam-se principalmente ao uso por outros
125    aplicativos, que acessam o provedor usando um objeto cliente do provedor. Juntos, provedores
126    e clientes do provedor oferecem interface padronizada e consistente para dados que também lidam com
127    comunicação em processos internos e garantem acesso a dados.
128</p>
129<p>
130    Esse tópico descreve os conceitos básicos do seguinte:
131</p>
132    <ul>
133        <li>Como os provedores de conteúdo funcionam.</li>
134        <li>A API usada para recuperar dados de um provedor de conteúdo.</li>
135        <li>A API usada para inserir, atualizar ou excluir dados em um provedor de conteúdo.</li>
136        <li>Outros recursos de API que facilitam o trabalho com provedores.</li>
137    </ul>
138
139    <!-- Basics -->
140<h2 id="Basics">Visão geral</h2>
141<p>
142    O provedor de conteúdo apresenta dados a aplicativos externos na forma de uma ou mais tabelas
143    similares às tabelas encontradas em um banco de dados relacional. Uma linha representa uma instância de algum tipo
144    de dados que o provedor coleta e cada coluna na linha representa uma parte individual de
145    dados coletados por uma instância.
146</p>
147<p>
148    Por exemplo: um dos provedores embutidos na plataforma do Android é o dicionário do usuário, que
149    armazena as grafias de palavras incomuns que o usuário deseja manter. A tabela 1 ilustra
150    como podem ser os dados nesta tabela do provedor:
151</p>
152<p class="table-caption">
153    <strong>Tabela 1:</strong> Tabela de dicionário do usuário de exemplo.
154</p>
155<table id="table1" style="width: 50%;">
156    <tr>
157        <th style="width:20%" align="center" scope="col">palavra</th>
158        <th style="width:20%" align="center" scope="col">id do aplicativo</th>
159        <th style="width:20%" align="center" scope="col">frequência</th>
160        <th style="width:20%" align="center" scope="col">localidade</th>
161        <th style="width:20%" align="center" scope="col">_ID</th>
162    </tr>
163    <tr>
164        <td align="center" scope="row">reduçãodomapa</td>
165        <td align="center">usuário1</td>
166        <td align="center">100</td>
167        <td align="center">en_US</td>
168        <td align="center">1</td>
169    </tr>
170    <tr>
171        <td align="center" scope="row">pré-compilador</td>
172        <td align="center">usuário14</td>
173        <td align="center">200</td>
174        <td align="center">fr_FR</td>
175        <td align="center">2</td>
176    </tr>
177    <tr>
178        <td align="center" scope="row">applet</td>
179        <td align="center">usuário2</td>
180        <td align="center">225</td>
181        <td align="center">fr_CA</td>
182        <td align="center">3</td>
183    </tr>
184    <tr>
185        <td align="center" scope="row">const</td>
186        <td align="center">usuário1</td>
187        <td align="center">255</td>
188        <td align="center">pt_BR</td>
189        <td align="center">4</td>
190    </tr>
191    <tr>
192        <td align="center" scope="row">int</td>
193        <td align="center">usuário5</td>
194        <td align="center">100</td>
195        <td align="center">en_UK</td>
196        <td align="center">5</td>
197    </tr>
198</table>
199<p>
200    Na tabela 1, cada linha representa uma instância de uma palavra que pode não ser
201    encontrada em um dicionário comum. Cada coluna representa alguns dados dessa palavra, como
202    a localidade em que foi encontrada pela primeira vez. Os cabeçalhos da coluna são nomes de coluna armazenados
203    no provedor. Para consultar a localidade de uma linha, consulte a sua coluna <code>locale</code>. Para
204    esse provedor, a coluna <code>_ID</code> serve como uma coluna de "chave principal" que
205    o provedor mantém automaticamente.
206</p>
207<p class="note">
208    <strong>Observação:</strong> os provedores não precisam ter uma chave principal e não precisam
209    usar <code>_ID</code> como o nome de coluna de uma chave principal se uma for apresentada. Contudo,
210    se você deseja agrupar dados de um provedor em um {@link android.widget.ListView}, um dos
211    nomes de coluna deve ser <code>_ID</code>. Esse requisito é explicado com mais detalhes
212    na seção <a href="#DisplayResults">Exibição dos resultados da consulta</a>.
213</p>
214<h3 id="ClientProvider">Acesso a um provedor</h3>
215<p>
216    Os aplicativos acessam dados a partir de um provedor de conteúdo
217    com um objeto cliente {@link android.content.ContentResolver}. Esse objeto tem métodos que chamam
218    métodos de nome idêntico no objeto do provedor, uma instância de uma das subclasses
219    concretas de {@link android.content.ContentProvider}.
220    Os métodos {@link android.content.ContentResolver} fornecem as funções básicas
221    do "CRUD" (criar, recuperar, atualizar e excluir) de armazenamento persistente.
222</p>
223<p>
224    O objeto {@link android.content.ContentResolver} no processo do aplicativo
225    cliente e o objeto {@link android.content.ContentProvider} no aplicativo que possui
226    o provedor lidam automaticamente com a comunicação de processos internos.
227    {@link android.content.ContentProvider} também age como uma camada de abstração entre
228    ser repositório de dados e a aparência externa de dados na forma de tabelas.
229</p>
230<p class="note">
231    <strong>Observação:</strong> para acessar um provedor, o aplicativo normalmente precisa solicitar permissões
232    específicas no arquivo de manifesto. Isso é descrito com mais detalhes na seção
233    <a href="#Permissions">Permissões do provedor de conteúdo</a>.
234</p>
235<p>
236    Por exemplo: para obter uma lista das palavras e respectivas localidades do Provedor de dicionário do usuário,
237    chama-se {@link android.content.ContentResolver#query ContentResolver.query()}.
238    O método {@link android.content.ContentResolver#query query()} chama
239    o método {@link android.content.ContentProvider#query ContentProvider.query()} definido pelo
240    Provedor de dicionário do usuário. As linhas de código a seguir exibem
241    uma chamada {@link android.content.ContentResolver#query ContentResolver.query()}:
242<p>
243<pre>
244// Queries the user dictionary and returns results
245mCursor = getContentResolver().query(
246    UserDictionary.Words.CONTENT_URI,   // The content URI of the words table
247    mProjection,                        // The columns to return for each row
248    mSelectionClause                    // Selection criteria
249    mSelectionArgs,                     // Selection criteria
250    mSortOrder);                        // The sort order for the returned rows
251</pre>
252<p>
253    A tabela 2 mostra como os argumentos para
254    {@link android.content.ContentResolver#query
255    query(Uri,projection,selection,selectionArgs,sortOrder)} correspondem a uma declaração SQL SELECT:
256</p>
257<p class="table-caption">
258    <strong>Tabela 2:</strong> Query() comparada à consulta SQL.
259</p>
260<table id="table2" style="width: 75%;">
261    <tr>
262        <th style="width:25%" align="center" scope="col">Argumento query()</th>
263        <th style="width:25%" align="center" scope="col">Palavra-chave/parâmetro de SELEÇÃO</th>
264        <th style="width:50%" align="center" scope="col">Observações</th>
265    </tr>
266    <tr>
267        <td align="center"><code>Uri</code></td>
268        <td align="center"><code>FROM <em>table_name</em></code></td>
269        <td><code>Uri</code> mapeia para a tabela no provedor chamado <em>table_name</em>.</td>
270    </tr>
271    <tr>
272        <td align="center"><code>projection</code></td>
273        <td align="center"><code><em>col,col,col,...</em></code></td>
274        <td>
275            <code>projection</code> é uma matriz de colunas que devem ser incluídas para cada linha
276            recuperada.
277        </td>
278    </tr>
279    <tr>
280        <td align="center"><code>selection</code></td>
281        <td align="center"><code>WHERE <em>col</em> = <em>value</em></code></td>
282        <td><code>selection</code> especifica o critério para a seleção de linhas.</td>
283    </tr>
284    <tr>
285        <td align="center"><code>selectionArgs</code></td>
286        <td align="center">
287            (Não exatamente equivalente. Argumentos de seleção substituem marcadores de posição <code>?</code>
288            na cláusula de seleção.)
289        </td>
290    </tr>
291    <tr>
292        <td align="center"><code>sortOrder</code></td>
293        <td align="center"><code>ORDER BY <em>col,col,...</em></code></td>
294        <td>
295            <code>sortOrder</code> especifica a ordem em que as linhas aparecem
296            no {@link android.database.Cursor} retornado.
297        </td>
298    </tr>
299</table>
300<h3 id="ContentURIs">URIs de conteúdo</h3>
301<p>
302    <strong>URI de conteúdo</strong> é uma URI que identifica dados em um provedor. URIs de conteúdo
303    contêm o nome simbólico de todo o provedor (sua <strong>autoridade</strong>)
304    e um nome que aponta para uma tabela (um <strong>caminho</strong>). Ao chamar
305    um método cliente para acessar uma tabela em um provedor, a URI de conteúdo da tabela é
306    um dos argumentos.
307</p>
308<p>
309    Nas linhas de código anteriores, a constante
310    {@link android.provider.UserDictionary.Words#CONTENT_URI} contém a URI de conteúdo
311    da tabela de "palavras" do dicionário do usuário. O objeto {@link android.content.ContentResolver}
312    analisa a autoridade da URI e usa-na para "determinar" o provedor
313    comparando a autoridade a uma tabela de provedores conhecidos do sistema.
314    O {@link android.content.ContentResolver} pode, então, enviar os argumentos da consulta ao provedor
315    correto.
316</p>
317<p>
318    O {@link android.content.ContentProvider} usa o caminho que é parte da URI de conteúdo para escolher
319    a tabela para acessar. Os provedores normalmente têm um <strong>caminho</strong> para cada tabela exposta.
320</p>
321<p>
322    Nas linhas de código anteriores, a URI completa da tabela de "palavras" é:
323</p>
324<pre>
325content://user_dictionary/words
326</pre>
327<p>
328    onde a string <code>user_dictionary</code> é a autoridade do provedor e
329    a string <code>words</code> é o caminho da tabela. A string
330    <code>content://</code> (o <strong>esquema</strong>) está sempre presente
331    e identifica isso como uma URI de conteúdo.
332</p>
333<p>
334    Muitos provedores permitem acesso a uma única linha em uma tabela, por meio da anexação do valor de um ID
335    no fim da URI. Por exemplo, para recuperar uma linha em que <code>_ID</code> seja
336    <code>4</code> do dicionário do usuário, é possível usar essa URI de conteúdo:
337</p>
338<pre>
339Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
340</pre>
341<p>
342    Normalmente usam-se valores de ID ao recuperar um conjunto de linhas e, em seguida, é necessário atualizar ou excluir
343    uma delas.
344</p>
345<p class="note">
346    <strong>Observação:</strong> as classes {@link android.net.Uri} e {@link android.net.Uri.Builder}
347    contêm métodos convenientes para a construção de objetos de URI bem formados a partir de strings.
348    As {@link android.content.ContentUris} contêm métodos conveniente para anexar valores de ID
349    a uma URI. O fragmento anterior usa {@link android.content.ContentUris#withAppendedId
350    withAppendedId()} para anexar um ID à URI de conteúdo UserDictionary.
351</p>
352
353
354    <!-- Retrieving Data from the Provider -->
355<h2 id="SimpleQuery">Recuperação de dados pelo Provedor</h2>
356<p>
357    Esta seção descreve como recuperar dados de um provedor usando o Provedor de dicionário do usuário
358    como um exemplo.
359</p>
360<p class="note">
361    Por uma questão de clareza, os fragmentos de código nesta seção chamam
362    {@link android.content.ContentResolver#query ContentResolver.query()} no "encadeamento da IU".
363    No código atual, contudo, deve-se realizar consultas assincronamente em um encadeamento separado. Um modo de fazê-lo
364    é usar a classe {@link android.content.CursorLoader}, descrita
365    com mais detalhes no guia <a href="{@docRoot}guide/components/loaders.html">
366    Carregadores</a>. Além disso, as linhas de código são somente fragmentos — não mostram um aplicativo
367    completo.
368</p>
369<p>
370    Para recuperar dados de um provedor, siga essas etapas básicas:
371</p>
372<ol>
373   <li>
374        Solicite a permissão de acesso para leitura para um provedor.
375   </li>
376   <li>
377        Defina o código que envia uma consulta ao provedor.
378   </li>
379</ol>
380<h3 id="RequestPermissions">Solicitação de permissão de acesso para leitura</h3>
381<p>
382    Para recuperar dados de um provedor, o aplicativo precisa de "permissão de acesso a leitura"
383    para o provedor. Não é possível solicitar essa permissão em tempo de execução. Em vez disso, deve-se especificar
384    que precisa dessa permissão no manifesto com o elemento
385<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
386    e o nome da permissão exata definida
387    pelo provedor. Ao especificar esse elemento no manifesto, você está efetivamente "solicitando" essa
388    permissão para o aplicativo. Quando usuários instalam seu aplicativo, eles concedem essa solicitação
389    implicitamente.
390</p>
391<p>
392    Para encontrar o nome exato da permissão de acesso para leitura do provedor que está usando, bem
393    como os nomes de outras permissões de acesso usadas pelo provedor, consulte a documentação
394    do provedor.
395</p>
396<p>
397    O papel das permissões no acesso a provedores é descrito com mais detalhes na seção
398    <a href="#Permissions">Permissões do provedor de conteúdo</a>.
399</p>
400<p>
401    O Provedor de Dicionário do Usuário define a permissão
402    <code>android.permission.READ_USER_DICTIONARY</code> no arquivo de manifesto, portanto, se um
403    aplicativo quiser ler pelo provedor, deve solicitar essa permissão.
404</p>
405<!-- Constructing the query -->
406<h3 id="Query">Construção da consulta</h3>
407<p>
408    A próxima etapa na recuperação de dados de um provedor é construir uma consulta. Este primeiro fragmento
409    define algumas variáveis para acessar o Provedor de Dicionário do Usuário:
410</p>
411<pre class="prettyprint">
412
413// A "projection" defines the columns that will be returned for each row
414String[] mProjection =
415{
416    UserDictionary.Words._ID,    // Contract class constant for the _ID column name
417    UserDictionary.Words.WORD,   // Contract class constant for the word column name
418    UserDictionary.Words.LOCALE  // Contract class constant for the locale column name
419};
420
421// Defines a string to contain the selection clause
422String mSelectionClause = null;
423
424// Initializes an array to contain selection arguments
425String[] mSelectionArgs = {""};
426
427</pre>
428<p>
429    O próximo fragmento mostra como usar
430    {@link android.content.ContentResolver#query ContentResolver.query()} usando o Provedor de
431    Dicionário do Usuário como exemplo. Uma consulta cliente do provedor é similar a uma consulta SQL e contém um
432    conjunto de colunas para retornar, um conjunto de critérios de seleção e uma classificação ordenada.
433</p>
434<p>
435    O conjunto de colunas que a consulta deve retornar é chamado de <strong>projeção</strong>
436    (a variável <code>mProjection</code>).
437</p>
438<p>
439    A expressão que especifica as linhas a recuperar é dividida em uma cláusula de seleção
440    e em argumentos de seleção. A cláusula de seleção é uma combinação de expressões lógicas e booleanas
441    e nomes e valores de colunas (a variável <code>mSelectionClause</code>). Ao especificar
442    o parâmetro <code>?</code> substituível em vez de um valor, o método da consulta recupera o valor
443    da matriz de argumentos de seleção (a variável <code>mSelectionArgs</code>).
444</p>
445<p>
446    No próximo fragmento, se o usuário não inserir nenhuma palavra, a cláusula de seleção será definida como
447    <code>null</code> e a consulta retornará todas as palavras no provedor. Se o usuário inserir
448    uma palavra, a cláusula de seleção será definida como <code>UserDictionary.Words.WORD + " = ?"</code>
449    e o primeiro elemento da matriz de argumentos de seleção é definida como a palavra que o usuário inserir.
450</p>
451<pre class="prettyprint">
452/*
453 * This defines a one-element String array to contain the selection argument.
454 */
455String[] mSelectionArgs = {""};
456
457// Gets a word from the UI
458mSearchString = mSearchWord.getText().toString();
459
460// Remember to insert code here to check for invalid or malicious input.
461
462// If the word is the empty string, gets everything
463if (TextUtils.isEmpty(mSearchString)) {
464    // Setting the selection clause to null will return all words
465    mSelectionClause = null;
466    mSelectionArgs[0] = "";
467
468} else {
469    // Constructs a selection clause that matches the word that the user entered.
470    mSelectionClause = UserDictionary.Words.WORD + " = ?";
471
472    // Moves the user's input string to the selection arguments.
473    mSelectionArgs[0] = mSearchString;
474
475}
476
477// Does a query against the table and returns a Cursor object
478mCursor = getContentResolver().query(
479    UserDictionary.Words.CONTENT_URI,  // The content URI of the words table
480    mProjection,                       // The columns to return for each row
481    mSelectionClause                   // Either null, or the word the user entered
482    mSelectionArgs,                    // Either empty, or the string the user entered
483    mSortOrder);                       // The sort order for the returned rows
484
485// Some providers return null if an error occurs, others throw an exception
486if (null == mCursor) {
487    /*
488     * Insert code here to handle the error. Be sure not to use the cursor! You may want to
489     * call android.util.Log.e() to log this error.
490     *
491     */
492// If the Cursor is empty, the provider found no matches
493} else if (mCursor.getCount() &lt; 1) {
494
495    /*
496     * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily
497     * an error. You may want to offer the user the option to insert a new row, or re-type the
498     * search term.
499     */
500
501} else {
502    // Insert code here to do something with the results
503
504}
505</pre>
506<p>
507    Essa consulta é análoga à declaração SQL:
508</p>
509<pre>
510SELECT _ID, word, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
511</pre>
512<p>
513    Nesta declaração SQL, os nomes de coluna reais são usados no lugar de constantes de classes de contrato.
514</p>
515<h4 id="Injection">Proteção contra inserções mal-intencionadas</h4>
516<p>
517    Se os dados gerenciados pelo provedor de conteúdo estiverem em um banco de dados SQL, inclusive dados não confiáveis
518    externos nas declarações SQL brutas, existe a possibilidade de haver uma injeção de SQL.
519</p>
520<p>
521    Considere esta cláusula de seleção:
522</p>
523<pre>
524// Constructs a selection clause by concatenating the user's input to the column name
525String mSelectionClause =  "var = " + mUserInput;
526</pre>
527<p>
528    Se você fizer isso, estará permitindo que o usuário concatene SQL mal-intencionados na sua declaração SQL.
529    Por exemplo: o usuário poderia inserir "nada; REMOVER TABELA *;" para <code>mUserInput</code>, o que
530    resultaria na cláusula de seleção <code>var = nothing; DROP TABLE *;</code>. Como
531    a cláusula de seleção é tratada como uma declaração SQL, isso pode fazer com que o provedor apague todas
532    as tabelas no banco de dados SQLite em questão (a menos que o provedor esteja configurado para capturar
533    tentativas de <a href="http://en.wikipedia.org/wiki/SQL_injection">injeção de SQL</a>).
534</p>
535<p>
536    Para evitar este problema, use uma cláusula de seleção que use <code>?</code> como um parâmetro
537    substituível e uma matriz de argumentos de seleção separada. Ao fazer isso, a inserção de dados do usuário
538    limita-se diretamente à consulta em vez de ser interpretada como parte de uma declaração SQL.
539    Pelo fato de não ser tratada como SQL, a inserção de dados do usuário não injeta SQL mal-intencionados. Em vez de usar
540    a concatenação para incluir a inserção de dados do usuário, use esta cláusula de seleção:
541</p>
542<pre>
543// Constructs a selection clause with a replaceable parameter
544String mSelectionClause =  "var = ?";
545</pre>
546<p>
547    Configure a matriz de argumentos de seleção desta maneira:
548</p>
549<pre>
550// Defines an array to contain the selection arguments
551String[] selectionArgs = {""};
552</pre>
553<p>
554    Insira um valor na matriz de argumentos de seleção desta maneira:
555</p>
556<pre>
557// Sets the selection argument to the user's input
558selectionArgs[0] = mUserInput;
559</pre>
560<p>
561    Usar uma cláusula de seleção que use <code>?</code> como um parâmetro substituível e uma matriz
562    de argumentos de seleção é o melhor modo de especificar uma seleção, mesmo que o provedor se baseie
563    base em um banco de dados SQL.
564</p>
565<!-- Displaying the results -->
566<h3 id="DisplayResults">Exibição dos resultados da consulta</h3>
567<p>
568    O método cliente {@link android.content.ContentResolver#query ContentResolver.query()} sempre
569    retorna um {@link android.database.Cursor} contendo as colunas especificadas pela projeção
570    da consulta para as linhas que atendem aos critérios de seleção da consulta.
571    Um objeto {@link android.database.Cursor} fornece acesso para leitura aleatório para as linhas e colunas que
572    contém. Usando métodos {@link android.database.Cursor}, é possível repetir as linhas
573    nos resultados, determinar o tipo dos dados de cada coluna, extrair os dados de uma coluna e examinar
574    outras propriedades dos resultados. Algumas implementações do {@link android.database.Cursor} atualizam o objeto
575    automaticamente quando os dados do provedor mudam ou acionam métodos em um objeto observador
576    quando o {@link android.database.Cursor} muda, ou ambos.
577</p>
578<p class="note">
579    <strong>Observação:</strong> os provedores podem restringir acesso a colunas com base na natureza
580    do objeto que realiza a consulta. Por exemplo: o Provedor de Contatos restringe o acesso de algumas colunas
581    a adaptadores de sincronização, por isso ela não os retornará a uma atividade ou serviço.
582</p>
583<p>
584    Se nenhuma linha atender aos critérios de seleção, o provedor
585    retorna um objeto {@link android.database.Cursor} para o qual
586    {@link android.database.Cursor#getCount Cursor.getCount()} é 0 (um cursor vazio).
587</p>
588<p>
589    Se ocorrer um erro interno, os resultados da consulta dependem do provedor determinado. Ele pode
590    escolher retornar <code>null</code> ou pode gerar uma {@link java.lang.Exception}.
591</p>
592<p>
593    Já que {@link android.database.Cursor} é uma "lista" de linhas, um bom modo de exibir
594    o conteúdo de um {@link android.database.Cursor} é vinculá-lo a uma {@link android.widget.ListView}
595    por meio de um {@link android.widget.SimpleCursorAdapter}.
596</p>
597<p>
598    O fragmento a seguir continua o código do fragmento anterior. Ele cria
599    um objeto {@link android.widget.SimpleCursorAdapter} contendo o {@link android.database.Cursor}
600    recuperado pela consulta e configura esse objeto para ser o adaptador de uma
601    {@link android.widget.ListView}:
602</p>
603<pre class="prettyprint">
604// Defines a list of columns to retrieve from the Cursor and load into an output row
605String[] mWordListColumns =
606{
607    UserDictionary.Words.WORD,   // Contract class constant containing the word column name
608    UserDictionary.Words.LOCALE  // Contract class constant containing the locale column name
609};
610
611// Defines a list of View IDs that will receive the Cursor columns for each row
612int[] mWordListItems = { R.id.dictWord, R.id.locale};
613
614// Creates a new SimpleCursorAdapter
615mCursorAdapter = new SimpleCursorAdapter(
616    getApplicationContext(),               // The application's Context object
617    R.layout.wordlistrow,                  // A layout in XML for one row in the ListView
618    mCursor,                               // The result from the query
619    mWordListColumns,                      // A string array of column names in the cursor
620    mWordListItems,                        // An integer array of view IDs in the row layout
621    0);                                    // Flags (usually none are needed)
622
623// Sets the adapter for the ListView
624mWordList.setAdapter(mCursorAdapter);
625</pre>
626<p class="note">
627    <strong>Observação:</strong> para retornar uma {@link android.widget.ListView} com um
628    {@link android.database.Cursor}, o cursor deve conter uma coluna chamada <code>_ID</code>.
629    Por isso, a consulta exibida anteriormente recupera a coluna <code>_ID</code> da
630    tabelas de "palavras", mesmo que a {@link android.widget.ListView} não a exiba.
631    Essa restrição também explica por que a maioria dos provedores tem uma coluna <code>_ID</code> para cada
632    tabela.
633</p>
634
635        <!-- Getting data from query results -->
636<h3 id="GettingResults">Obtenção de dados de resultados da consulta</h3>
637<p>
638    Em vez de simplesmente exibir resultados da consulta, é possível usá-los para outras tarefas. Por
639    exemplo: é possível recuperar grafias de um dicionário do usuário e, em seguida, procurá-los
640    em outros provedores. Para isso, repetem-se as linhas no {@link android.database.Cursor}:
641</p>
642<pre class="prettyprint">
643
644// Determine the column index of the column named "word"
645int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);
646
647/*
648 * Only executes if the cursor is valid. The User Dictionary Provider returns null if
649 * an internal error occurs. Other providers may throw an Exception instead of returning null.
650 */
651
652if (mCursor != null) {
653    /*
654     * Moves to the next row in the cursor. Before the first movement in the cursor, the
655     * "row pointer" is -1, and if you try to retrieve data at that position you will get an
656     * exception.
657     */
658    while (mCursor.moveToNext()) {
659
660        // Gets the value from the column.
661        newWord = mCursor.getString(index);
662
663        // Insert code here to process the retrieved word.
664
665        ...
666
667        // end of while loop
668    }
669} else {
670
671    // Insert code here to report an error if the cursor is null or the provider threw an exception.
672}
673</pre>
674<p>
675    As implementações {@link android.database.Cursor} contêm diversos métodos "get" (obter)
676    para recuperar diferentes tipos de dados do objeto. Por exemplo, o fragmento anterior
677    usa {@link android.database.Cursor#getString getString()}. Elas também têm
678    um método {@link android.database.Cursor#getType getType()} que retorna um valor indicando
679    o tipo dos dados da coluna.
680</p>
681
682
683    <!-- Requesting permissions -->
684<h2 id="Permissions">Permissões do provedor de conteúdo</h2>
685<p>
686    Um aplicativo do provedor pode especificar permissões que outros aplicativos devem ter para
687    acessar os dados do provedor. Essas permissões garantem que o usuário saiba quais dados
688    um aplicativo tentará acessar. Com base nos requisitos do provedor, outros aplicativos
689    solicitam as permissões de que precisam para acessar o provedor. Usuários finais veem as permissões
690    solicitadas quando instalam o aplicativo.
691</p>
692<p>
693    Se um aplicativo do provedor não especificar nenhuma permissão, outros aplicativos não terão
694    acesso aos dados do provedor. No entanto, os componentes no aplicativo do provedor sempre têm
695    acesso total para leitura e gravação, independentemente das permissões especificadas.
696</p>
697<p>
698    Como observado anteriormente, o Provedor de Dicionário do Usuário requer
699    a permissão <code>android.permission.READ_USER_DICTIONARY</code> para recuperar dados dele.
700    O provedor tem a permissão <code>android.permission.WRITE_USER_DICTIONARY</code>
701    separadamente para inserção, atualização ou exclusão de dados.
702</p>
703<p>
704    Para obter as permissões necessárias para acessar um provedor, um aplicativo as solicita
705como um elemento <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
706    no arquivo de manifesto. Quando o Android Package Manager (gerente de pacotes do Android) instala o aplicativo, o usuário
707    precisa aprovar todas as permissões que o aplicativo solicita. Se o usuário aprovar todas elas,
708    o gerente de pacotes continua a instalação; se o usuário não as aprovar, o gerente de pacotes
709    aborta a instalação.
710</p>
711<p>
712    O elemento
713<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code> a seguir
714     solicita acesso para leitura ao Provedor de Dicionário do Usuário:
715</p>
716<pre>
717    &lt;uses-permission android:name="android.permission.READ_USER_DICTIONARY"&gt;
718</pre>
719<p>
720    O impacto das permissões no acesso ao provedor é explicado com mais detalhes
721    no guia <a href="{@docRoot}guide/topics/security/security.html">Permissões e segurança</a>.
722</p>
723
724
725<!-- Inserting, Updating, and Deleting Data -->
726<h2 id="Modifications">Inserção, atualização e exclusão de dados</h2>
727<p>
728    Do mesmo modo que se recupera dados de um provedor, também usa-se a interação entre
729    um cliente do provedor e o {@link android.content.ContentProvider} do provedor para modificar dados.
730    Chama-se um método de {@link android.content.ContentResolver} com argumentos que são passados para
731    o método correspondente de {@link android.content.ContentProvider}. O provedor e o cliente
732    do provedor tratam automaticamente da segurança e da comunicação de processos internos.
733</p>
734<h3 id="Inserting">Inserção de dados</h3>
735<p>
736    Para inserir dados em um provedor, chame
737    o método
738{@link android.content.ContentResolver#insert ContentResolver.insert()}. Esse método insere uma nova linha no provedor e retorna uma URI de conteúdo dessa linha.
739    Este fragmento mostra como inserir uma nova palavra no Provedor de Dicionário do Usuário:
740</p>
741<pre class="prettyprint">
742// Defines a new Uri object that receives the result of the insertion
743Uri mNewUri;
744
745...
746
747// Defines an object to contain the new values to insert
748ContentValues mNewValues = new ContentValues();
749
750/*
751 * Sets the values of each column and inserts the word. The arguments to the "put"
752 * method are "column name" and "value"
753 */
754mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
755mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
756mNewValues.put(UserDictionary.Words.WORD, "insert");
757mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
758
759mNewUri = getContentResolver().insert(
760    UserDictionary.Word.CONTENT_URI,   // the user dictionary content URI
761    mNewValues                          // the values to insert
762);
763</pre>
764<p>
765    Os dados da nova linha vão para um objeto {@link android.content.ContentValues} único, que
766    tem forma semelhante a um cursor de uma linha. As colunas nesse objeto não precisam ter
767    o mesmo tipo de dados e, se você não quiser especificar um valor, pode definir uma coluna
768    como <code>null</code> usando {@link android.content.ContentValues#putNull ContentValues.putNull()}.
769</p>
770<p>
771    O fragmento não adiciona a coluna <code>_ID</code> porque essa coluna é mantida
772    automaticamente. O provedor atribui um valor exclusivo de <code>_ID</code> para cada linha
773    adicionada. Os provedores normalmente usam esse valor como a chave principal da tabela.
774</p>
775<p>
776    A URI de conteúdo retornada em <code>newUri</code> identifica a linha recentemente adicionada com
777    o seguinte formato:
778</p>
779<pre>
780content://user_dictionary/words/&lt;id_value&gt;
781</pre>
782<p>
783    O <code>&lt;id_value&gt;</code> é o conteúdo de <code>_ID</code> da nova linha.
784    A maioria dos provedores pode detectar essa forma de URI de conteúdo automaticamente e, em seguida, realizar a operação
785    solicitada naquela linha.
786</p>
787<p>
788    Para obter o valor de <code>_ID</code> do {@link android.net.Uri} retornado, chame
789    {@link android.content.ContentUris#parseId ContentUris.parseId()}.
790</p>
791<h3 id="Updating">Atualização de dados</h3>
792<p>
793    Para atualizar uma linha, use um objeto {@link android.content.ContentValues} com os valores
794    e os critérios de seleção atualizados, como se faz com uma inserção e em uma consulta, respectivamente.
795    O método cliente usado é
796    {@link android.content.ContentResolver#update ContentResolver.update()}. Só é necessário adicionar
797    valores ao objeto {@link android.content.ContentValues} das colunas que forem atualizadas. Se você
798    deseja apagar o conteúdo de uma coluna, defina o valor como <code>null</code>.
799</p>
800<p>
801    O fragmento a seguir altera todas as linhas cuja localidade tem o idioma "en" para
802    terem uma localidade de <code>null</code>. O valor de retorno é o número de linhas que foram atualizadas:
803</p>
804<pre>
805// Defines an object to contain the updated values
806ContentValues mUpdateValues = new ContentValues();
807
808// Defines selection criteria for the rows you want to update
809String mSelectionClause = UserDictionary.Words.LOCALE +  "LIKE ?";
810String[] mSelectionArgs = {"en_%"};
811
812// Defines a variable to contain the number of updated rows
813int mRowsUpdated = 0;
814
815...
816
817/*
818 * Sets the updated value and updates the selected words.
819 */
820mUpdateValues.putNull(UserDictionary.Words.LOCALE);
821
822mRowsUpdated = getContentResolver().update(
823    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI
824    mUpdateValues                       // the columns to update
825    mSelectionClause                    // the column to select on
826    mSelectionArgs                      // the value to compare to
827);
828</pre>
829<p>
830    Você também deve filtrar a inserção de dados do usuário ao chamar
831    {@link android.content.ContentResolver#update ContentResolver.update()}. Para saber mais sobre
832    isso, leia a seção <a href="#Injection">Proteção contra inserções mal-intencionadas</a>.
833</p>
834<h3 id="Deleting">Exclusão de dados</h3>
835<p>
836    Excluir linhas é semelhante a recuperar dados de linhas: especificam-se critérios de seleção para as linhas
837    que se deseja excluir e o método cliente retorna o número de linhas excluídas.
838    O fragmento a seguir exclui linhas cujo appid (id do aplicativo) corresponda a "usuário". O método retorna
839    o número de linhas excluídas.
840</p>
841<pre>
842
843// Defines selection criteria for the rows you want to delete
844String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?";
845String[] mSelectionArgs = {"user"};
846
847// Defines a variable to contain the number of rows deleted
848int mRowsDeleted = 0;
849
850...
851
852// Deletes the words that match the selection criteria
853mRowsDeleted = getContentResolver().delete(
854    UserDictionary.Words.CONTENT_URI,   // the user dictionary content URI
855    mSelectionClause                    // the column to select on
856    mSelectionArgs                      // the value to compare to
857);
858</pre>
859<p>
860    Também se deve filtrar a inserção de dados do usuário ao chamar
861    {@link android.content.ContentResolver#delete ContentResolver.delete()}. Para saber mais sobre
862    isso, leia a seção <a href="#Injection">Proteção contra inserções mal-intencionadas</a>.
863</p>
864<!-- Provider Data Types -->
865<h2 id="DataTypes">Tipos de dados do provedor</h2>
866<p>
867    Provedores de conteúdo podem oferecer muitos tipos de dados diferentes. O Provedor de Dicionário do Usuário oferece somente
868    texto, mas provedores também podem oferecer os seguintes formatos:
869</p>
870    <ul>
871        <li>
872            número inteiro
873        </li>
874        <li>
875            número inteiro longo (longo)
876        </li>
877        <li>
878            ponto flutuante
879        </li>
880        <li>
881            ponto flutuante longo (duplo)
882        </li>
883    </ul>
884<p>
885    Outros tipos de dados que provedores usam com frequência são objetos binários largos (BLOB) implementados como uma
886    matriz de byte de 64 kB. É possível ver os tipos de dados disponíveis consultando
887    os métodos "get" da classe {@link android.database.Cursor}.
888</p>
889<p>
890    O tipo dos dados para cada coluna em um provedor normalmente é listado na documentação do provedor.
891    Os tipos de dados do Provedor de Dicionário do Usuário são listados na documentação de referência
892    para sua classe de contrato {@link android.provider.UserDictionary.Words} (classes de contrato são
893    descritas na seção <a href="#ContractClasses">Classes de contrato</a>).
894    Também é possível determinar o tipo dos dados chamando {@link android.database.Cursor#getType
895    Cursor.getType()}.
896</p>
897<p>
898    Os provedores também mantêm informações do tipo MIME de dados para cada URI de conteúdo que definem. É possível
899    usar as informações do tipo MIME para descobrir se o aplicativo pode tratar de dados que
900    o provedor fornece ou para escolher um tipo de tratamento com base no tipo MIME. Normalmente é necessário ter
901    o tipo MIME ao trabalhar com um provedor que contenha estruturas
902    complexas de dados ou arquivos. Por exemplo: a tabela {@link android.provider.ContactsContract.Data}
903    no Provedor de contatos usa tipos MIME para etiquetar o tipo dos dados de contato armazenados em cada
904    linha. Para obter o tipo MIME correspondente a uma URI de conteúdo, chame
905    {@link android.content.ContentResolver#getType ContentResolver.getType()}.
906</p>
907<p>
908    A seção <a href="#MIMETypeReference">Referência de tipo MIME</a> descreve
909    a sintaxe de tipos MIME padrão e personalizados.
910</p>
911
912
913<!-- Alternative Forms of Provider Access -->
914<h2 id="AltForms">Formas alternativas de acessar o provedor</h2>
915<p>
916    Três formas alternativas de acesso ao provedor são importantes no desenvolvimento do aplicativo:
917</p>
918<ul>
919    <li>
920        <a href="#Batch">Acesso em lote</a>: É possível criar um lote de chamadas de acesso com métodos na
921        classe {@link android.content.ContentProviderOperation} e, em seguida, aplicá-los com
922        {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}.
923    </li>
924    <li>
925        Consultas assíncronas: Devem-se realizar consultas em um encadeamento separado. Um modo de fazer isso é
926        usar um objeto {@link android.content.CursorLoader}. Os exemplos
927        no guia <a href="{@docRoot}guide/components/loaders.html">Carregadores</a> demonstram
928        como fazer isso.
929    </li>
930    <li>
931        <a href="#Intents">Acesso a dados via intenções</a> Embora não seja possível enviar uma intenção
932        diretamente a um provedor, é possível enviar uma intenção ao aplicativo do provedor, que
933        normalmente é o recomendável para modificar os dados do provedor.
934    </li>
935</ul>
936<p>
937    O acesso em lote e a modificação via intenções são descritos nas seções a seguir.
938</p>
939<h3 id="Batch">Acesso em lote</h3>
940<p>
941    O acesso em lote a um provedor é útil para inserir uma grande quantidade de linhas ou para inserir
942    linhas em diversas tabelas na mesma chamada de método ou, em geral, para realizar um conjunto de
943    operações dentre limites de processo como uma transação (uma operação atômica).
944</p>
945<p>
946    Para acessar um provedor em "modo de lote",
947    cria-se uma matriz de objetos {@link android.content.ContentProviderOperation} e, em seguida,
948    envia-os a um provedor de conteúdo com
949    {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Confere-se a
950    <em>autoridade</em> do provedor de conteúdo para esse método em vez de para uma URI de conteúdo específica.
951    Isso permite que cada objeto {@link android.content.ContentProviderOperation} na matriz trabalhe
952    com uma tabela diferente. Chamar {@link android.content.ContentResolver#applyBatch
953    ContentResolver.applyBatch()} retorna uma matriz de resultados.
954</p>
955<p>
956    A descrição da classe de contrato {@link android.provider.ContactsContract.RawContacts}
957    contém um fragmento de código que demonstra a inserção em lote.
958O aplicativo de exemplo do <a href="{@docRoot}resources/samples/ContactManager/index.html">Gerente de contato</a>
959    contém um exemplo de acesso em lote em seu
960    arquivo de origem <code>ContactAdder.java</code>.
961</p>
962<div class="sidebox-wrapper">
963<div class="sidebox">
964<h2>Exibição de dados usando um aplicativo auxiliar</h2>
965<p>
966    Se o seu aplicativo <em>tem</em> permissões de acesso, ainda é possível usar
967    uma intenção para exibir dados em outro aplicativo. Por exemplo: o aplicativo Agenda aceita
968    uma intenção {@link android.content.Intent#ACTION_VIEW} que exibe uma data ou evento específico.
969    Isso permite a exibição de informações da agenda sem precisar criar a própria IU.
970    Para saber mais sobre esse recurso, consulte
971    o guia <a href="{@docRoot}guide/topics/providers/calendar-provider.html">Provedor de agenda</a>.
972</p>
973<p>
974    O aplicativo para o qual você enviou uma intenção não precisa ser o aplicativo
975    associado ao provedor. Por exemplo: você pode recuperar um contato
976    do Provedor de Contatos e, em seguida, enviar uma intenção {@link android.content.Intent#ACTION_VIEW}
977    que contém a URI de conteúdo da imagem do contato para um visualizador de imagens.
978</p>
979</div>
980</div>
981<h3 id="Intents">Acesso a dados via intenções</h3>
982<p>
983    Intenções podem fornecer acesso indireto a um provedor de conteúdo. Basta permitir que o usuário acesse
984    dados em um provedor mesmo se o aplicativo não tiver permissões de acesso, tanto
985    retornando uma intenção de resultado de um aplicativo que tem permissões quanto ativando
986    um aplicativo que tem permissões e permitindo que o usuário trabalhe nele.
987</p>
988<h4>Obtenção de acesso com permissões temporárias</h4>
989<p>
990    É possível acessar dados em um provedor de conteúdo, mesmo sem s permissões
991    de acesso adequadas. Basta enviar uma intenção a um aplicativo que tenha as permissões e
992    receber de volta uma intenção de resultado contendo permissões da "URI".
993    Essas são permissões para uma URI de conteúdo específica que duram enquanto durar a atividade
994    que as recebeu. O aplicativo que tem permissões permanentes concedem permissões
995    temporárias ativando um sinalizador na intenção de resultado:
996</p>
997<ul>
998    <li>
999        <strong>Permissão de leitura:</strong>
1000        {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}
1001    </li>
1002    <li>
1003        <strong>Permissão de gravação:</strong>
1004        {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}
1005    </li>
1006</ul>
1007<p class="note">
1008    <strong>Observação:</strong> esses sinalizadores não fornecem acesso geral de leitura ou gravação ao provedor
1009    cuja autoridade esteja contida na URI de conteúdo. O acesso destina-se somente à URI.
1010</p>
1011<p>
1012    Um provedor define permissões de URI para URIs de conteúdo no manifesto usando o atributo
1013<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code>
1014    do elemento
1015<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>,
1016    bem como o elemento filho
1017<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
1018    do elemento
1019<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
1020. O mecanismo das permissões de URI é explicado com mais detalhes
1021    no guia <a href="{@docRoot}guide/topics/security/security.html">Permissões e segurança</a>,
1022    na seção "Permissões da URI".
1023</p>
1024<p>
1025    Por exemplo: é possível recuperar dados de um contato no Provedor de Contatos, mesmo sem
1026    a permissão {@link android.Manifest.permission#READ_CONTACTS}. Você pode desejar fazer
1027    isso em um aplicativo que envie e-mails de parabenização a um contato no aniversário dele. Em vez de
1028    solicitar {@link android.Manifest.permission#READ_CONTACTS}, que fornece acesso a todos
1029    os contatos do usuário e suas informações, é preferível deixar que o usuário controle quais
1030    contatos serão usados pelo seu aplicativo. Para isso, use o processo a seguir:
1031</p>
1032<ol>
1033    <li>
1034        O aplicativo envia uma intenção contendo a ação
1035    {@link android.content.Intent#ACTION_PICK} e o tipo MIME
1036    {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} dos "contatos" usando
1037    o método {@link android.app.Activity#startActivityForResult
1038        startActivityForResult()}.
1039    </li>
1040    <li>
1041        Como essa intenção corresponde ao filtro de intenções da
1042        atividade de "seleção" do aplicativo Pessoas, a atividade ficará em primeiro plano.
1043    </li>
1044    <li>
1045        Na atividade de seleção, o usuário seleciona
1046        um contato para atualizar. Quando isso acontece, a atividade de seleção chama
1047        {@link android.app.Activity#setResult setResult(resultcode, intent)}
1048        para configurar uma intenção para retornar ao aplicativo. A intenção contém a URI de conteúdo
1049        do contato que o usuário selecionou e os sinalizadores "extras"
1050        {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. Esses sinalizadores concedem
1051        permissão de URI para que o aplicativo leia dados do contato apontados pela
1052        URI de conteúdo. A atividade de seleção, em seguida, chama {@link android.app.Activity#finish()} para
1053        retornar o controle para o aplicativo.
1054    </li>
1055    <li>
1056        A atividade volta ao primeiro plano e o sistema chama o
1057        método {@link android.app.Activity#onActivityResult onActivityResult()}
1058        da sua atividade. Esse método recebe a intenção de resultado criada pela atividade de seleção
1059        no aplicativo Pessoas.
1060    </li>
1061    <li>
1062        Com a URI de conteúdo da intenção de resultado, é possível ler os dados do contato
1063        a partir do Provedor de Contatos, mesmo que não tenha solicitado permissão permanente de acesso a leitura
1064        para o provedor no manifesto. Pode-se, então, pode obter as informações de data de nascimento do contato
1065        ou seu endereço de e-mail e, assim, enviar um e-mail de parabenização.
1066    </li>
1067</ol>
1068<h4>Uso de outro aplicativo</h4>
1069<p>
1070    Um modo simples que permite ao usuário modificar dados para os quais você não tem permissões de acesso é
1071    ativar um aplicativo que tenha permissões e deixar o usuário fazer o resto.
1072</p>
1073<p>
1074    Por exemplo: o aplicativo Agenda aceita uma
1075    intenção {@link android.content.Intent#ACTION_INSERT} que permite a ativação da
1076    IU de inserção do aplicativo. Você pode passar dados "extras" nessa intenção que o aplicativo
1077    usa para "pré-preencher" a IU. como os eventos recorrentes têm sintaxe complexa, o modo
1078    recomendado de inserir eventos no Provedor de Agenda é ativar o aplicativo Agenda com um
1079    {@link android.content.Intent#ACTION_INSERT} e, em seguida, deixar o usuário inserir o evento.
1080</p>
1081<!-- Contract Classes -->
1082<h2 id="ContractClasses">Classes de contrato</h2>
1083<p>
1084    As classes de contrato definem constantes que ajudam os aplicativos a trabalhar com URIs de conteúdo, nomes
1085    de colunas, ações de intenções e outros recursos de um provedor de conteúdo. Elas não estão
1086    automaticamente inclusas em um provedor; o desenvolvedor do provedor deve defini-las e
1087    disponibilizá-las a outros desenvolvedores. Muitos dos provedores incluídos na plataforma
1088    do Android têm classes de contrato correspondentes no pacote {@link android.provider}.
1089</p>
1090<p>
1091    Por exemplo: o Provedor de Dicionário do Usuário tem uma classe de contrato
1092    {@link android.provider.UserDictionary} que contém constantes de URI de conteúdo e de nome de coluna.
1093    A URI de conteúdo da tabela de "palavras" é definida na constante
1094    {@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI}.
1095    A classe {@link android.provider.UserDictionary.Words} também contém constantes de nome de coluna
1096    que são usadas nos fragmentos de exemplo neste guia. Por exemplo, uma projeção de consulta pode ser
1097    definida como:
1098</p>
1099<pre>
1100String[] mProjection =
1101{
1102    UserDictionary.Words._ID,
1103    UserDictionary.Words.WORD,
1104    UserDictionary.Words.LOCALE
1105};
1106</pre>
1107<p>
1108    Outra classe de contrato é {@link android.provider.ContactsContract} para o Provedor de Contatos.
1109    A documentação de referência desta classe contém fragmentos de código de exemplo. Uma das suas
1110    subclasses, {@link android.provider.ContactsContract.Intents.Insert}, é uma classe
1111    de contrato que contém constantes para intenções e dados da intenção.
1112</p>
1113
1114
1115<!-- MIME Type Reference -->
1116<h2 id="MIMETypeReference">Referência do tipo MIME</h2>
1117<p>
1118    Provedores de conteúdo podem retornar tipos MIME de mídia, strings de tipos MIME personalizados ou ambos.
1119</p>
1120<p>
1121    Tipos MIME têm o formato
1122</p>
1123<pre>
1124<em>type</em>/<em>subtype</em>
1125</pre>
1126<p>
1127    Por exemplo: o tipo MIME <code>text/html</code> conhecido tem o tipo <code>text</code>
1128    e o subtipo <code>html</code>. Se o provedor retornar esse tipo para uma URI,
1129    uma consulta usando essa URI retornará um texto que contém tags HTML.
1130</p>
1131<p>
1132    Strings de tipo MIME personalizado, também chamadas de tipos MIME "específicos do fornecedor" (vendor-specific), têm mais
1133    valores de <em>tipo</em> e <em>subtipo</em> complexos. O valor de <em>tipo</em> é sempre
1134</p>
1135<pre>
1136vnd.android.cursor.<strong>dir</strong>
1137</pre>
1138<p>
1139    para diversas linhas ou
1140</p>
1141<pre>
1142vnd.android.cursor.<strong>item</strong>
1143</pre>
1144<p>
1145    para uma única linha.
1146</p>
1147<p>
1148    O <em>subtipo</em> é específico do provedor. Os provedores embutidos do Android normalmente têm um subtipo
1149    simples. Por exemplo, quando o aplicativo de contatos cria uma linha para um número de telefone,
1150    ele configura o seguinte tipo MIME na linha:
1151</p>
1152<pre>
1153vnd.android.cursor.item/phone_v2
1154</pre>
1155<p>
1156    Observe que o valor do subtipo é simplesmente <code>phone_v2</code>.
1157</p>
1158<p>
1159    Outros desenvolvedores de provedor podem criar os próprios padrões de subtipos com base
1160    na autoridade do provedor e nos nomes da tabela. Por exemplo: considere um provedor que contenha horários de trens.
1161    A autoridade do provedor é <code>com.example.trains</code> e ele contém as tabelas
1162    Linha1, Linha2 e Linha3. Em resposta à URI de conteúdo
1163</p>
1164<p>
1165<pre>
1166content://com.example.trains/Line1
1167</pre>
1168<p>
1169    para a tabela Linha1, o provedor retorna o tipo MIME
1170</p>
1171<pre>
1172vnd.android.cursor.<strong>dir</strong>/vnd.example.line1
1173</pre>
1174<p>
1175     Em resposta à URI de conteúdo
1176</p>
1177<pre>
1178content://com.example.trains/Line2/5
1179</pre>
1180<p>
1181    da linha 5 na tabela Linha2, o provedor retorna o tipo MIME
1182</p>
1183<pre>
1184vnd.android.cursor.<strong>item</strong>/vnd.example.line2
1185</pre>
1186<p>
1187    A maioria dos provedores define constantes de classe de contrato para os tipos MIME que usam.
1188    A classe de contrato {@link android.provider.ContactsContract.RawContacts} do Provedor de Contatos,
1189    por exemplo, define a constante
1190    {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} para o tipo MIME
1191    de uma linha exclusiva do contato bruto.
1192</p>
1193<p>
1194    URIs de conteúdo de linhas exclusivas são descritas na seção
1195    <a href="#ContentURIs">URIs de conteúdo</a>.
1196</p>
1197