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"><uses-permission></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() < 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 = <userinput> 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"><uses-permission></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"><uses-permission></a></code> a seguir 714 solicita acesso para leitura ao Provedor de Dicionário do Usuário: 715</p> 716<pre> 717 <uses-permission android:name="android.permission.READ_USER_DICTIONARY"> 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/<id_value> 781</pre> 782<p> 783 O <code><id_value></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"><provider></a></code>, 1016 bem como o elemento filho 1017<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission></a></code> 1018 do elemento 1019<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></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