| page.title=Criação de um Provedor de Conteúdo |
| @jd:body |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| |
| |
| <h2>Neste documento</h2> |
| <ol> |
| <li> |
| <a href="#DataStorage">Projeto de armazenamento de dados</a> |
| </li> |
| <li> |
| <a href="#ContentURI">Projeto de URIs de conteúdo</a> |
| </li> |
| <li> |
| <a href="#ContentProvider">Implementação da classe ContentProvider</a> |
| <ol> |
| <li> |
| <a href="#RequiredAccess">Métodos obrigatórios</a> |
| </li> |
| <li> |
| <a href="#Query">Implementação do método query()</a> |
| </li> |
| <li> |
| <a href="#Insert">Implementação do método insert()</a> |
| </li> |
| <li> |
| <a href="#Delete">Implementação do método delete()</a> |
| </li> |
| <li> |
| <a href="#Update">Implementação do método update()</a> |
| </li> |
| <li> |
| <a href="#OnCreate">Implementação do método onCreate()</a> |
| </li> |
| </ol> |
| </li> |
| <li> |
| <a href="#MIMETypes">Implementação de tipos MIME do Provedor de Conteúdo</a> |
| <ol> |
| <li> |
| <a href="#TableMIMETypes">Tipos MIME para tabelas</a> |
| </li> |
| <li> |
| <a href="#FileMIMETypes">Tipos MIME para arquivos</a> |
| </li> |
| </ol> |
| </li> |
| <li> |
| <a href="#ContractClass">Implementação de uma classe de contrato</a> |
| </li> |
| <li> |
| <a href="#Permissions">Implementação de permissões do Provedor de Conteúdo</a> |
| </li> |
| <li> |
| <a href="#ProviderElement">O elemento <provider></a> |
| </li> |
| <li> |
| <a href="#Intents">Intenções e acesso a dados</a> |
| </li> |
| </ol> |
| <h2>Classes principais</h2> |
| <ol> |
| <li> |
| {@link android.content.ContentProvider} |
| </li> |
| <li> |
| {@link android.database.Cursor} |
| </li> |
| <li> |
| {@link android.net.Uri} |
| </li> |
| </ol> |
| <h2>Exemplos relacionados</h2> |
| <ol> |
| <li> |
| <a href="{@docRoot}resources/samples/NotePad/index.html"> |
| Aplicativo de exemplo do Bloco de Notas |
| </a> |
| </li> |
| </ol> |
| <h2>Veja também</h2> |
| <ol> |
| <li> |
| <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a> |
| </li> |
| <li> |
| <a href="{@docRoot}guide/topics/providers/calendar-provider.html"> |
| Provedor de agenda</a> |
| </li> |
| </ol> |
| </div> |
| </div> |
| |
| |
| <p> |
| O provedor de conteúdo gerencia o acesso a um repositório central de dados. Implementa-se |
| um provedor como uma ou mais classes em um aplicativo do Android, em conjunto com elementos |
| no arquivo de manifesto. Uma das classes implementa uma subclasse |
| {@link android.content.ContentProvider}, que é a interface entre o provedor |
| e outros aplicativos. Embora provedores de conteúdo se destinem a disponibilizar dados a outros |
| aplicativos, naturalmente é possível ter atividades no aplicativo que permitam ao usuário |
| consultar e modificar os dados gerenciados pelo provedor. |
| </p> |
| <p> |
| O restante deste tópico é uma lista básica de etapas para a criação de um provedor de conteúdo e uma lista |
| de APIs para usar. |
| </p> |
| |
| |
| <!-- Before You Start Building --> |
| <h2 id="BeforeYouStart">Antes de começar a criar</h2> |
| <p> |
| Antes de começar a criar um provedor, faça o seguinte: |
| </p> |
| <ol> |
| <li> |
| <strong>Avalie se você precisa de um provedor de conteúdo</strong>. É necessário criar um provedor |
| de conteúdo para fornecer um ou mais dos recursos a seguir: |
| <ul> |
| <li>Oferecer dados ou arquivos complexos a outros aplicativos.</li> |
| <li>Permitir que usuários copiem dados complexos do seu aplicativo para outros aplicativos.</li> |
| <li>Fornecer sugestões de pesquisa personalizada usando a estrutura de pesquisa.</li> |
| </ul> |
| <p> |
| <em>Não</em> é necessário um provedor para usar um banco de dados SQLite se o uso for inteiramente dentro |
| do próprio aplicativo. |
| </p> |
| </li> |
| <li> |
| Se você ainda não tiver feito isso, leia o tópico |
| <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a> para saber mais sobre provedores. |
| </li> |
| </ol> |
| <p> |
| A seguir, siga estas etapas para criar seu provedor: |
| </p> |
| <ol> |
| <li> |
| Projete o armazenamento bruto dos dados. Os provedores de conteúdo oferecem dados de duas maneiras: |
| <dl> |
| <dt> |
| Dados de arquivo |
| </dt> |
| <dd> |
| Dados que normalmente transitam em arquivos, como |
| fotos, áudio ou vídeos. Armazene os arquivos no espaço privado |
| do seu aplicativo. Em resposta a uma solicitação de um arquivo por outro aplicativo, |
| o provedor pode oferecer um identificador para o arquivo. |
| </dd> |
| <dt> |
| Dados "estruturados" |
| </dt> |
| <dd> |
| Dados que normalmente transitam em um banco de dados, uma matriz ou estrutura similar. |
| Armazene os dados de forma compatível com tabelas de linhas e colunas. Cada linha |
| representa uma entidade, como uma pessoa ou um item em um inventário. Cada coluna representa |
| alguns dados da entidade, como o nome da pessoa ou o preço do item. Um modo comum de |
| armazenar esse tipo de dados é em um banco de dados SQLite, mas é possível usar qualquer tipo |
| de armazenamento persistente. Para saber mais sobre os tipos de armazenamento disponíveis |
| no sistema Android, consulte a seção <a href="#DataStorage"> |
| Projeto de armazenamento de dados</a>. |
| </dd> |
| </dl> |
| </li> |
| <li> |
| Defina uma implementação sólida da classe {@link android.content.ContentProvider} |
| e seus métodos obrigatórios. Essa classe é a interface entre seus dados e o restante |
| do sistema Android. Para obter mais informações sobre essa classe, consulte a seção |
| <a href="#ContentProvider">Implementação da classe ContentProvider</a>. |
| </li> |
| <li> |
| Defina a string de autoridade do provedor, suas URIs de conteúdo e seus nomes de coluna. Se você deseja que |
| o aplicativo do provedor trate de intenções, defina também ações de intenção, dados extras |
| e sinalizadores. Também defina as permissões necessárias para aplicativos que queiram |
| acessar seus dados. Deve-se considerar definir todos esses valores como constantes |
| em uma classe de contrato separada; posteriormente, será possível expor essa classe a outros desenvolvedores. Para |
| obter mais informações sobre URIs de conteúdo, consulte |
| a seção <a href="#ContentURI">Projeto de URIs de conteúdo</a>. |
| Para obter mais informações sobre intenções, consulte |
| a seção <a href="#Intents">Intenções e acesso a dados</a>. |
| </li> |
| <li> |
| Adicione outras partes opcionais, como dados de exemplo ou uma implementação |
| de {@link android.content.AbstractThreadedSyncAdapter} que possa sincronizar dados entre |
| o provedor e os dados com base em nuvem. |
| </li> |
| </ol> |
| |
| |
| <!-- Designing Data Storage --> |
| <h2 id="DataStorage">Projeto de armazenamento de dados</h2> |
| <p> |
| Os provedores de conteúdo são a interface para dados salvos em um formato estruturado. Antes de criar |
| a interface, é preciso decidir como armazenar os dados. É possível armazená-los da forma que |
| quiser e, em seguida, projetar a interface para ler e gravar os dados conforme o necessário. |
| </p> |
| <p> |
| Essas são algumas das tecnologias de armazenamento de dados disponíveis no Android: |
| </p> |
| <ul> |
| <li> |
| O sistema Android contém uma API de banco de dados SQLite que os provedores do Android usam |
| para armazenar dados orientados a tabela. |
| A classe {@link android.database.sqlite.SQLiteOpenHelper} ajuda a criar bancos de dados |
| e a classe {@link android.database.sqlite.SQLiteDatabase} é a classe de base para acessar |
| banco de dados. |
| <p> |
| Lembre-se de que não é necessário usar nenhum banco de dados para implementar o repositório. Um provedor |
| aparece externamente como um conjunto de tabelas, semelhante a um banco de dados relacional, mas isso não |
| é um requisito para a implementação interna do provedor. |
| </p> |
| </li> |
| <li> |
| Para armazenar dados de arquivos, o Android tem diversas APIs orientadas a arquivo. |
| Para saber mais sobre armazenamento de arquivos, leia o tópico |
| <a href="{@docRoot}guide/topics/data/data-storage.html">Armazenamento de dados</a>. Se você estiver |
| projetando um provedor que oferece dados relacionados a mídia como música ou vídeos, é possível |
| ter um provedor que combine dados de tabela e de arquivos. |
| </li> |
| <li> |
| Para trabalhar com dados com base em rede, use classes em {@link java.net} |
| e em {@link android.net}. É possível, também, sincronizar dados com base em rede com uma armazenagem |
| local de dados, como um banco de dados e, em seguida, fornecer os dados na forma de tabelas ou arquivos. |
| O exemplo de aplicativo <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html"> |
| Exemplo de adaptador de sincronização</a> demonstra o tipo de sincronização. |
| </li> |
| </ul> |
| <h3 id="DataDesign"> |
| Considerações para projetar dados |
| </h3> |
| <p> |
| A seguir há algumas dicas para projetar a estrutura de dados do seu provedor: |
| </p> |
| <ul> |
| <li> |
| Os dados de tabela sempre devem ter uma coluna de "chave principal" que o provedor mantém |
| como um valor numérico exclusivo para cada linha. É possível usar esse valor para vincular a linha a linhas |
| relacionadas em outras tabelas (usando-o como uma "chave externa"). Embora seja possível usar qualquer nome |
| para essa coluna, é melhor usar {@link android.provider.BaseColumns#_ID BaseColumns._ID} |
| porque a vinculação dos resultados de uma consulta de provedor com uma |
| {@link android.widget.ListView} requer que uma das colunas tenha o nome |
| <code>_ID</code>. |
| </li> |
| <li> |
| Se você deseja fornecer imagens bitmap ou outras partes muito grandes de dados orientados a arquivo, armazene |
| os dados em um arquivo e, em seguida, forneça-o indiretamente em vez de armazená-lo diretamente em uma |
| tabela. Ao fazer isso, será necessário informar aos usuários do provedor que eles precisam usar |
| um método de arquivo {@link android.content.ContentResolver} para acessar os dados. |
| </li> |
| <li> |
| Use objeto grande binário (BLOB) como tipo de dados para armazenar dados que variam em tamanho ou que tenham |
| estrutura variável. Por exemplo: é possível usar uma coluna de BLOB para armazenar |
| um <a href="http://code.google.com/p/protobuf">buffer de protocolo</a> ou |
| uma <a href="http://www.json.org">estrutura JSON</a>. |
| <p> |
| Pode-se usar um BLOB para implementar uma tabela <em>independente de esquema</em>. Nesse |
| tipo de tabela, define-se uma coluna de chave principal, uma coluna de tipo MIME e uma |
| ou mais colunas genéricas como BLOB. O significado dos dados nas colunas BLOB é indicado |
| pelo valor na coluna de tipo MIME. Isso permite o armazenamento de diferentes tipos de linha |
| na mesma tabela. A tabela de "dados" {@link android.provider.ContactsContract.Data} |
| do Provedor de contatos é um exemplo de uma tabela |
| independente de esquema. |
| </p> |
| </li> |
| </ul> |
| <!-- Designing Content URIs --> |
| <h2 id="ContentURI">Projeto de URIs de conteúdo</h2> |
| <p> |
| <strong>URI de conteúdo</strong> é uma URI que identifica dados em um provedor. URIs de conteúdo |
| contêm o nome simbólico de todo o provedor (sua <strong>autoridade</strong>) e um |
| nome que aponta para uma tabela ou arquivo (um <strong>caminho</strong>). Parte do ID opcional aponta para |
| uma linha individual em uma tabela. Cada método de acesso aos dados |
| {@link android.content.ContentProvider} de tem uma URI de conteúdo como um argumento. Isso permite |
| determinar a tabela, a linha ou o arquivo a acessar. |
| </p> |
| <p> |
| Os conceitos básicos de URIs de conteúdo são escritos no tópico |
| <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a>. |
| </p> |
| <h3>Projeto de uma autoridade</h3> |
| <p> |
| Os provedores normalmente têm uma única autoridade, que serve como seu nome interno do Android. Para |
| evitar conflitos com outros provedores, deve-se usar a propriedade de domínio da internet (ao contrário) |
| como a base da autoridade do provedor. Em virtude de esta recomendação ser verdadeira para nomes |
| de pacote do Android, é possível definir a autoridade do provedor como uma extensão do nome |
| do pacote que contém o provedor. Por exemplo: se o nome do pacote do Android for |
| <code>com.example.<appname></code>, deve-se atribuir ao provedor |
| a autoridade <code>com.example.<appname>.provider</code>. |
| </p> |
| <h3>Projeto de uma estrutura de caminho</h3> |
| <p> |
| Desenvolvedores normalmente criam URIs de conteúdo a partir da autoridade anexando caminhos que apontam para |
| tabelas individuais. Por exemplo: se você tiver duas tabelas (<em>tabela1</em> e |
| <em>tabela2</em>), combine a autoridade do exemplo anterior para produzir |
| as URIs de conteúdo |
| <code>com.example.<appname>.provider/table1</code> e |
| <code>com.example.<appname>.provider/table2</code>. Caminhos não |
| se limitam a um único segmento e não precisa ter uma tabela para cada nível do caminho. |
| </p> |
| <h3>Identificação de IDs de URIs de conteúdo</h3> |
| <p> |
| Por convenção, provedores fornecem acesso a uma linha exclusiva em uma tabela aceitando uma URI de conteúdo |
| com um valor de ID para a linha no fim da URI. Também por convenção, provedores combinam |
| o valor do ID com a coluna <code>_ID</code> da tabela e realizam o acesso solicitado |
| na linha correspondente. |
| </p> |
| <p> |
| Essa convenção facilita a padronização comum do projeto para aplicativos que acessam um provedor. O aplicativo |
| realiza uma consulta no provedor e exibe o {@link android.database.Cursor} |
| resultante em uma {@link android.widget.ListView} usando um {@link android.widget.CursorAdapter}. |
| A definição de {@link android.widget.CursorAdapter} requer que uma das colunas |
| no {@link android.database.Cursor} seja <code>_ID</code> |
| </p> |
| <p> |
| Em seguida, o usuário seleciona uma das linhas exibidas na IU para visualizar ou modificar |
| os dados. O aplicativo tem a linha correspondente do {@link android.database.Cursor} apoiando |
| a {@link android.widget.ListView}, obtém o valor <code>_ID</code> para essa linha, anexa-o |
| à URI de conteúdo e envia a solicitação de acesso ao provedor. O provedor, então, pode realizar |
| a consulta ou modificação na exata linha que o usuário selecionou. |
| </p> |
| <h3>Padrões de URI de conteúdo</h3> |
| <p> |
| Para ajudar a escolher que ação tomar para uma URI de conteúdo recebida, a API do provedor contém |
| a classe de conveniência {@link android.content.UriMatcher}, que mapeia "padrões" de URI de conteúdo |
| como valores de número inteiro. É possível usar os valores de número inteiro em uma declaração <code>switch</code> que |
| escolha a ação desejada para a URI de conteúdo ou URIs que atendam ao padrão determinado. |
| </p> |
| <p> |
| Um padrão de URI de conteúdo corresponde a URIs de conteúdo que usam caracteres especiais: |
| </p> |
| <ul> |
| <li> |
| <strong><code>*</code>:</strong> Corresponde a uma string de qualquer caractere válido de qualquer comprimento. |
| </li> |
| <li> |
| <strong><code>#</code>:</strong> Corresponde a uma string de caracteres numéricos de qualquer comprimento. |
| </li> |
| </ul> |
| <p> |
| Como um exemplo de projeto e codificação da identificação de URIs de conteúdo, considere um provedor |
| com a autoridade <code>com.example.app.provider</code> que reconheça as URIs de conteúdo |
| que apontam para tabelas: |
| </p> |
| <ul> |
| <li> |
| <code>content://com.example.app.provider/table1</code>: Uma tabela chamada <code>table1</code>. |
| </li> |
| <li> |
| <code>content://com.example.app.provider/table2/dataset1</code>: Uma tabela chamada |
| <code>dataset1</code>. |
| </li> |
| <li> |
| <code>content://com.example.app.provider/table2/dataset2</code>: Uma tabela chamada |
| <code>dataset1</code>. |
| </li> |
| <li> |
| <code>content://com.example.app.provider/table3</code>: Uma tabela chamada <code>table3</code>. |
| </li> |
| </ul> |
| <p> |
| O provedor também reconhece essas URIs de conteúdo se elas tiverem um ID de linha anexado, como |
| <code>content://com.example.app.provider/table3/1</code> para a linha identificada por |
| <code>1</code> em <code>table3</code>. |
| </p> |
| <p> |
| Os seguintes padrões de URI de conteúdo seriam possíveis: |
| </p> |
| <dl> |
| <dt> |
| <code>content://com.example.app.provider/*</code> |
| </dt> |
| <dd> |
| Corresponde a qualquer URI de conteúdo no provedor. |
| </dd> |
| <dt> |
| <code>content://com.example.app.provider/table2/*</code>: |
| </dt> |
| <dd> |
| Corresponde a uma URI de conteúdo das tabelas <code>dataset1</code> |
| e <code>dataset2</code>, mas não a URIs de conteúdo de <code>table1</code> |
| nem <code>table3</code>. |
| </dd> |
| <dt> |
| <code>content://com.example.app.provider/table3/#</code>: Corresponde a uma URI de conteúdo |
| para linhas exclusivas em <code>table3</code>, como |
| <code>content://com.example.app.provider/table3/6</code> da linha identificada por |
| <code>6</code>. |
| </dt> |
| </dl> |
| <p> |
| O fragmento de código a seguir mostra como funcionam os métodos em {@link android.content.UriMatcher}. |
| Esse código identifica URIs para toda uma tabela, diferentemente das URIs |
| para uma linha exclusiva, usando o padrão de URI de conteúdo |
| <code>content://<authority>/<path></code> para tabelas e |
| <code>content://<authority>/<path>/<id></code> para linhas exclusivas. |
| </p> |
| <p> |
| O método {@link android.content.UriMatcher#addURI(String, String, int) addURI()} mapeia |
| uma autoridade e um caminho como um valor de número inteiro. O método {@link android.content.UriMatcher#match(Uri) |
| match()} retorna o valor de número inteiro para a URI. Uma declaração <code>switch</code> |
| escolhe entre consultar a tabela inteira e consultar um único registro: |
| </p> |
| <pre class="prettyprint"> |
| public class ExampleProvider extends ContentProvider { |
| ... |
| // Creates a UriMatcher object. |
| private static final UriMatcher sUriMatcher; |
| ... |
| /* |
| * The calls to addURI() go here, for all of the content URI patterns that the provider |
| * should recognize. For this snippet, only the calls for table 3 are shown. |
| */ |
| ... |
| /* |
| * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used |
| * in the path |
| */ |
| sUriMatcher.addURI("com.example.app.provider", "table3", 1); |
| |
| /* |
| * Sets the code for a single row to 2. In this case, the "#" wildcard is |
| * used. "content://com.example.app.provider/table3/3" matches, but |
| * "content://com.example.app.provider/table3 doesn't. |
| */ |
| sUriMatcher.addURI("com.example.app.provider", "table3/#", 2); |
| ... |
| // Implements ContentProvider.query() |
| public Cursor query( |
| Uri uri, |
| String[] projection, |
| String selection, |
| String[] selectionArgs, |
| String sortOrder) { |
| ... |
| /* |
| * Choose the table to query and a sort order based on the code returned for the incoming |
| * URI. Here, too, only the statements for table 3 are shown. |
| */ |
| switch (sUriMatcher.match(uri)) { |
| |
| |
| // If the incoming URI was for all of table3 |
| case 1: |
| |
| if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC"; |
| break; |
| |
| // If the incoming URI was for a single row |
| case 2: |
| |
| /* |
| * Because this URI was for a single row, the _ID value part is |
| * present. Get the last path segment from the URI; this is the _ID value. |
| * Then, append the value to the WHERE clause for the query |
| */ |
| selection = selection + "_ID = " uri.getLastPathSegment(); |
| break; |
| |
| default: |
| ... |
| // If the URI is not recognized, you should do some error handling here. |
| } |
| // call the code to actually do the query |
| } |
| </pre> |
| <p> |
| Outra classe, {@link android.content.ContentUris}, fornece métodos convenientes para trabalhar |
| com a parte <code>id</code> das URIs de conteúdo. As classes {@link android.net.Uri} |
| e {@link android.net.Uri.Builder} contêm métodos convenientes para analisar objetos |
| {@link android.net.Uri} existentes e criar novos. |
| </p> |
| |
| <!-- Implementing the ContentProvider class --> |
| <h2 id="ContentProvider">Implementação da classe ContentProvider</h2> |
| <p> |
| A instância {@link android.content.ContentProvider} gerencia o acesso |
| a um conjunto de dados estruturado lidando com solicitações de outros aplicativos. Todas as formas |
| de acesso ocasionalmente chamam {@link android.content.ContentResolver} que, em seguida, chama um método |
| concreto de {@link android.content.ContentProvider} para obter acesso. |
| </p> |
| <h3 id="RequiredAccess">Métodos obrigatórios</h3> |
| <p> |
| A classe abstrata {@link android.content.ContentProvider} define seis métodos abstratos |
| que devem ser implementados como parte das subclasses concretas. Todos esses métodos, exceto |
| {@link android.content.ContentProvider#onCreate() onCreate()}, são chamados por um aplicativo cliente |
| que está tentando acessar seu provedor de conteúdo: |
| </p> |
| <dl> |
| <dt> |
| {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) |
| query()} |
| </dt> |
| <dd> |
| Recupere dados do provedor. Use os argumentos para selecionar a tabela |
| para consultar as linhas e colunas a retornar e a ordem de classificação do resultado. |
| Retorne os dados como um objeto {@link android.database.Cursor}. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} |
| </dt> |
| <dd> |
| Insira uma nova linha no provedor. Use os argumentos para selecionar |
| a tabela de destino e obter os valores de coluna a usar. Retorne uma URI de conteúdo para |
| a linha recentemente inserida. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) |
| update()} |
| </dt> |
| <dd> |
| Atualize as linhas existentes no provedor. Use os argumentos para selecionar a tabela e linhas |
| para atualizar e obter os valores de coluna atualizados. Retorne o número de linhas atualizadas. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} |
| </dt> |
| <dd> |
| Exclua linhas do provedor. Use os argumentos para selecionar a tabela e as linhas |
| a excluir. Retorne o número de linhas excluídas. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#getType(Uri) getType()} |
| </dt> |
| <dd> |
| Retorne o tipo MIME correspondente a uma URI de conteúdo. Esse método é descrito com mais |
| detalhes na seção <a href="#MIMETypes">Implementação de tipos MIME do Provedor de Conteúdo</a>. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#onCreate() onCreate()} |
| </dt> |
| <dd> |
| Inicializar o provedor. O sistema Android chama esse método imediatamente |
| após criar o provedor. Observe que o provedor não é criado até que |
| um objeto {@link android.content.ContentResolver} tente acessá-lo. |
| </dd> |
| </dl> |
| <p> |
| Observe que esses métodos têm a mesma assinatura dos métodos |
| {@link android.content.ContentResolver} de mesmo nome. |
| </p> |
| <p> |
| A implementação desses métodos deve levar em conta o seguinte: |
| </p> |
| <ul> |
| <li> |
| Todos esses métodos, exceto {@link android.content.ContentProvider#onCreate() onCreate()}, |
| podem ser chamados por diversos encadeamentos simultaneamente, então devem ter encadeamento seguro. Para saber |
| mais sobre encadeamentos múltiplos, consulte o tópico |
| <a href="{@docRoot}guide/components/processes-and-threads.html"> |
| Processos e encadeamentos</a>. |
| </li> |
| <li> |
| Evite realizar longas operações em {@link android.content.ContentProvider#onCreate() |
| onCreate()}. Adie tarefas de inicialização até que sejam realmente necessárias. |
| A seção <a href="#OnCreate">Implementação do método onCreate()</a> |
| aborda o assunto mais detalhadamente. |
| </li> |
| <li> |
| Embora seja preciso implementar esses métodos, o código não precisa fazer nada além |
| de retornar o tipo de dados esperado. Por exemplo: você pode querer evitar que outros aplicativos |
| insiram dados em algumas tabelas. Para tanto, pode-se ignorar a chamada de |
| {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} e retornar |
| 0. |
| </li> |
| </ul> |
| <h3 id="Query">Implementação do método query()</h3> |
| <p> |
| |
| O método {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) |
| ContentProvider.query()} precisa retornar um objeto {@link android.database.Cursor} ou, se |
| falhar, gerar uma {@link java.lang.Exception}. Se você estiver usando um banco de dados SQLite |
| como armazenamento de dados, pode simplesmente retornar o {@link android.database.Cursor} retornado |
| por um dos métodos <code>query()</code> da classe {@link android.database.sqlite.SQLiteDatabase}. |
| Se a consulta não corresponder a nenhuma linha, deve-se retornar uma instância {@link android.database.Cursor} |
| cujo método {@link android.database.Cursor#getCount()} retorne 0. |
| Deve-se retornar <code>null</code> somente se ocorrer um erro interno durante o processo de consulta. |
| </p> |
| <p> |
| Se você não estiver usando um banco de dados SQLite como modo de armazenamento de dados, use uma das subclasses concretas |
| de {@link android.database.Cursor}. Por exemplo, a classe {@link android.database.MatrixCursor} |
| implementa um cursor em que cada linha é uma matriz de {@link java.lang.Object}. Com essa classe, |
| use {@link android.database.MatrixCursor#addRow(Object[]) addRow()} para adicionar uma nova linha. |
| </p> |
| <p> |
| Lembre-se de que o sistema Android deve ser capaz de se comunicar com {@link java.lang.Exception} |
| entre limites de processo. O Android pode fazer isso para as exceções a seguir, que podem ser úteis |
| para tratar de erros de consulta: |
| </p> |
| <ul> |
| <li> |
| {@link java.lang.IllegalArgumentException} (é possível escolher lançar isso se o provedor |
| receber uma URI de conteúdo inválida) |
| </li> |
| <li> |
| {@link java.lang.NullPointerException} |
| </li> |
| </ul> |
| <h3 id="Insert">Implementação do método insert()</h3> |
| <p> |
| O método {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} adiciona |
| uma nova linha à tabela apropriada usando os valores no argumento |
| {@link android.content.ContentValues}. Se um nome de coluna não estiver no argumento {@link android.content.ContentValues}, |
| talvez seja necessário fornecer um valor padrão para ele tanto no código do provedor quanto no esquema |
| do banco de dados. |
| </p> |
| <p> |
| Esse método deve retornar a URI de conteúdo da nova linha. Para construir isso, anexe o valor <code>_ID</code> |
| da nova linha (ou outra chave principal) à URI de conteúdo da tabela usando |
| {@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()}. |
| </p> |
| <h3 id="Delete">Implementação do método delete()</h3> |
| <p> |
| O método {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} |
| não precisa excluir linhas fisicamente do armazenamento de dados. Se você estiver usando um adaptador de sincronização |
| com o provedor, considere marcar uma linha excluída |
| com um sinalizador "excluir" em vez de removê-la totalmente. O adaptador de sincronização pode |
| verificar se há linhas excluídas e removê-las do servidor antes de excluí-las do provedor. |
| </p> |
| <h3 id="Update">Implementação do método update()</h3> |
| <p> |
| O método {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) |
| update()} usa o mesmo argumento {@link android.content.ContentValues} usado por |
| {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}, e os |
| mesmos argumentos <code>selection</code> e <code>selectionArgs</code> usados por |
| {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} e |
| {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) |
| ContentProvider.query()}. Isso deve permitir a reutilização do código entre esses métodos. |
| </p> |
| <h3 id="OnCreate">Implementação do método onCreate()</h3> |
| <p> |
| O sistema Android chama {@link android.content.ContentProvider#onCreate() |
| onCreate()} quando inicia o provedor. Nesse método, devem-se realizar apenas tarefas de inicialização |
| de execução rápida e adiar a criação do banco de dados e o carregamento dos dados até que o provedor |
| receba efetivamente uma solicitação de acesso aos dados. Se houver tarefas longas |
| em {@link android.content.ContentProvider#onCreate() onCreate()}, a inicialização do provedor |
| ficará lenta. Consequentemente, isso diminuirá a rapidez da resposta do provedor |
| a outros aplicativos. |
| </p> |
| <p> |
| Por exemplo: se você estiver usando um banco de dados SQLite, é possível criar |
| um novo objeto {@link android.database.sqlite.SQLiteOpenHelper} |
| em {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} |
| e, em seguida, criar as tabelas SQL na primeira vez em que o banco de dados for aberto. Para facilitar isso, |
| a primeira vez que chamar {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase |
| getWritableDatabase()}, ele automaticamente chamará |
| o método {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) |
| SQLiteOpenHelper.onCreate()} |
| </p> |
| <p> |
| Os dois fragmentos a seguir demonstram a interação |
| entre {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} |
| e {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) |
| SQLiteOpenHelper.onCreate()}. O primeiro fragmento é a implementação de |
| {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}. |
| </p> |
| <pre class="prettyprint"> |
| public class ExampleProvider extends ContentProvider |
| |
| /* |
| * Defines a handle to the database helper object. The MainDatabaseHelper class is defined |
| * in a following snippet. |
| */ |
| private MainDatabaseHelper mOpenHelper; |
| |
| // Defines the database name |
| private static final String DBNAME = "mydb"; |
| |
| // Holds the database object |
| private SQLiteDatabase db; |
| |
| public boolean onCreate() { |
| |
| /* |
| * Creates a new helper object. This method always returns quickly. |
| * Notice that the database itself isn't created or opened |
| * until SQLiteOpenHelper.getWritableDatabase is called |
| */ |
| mOpenHelper = new MainDatabaseHelper( |
| getContext(), // the application context |
| DBNAME, // the name of the database) |
| null, // uses the default SQLite cursor |
| 1 // the version number |
| ); |
| |
| return true; |
| } |
| |
| ... |
| |
| // Implements the provider's insert method |
| public Cursor insert(Uri uri, ContentValues values) { |
| // Insert code here to determine which table to open, handle error-checking, and so forth |
| |
| ... |
| |
| /* |
| * Gets a writeable database. This will trigger its creation if it doesn't already exist. |
| * |
| */ |
| db = mOpenHelper.getWritableDatabase(); |
| } |
| } |
| </pre> |
| <p> |
| O próximo fragmento é a implementação de |
| {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) |
| SQLiteOpenHelper.onCreate()}, inclusive uma classe auxiliar: |
| </p> |
| <pre class="prettyprint"> |
| ... |
| // A string that defines the SQL statement for creating a table |
| private static final String SQL_CREATE_MAIN = "CREATE TABLE " + |
| "main " + // Table's name |
| "(" + // The columns in the table |
| " _ID INTEGER PRIMARY KEY, " + |
| " WORD TEXT" |
| " FREQUENCY INTEGER " + |
| " LOCALE TEXT )"; |
| ... |
| /** |
| * Helper class that actually creates and manages the provider's underlying data repository. |
| */ |
| protected static final class MainDatabaseHelper extends SQLiteOpenHelper { |
| |
| /* |
| * Instantiates an open helper for the provider's SQLite data repository |
| * Do not do database creation and upgrade here. |
| */ |
| MainDatabaseHelper(Context context) { |
| super(context, DBNAME, null, 1); |
| } |
| |
| /* |
| * Creates the data repository. This is called when the provider attempts to open the |
| * repository and SQLite reports that it doesn't exist. |
| */ |
| public void onCreate(SQLiteDatabase db) { |
| |
| // Creates the main table |
| db.execSQL(SQL_CREATE_MAIN); |
| } |
| } |
| </pre> |
| |
| |
| <!-- Implementing ContentProvider MIME Types --> |
| <h2 id="MIMETypes">Implementação de tipos MIME de ContentProvider</h2> |
| <p> |
| A classe {@link android.content.ContentProvider} tem dois métodos para retornar tipos MIME: |
| </p> |
| <dl> |
| <dt> |
| {@link android.content.ContentProvider#getType(Uri) getType()} |
| </dt> |
| <dd> |
| Um dos métodos obrigatórios que devem ser implementados em qualquer provedor. |
| </dd> |
| <dt> |
| {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()} |
| </dt> |
| <dd> |
| Um método que deve ser implementado se o provedor fornecer arquivos. |
| </dd> |
| </dl> |
| <h3 id="TableMIMETypes">Tipos MIME para tabelas</h3> |
| <p> |
| O método {@link android.content.ContentProvider#getType(Uri) getType()} retorna |
| uma {@link java.lang.String} em formato MIME que descreve o tipo de dados retornado pelo argumento |
| da URI de conteúdo. O argumento {@link android.net.Uri} pode ser um padrão em vez de uma URI específica; |
| nesse caso, deve-se retornar o tipo de dados associado a URIs de conteúdo que correspondam |
| ao padrão. |
| </p> |
| <p> |
| Para tipos de dados comuns como texto, HTML ou JPEG, |
| {@link android.content.ContentProvider#getType(Uri) getType()} deve retornar o tipo MIME |
| padrão daqueles dados. Há uma lista completa desse tipos de padrão |
| no site de |
| <a href="http://www.iana.org/assignments/media-types/index.htm">Tipos de mídia MIME IANA</a>. |
| </p> |
| <p> |
| Para obter URIs de conteúdo que apontam para uma linha ou linhas de dados de tabela, |
| {@link android.content.ContentProvider#getType(Uri) getType()} deve retornar |
| um tipo MIME no formato MIME específico do fornecedor do Android: |
| </p> |
| <ul> |
| <li> |
| Parte do tipo: <code>vnd</code> |
| </li> |
| <li> |
| Parte do subtipo: |
| <ul> |
| <li> |
| Se um padrão de URI se destinar a uma única linha: <code>android.cursor.<strong>item</strong>/</code> |
| </li> |
| <li> |
| Se um padrão de URI se destinar a mais de uma linha: <code>android.cursor.<strong>dir</strong>/</code> |
| </li> |
| </ul> |
| </li> |
| <li> |
| Parte específica do provedor: <code>vnd.<name></code>.<code><type></code> |
| <p> |
| Fornecem-se <code><name></code> e o <code><type></code>. |
| O valor <code><name></code> deve ser globalmente exclusivo |
| e o <code><type></code> deve ser exclusivo para o padrão de URI |
| correspondente. Uma boa escolha para <code><name></code> é o nome da empresa |
| ou alguma parte do nome do pacote do Android do seu aplicativo. Uma boa escolha para |
| <code><type></code> é uma string que identifique a tabela associada |
| à URI. |
| </p> |
| |
| </li> |
| </ul> |
| <p> |
| Por exemplo: se a autoridade de um provedor |
| for <code>com.example.app.provider</code> e ele expuser uma tabela chamada |
| <code>table1</code>, o tipo MIME de diversas linhas em <code>table1</code> será: |
| </p> |
| <pre> |
| vnd.android.cursor.<strong>dir</strong>/vnd.com.example.provider.table1 |
| </pre> |
| <p> |
| Para uma única linha de <code>table1</code>, o tipo MIME será: |
| </p> |
| <pre> |
| vnd.android.cursor.<strong>item</strong>/vnd.com.example.provider.table1 |
| </pre> |
| <h3 id="FileMIMETypes">Tipos MIME para arquivos</h3> |
| <p> |
| Se o provedor oferecer arquivos, implemente |
| {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}. |
| O método retorna uma matriz {@link java.lang.String} de tipos MIME para os arquivos que o provedor |
| pode retornar de uma dada URI de conteúdo. É preciso filtrar os tipos MIME oferecidos pelo argumento do filtro |
| de tipo MIME para retornar somente os tipos MIME que o cliente quer tratar. |
| </p> |
| <p> |
| Por exemplo: considere um provedor que ofereça imagens de foto como arquivos em formatos <code>.jpg</code>, |
| <code>.gif</code> e <code>.png</code>. |
| Se um aplicativo chama {@link android.content.ContentResolver#getStreamTypes(Uri, String) |
| ContentResolver.getStreamTypes()} com a string de filtro <code>image/*</code> (algo que |
| seja uma "imagem"), |
| o método {@link android.content.ContentProvider#getStreamTypes(Uri, String) |
| ContentProvider.getStreamTypes()} deve retornar a matriz: |
| </p> |
| <pre> |
| { "image/jpeg", "image/png", "image/gif"} |
| </pre> |
| <p> |
| Se o aplicativo estiver interessado apenas em arquivos <code>.jpg</code>, ele pode chamar |
| {@link android.content.ContentResolver#getStreamTypes(Uri, String) |
| ContentResolver.getStreamTypes()} com a string de filtro <code>*\/jpeg</code> |
| e {@link android.content.ContentProvider#getStreamTypes(Uri, String) |
| ContentProvider.getStreamTypes()} deve retornar: |
| <pre> |
| {"image/jpeg"} |
| </pre> |
| <p> |
| Se o provedor não oferecer nenhum tipo MIME solicitado na string de filtro, |
| {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()} |
| deve retornar <code>null</code>. |
| </p> |
| |
| |
| <!-- Implementing a Contract Class --> |
| <h2 id="ContractClass">Implementação de uma classe de contrato</h2> |
| <p> |
| Uma classe de contrato é uma classe <code>public final</code> que contém definições de constantes para |
| os nomes de coluna das URIs, dos tipos MIME e de outros metadados que pertencem ao provedor. A classe |
| estabelece um contrato entre o provedor e outros aplicativos, garantindo que o provedor |
| possa ser corretamente acessado mesmo se houver mudanças nos valores atuais de URIs, nomes de coluna |
| etc. |
| </p> |
| <p> |
| As classes de contrato também ajudam os desenvolvedores porque normalmente suas constantes têm nomes mnemônicos e, |
| por isso, os desenvolvedores têm menos chance de usar valores incorretos para nomes de coluna ou URIs. Já que é |
| uma classe, ela pode conter documentação Javadoc. Ambientes de desenvolvimento integrados, como |
| o Eclipse, podem preencher automaticamente os nomes de constantes da classe de contrato e exibir Javadoc para |
| as constantes. |
| </p> |
| <p> |
| Os desenvolvedores não podem acessar o arquivo de classe da classe de contrato do aplicativo, mas podem |
| compilá-lo estaticamente no aplicativo a partir de um arquivo <code>.jar</code> que você fornece. |
| </p> |
| <p> |
| A classe {@link android.provider.ContactsContract} e classes aninhadas são exemplos |
| de classes de contrato. |
| </p> |
| <h2 id="Permissions">Implementação de permissões do Provedor de Conteúdo</h2> |
| <p> |
| Permissões e acesso, para todos os aspectos do sistema Android, são descritos detalhadamente no |
| tópico <a href="{@docRoot}guide/topics/security/security.html">Permissões e segurança</a>. |
| O tópico <a href="{@docRoot}guide/topics/data/data-storage.html">Armazenamento de dados</a> também |
| descreve segurança e permissões em vigor para diversos tipos de armazenamento. |
| Em resumo, os pontos importantes são: |
| </p> |
| <ul> |
| <li> |
| Por padrão, arquivos de dados armazenados no armazenamento interno do dispositivo são privados em relação |
| ao aplicativo e ao provedor. |
| </li> |
| <li> |
| Os bancos de dados {@link android.database.sqlite.SQLiteDatabase} criados são privados em relação |
| ao aplicativo e ao provedor. |
| </li> |
| <li> |
| Por padrão, arquivos de dados salvos em armazenamentos externos são <em>públicos</em> |
| e <em>legíveis para todos</em>. Não é possível usar um provedor de conteúdo para restringir o acesso a arquivos |
| em um armazenamento externo porque outros aplicativos podem usar chamadas de outra API para lê-los e gravar neles. |
| </li> |
| <li> |
| O método que chama a abertura ou criação de arquivos ou bancos de dados SQLite no armazenamento |
| interno do seu dispositivo podem fornecer acesso de leitura e gravação a todos os outros aplicativos. Se você |
| usar um arquivo ou banco de dados interno como o repositório do provedor e conceder-lhe |
| acesso "legível para todos" ou "gravável por todos", as permissões definidas para o provedor |
| no manifesto não protegerão os dados. O acesso padrão de arquivos e bancos de dados |
| no armazenamento interno é "privado" e, para o repositório do provedor, não é recomendável alterar isso. |
| </li> |
| </ul> |
| <p> |
| Se você deseja usar permissões do provedor de conteúdo para controlar o acesso aos dados, deve |
| armazená-los em arquivos internos, bancos de dados SQLite ou em "nuvem" (por exemplo, |
| em um servidor remoto) e mantê-los privados em relação ao aplicativo. |
| </p> |
| <h3>Implementação de permissões</h3> |
| <p> |
| Todos os aplicativos podem ler ou gravar no provedor, mesmo que os dados em questão |
| sejam privados porque, por padrão, o provedor não tem permissões definidas. Para mudar isso, |
| defina permissões do provedor no arquivo de manifesto por meio de atributos ou elementos |
| filho do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. É possível definir permissões que se apliquem a todo o provedor, |
| a determinadas tabelas, a registros específicos ou a todos os três. |
| </p> |
| <p> |
| As permissões são definidas para o provedor com um ou mais |
| elementos <code><a href="{@docRoot}guide/topics/manifest/permission-element.html"> |
| <permission></a></code> no arquivo de manifesto. Para tornar |
| a permissão exclusiva para o provedor, use escopo de estilo Java para |
| o atributo <code><a href="{@docRoot}guide/topics/manifest/permission-element.html#nm"> |
| android:name</a></code>. Por exemplo: nomeie a permissão de leitura |
| <code>com.example.app.provider.permission.READ_PROVIDER</code>. |
| |
| </p> |
| <p> |
| A lista a seguir descreve o escopo de permissões do provedor, começando |
| com as permissões que se aplicam a todo o provedor e seguindo para as mais específicas. |
| Permissões mais específicas têm precedência sobre as de escopo maior: |
| </p> |
| <dl> |
| <dt> |
| Única permissão de leitura e gravação no nível do provedor |
| </dt> |
| <dd> |
| Uma permissão que controla os acessos de leitura e gravação a todo o provedor, especificada |
| com o atributo <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn"> |
| android:permission</a></code> |
| do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. |
| </dd> |
| <dt> |
| Permissões de leitura e gravação separadas no nível do provedor |
| </dt> |
| <dd> |
| Uma permissão de leitura e uma permissão de gravação para todo o provedor. São especificadas |
| com os atributos <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn"> |
| android:readPermission</a></code> |
| e <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn"> |
| android:writePermission</a></code> |
| do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. Elas têm precedência sobre a permissão exigida |
| por <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn"> |
| android:permission</a></code>. |
| </dd> |
| <dt> |
| Permissão no nível do caminho |
| </dt> |
| <dd> |
| Permissão de leitura, gravação ou leitura/gravação para uma URI de conteúdo no provedor. Especifica-se |
| cada URI que se deseja controlar |
| com um elemento filho <code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html"> |
| <path-permission></a></code> |
| do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. Para cada URI de conteúdo, pode-se especificar |
| uma permissão de leitura/gravação, uma permissão de leitura, uma permissão de gravação ou as três. As permissões |
| de leitura e gravação têm precedência sobre a permissão de leitura/gravação. Além disso, |
| permissões no nível do caminho têm precedência sobre permissões no nível do provedor. |
| </dd> |
| <dt> |
| Permissão temporária |
| </dt> |
| <dd> |
| Nível de permissão que concede acesso temporário a um aplicativo mesmo que ele |
| não tenha as permissões normalmente exigidas. O recurso de acesso |
| temporário reduz o número de permissões que um aplicativo deve solicitar |
| no manifesto. Ao ativar permissões temporárias, os únicos aplicativos que precisam de |
| permissões "permanentes" para seu provedor são os que têm acesso contínuo |
| a todos os dados. |
| <p> |
| Considere as permissões necessárias para implementar um provedor e um aplicativo de e-mail |
| ao permitir um aplicativo visualizador de imagens externas para exibir anexos de fotos |
| do provedor. Para conceder o acesso necessário ao visualizador de imagens sem as permissões exigidas, |
| configure permissões temporárias das URIs de conteúdo de fotos. Projete o aplicativo de e-mail |
| para que, quando o usuário quiser exibir uma foto, o aplicativo envie uma intenção |
| com a URI de conteúdo da foto e sinalizadores de permissão para o visualizador de imagens. O visualizador de imagens poderá, |
| então, consultar o provedor de e-mail para recuperar a foto mesmo que ele |
| não tenha a permissão normal de leitura para o provedor. |
| </p> |
| <p> |
| Para ativar permissões temporárias, defina |
| o atributo <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn"> |
| android:grantUriPermissions</a></code> |
| do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code> ou adicione um ou mais |
| elementos filhos <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"> |
| <grant-uri-permission></a></code> |
| ao elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. Se forem usadas permissões temporárias, será necessário chamar |
| {@link android.content.Context#revokeUriPermission(Uri, int) |
| Context.revokeUriPermission()} sempre que remover suporte a URI de conteúdo do |
| provedor, e a URI de conteúdo será associada a uma permissão temporária. |
| </p> |
| <p> |
| O valor do atributo determina o nível de acessibilidade do provedor. |
| Se o atributo estiver definido como <code>true</code>, o sistema concederá permissão |
| temporária a todo o provedor, sobrepondo todas as outras permissões exigidas |
| pelas permissões no nível do provedor ou no nível do caminho. |
| </p> |
| <p> |
| Se esse sinalizador estiver definido como <code>false</code>, será necessário adicionar |
| elementos filhos <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"> |
| <grant-uri-permission></a></code> |
| ao elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. Cada elemento filho especifica a URI ou URIs |
| de conteúdo para as quais o acesso temporário é concedido. |
| </p> |
| <p> |
| Para delegar o acesso temporário a um aplicativo, a intenção deve conter |
| os sinalizadores {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}, |
| {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} ou ambos. Eles |
| são definidos com o método {@link android.content.Intent#setFlags(int) setFlags()}. |
| </p> |
| <p> |
| Se o atributo <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn"> |
| android:grantUriPermissions</a></code> não estiver presente, presume-se que ele seja |
| <code>false</code>. |
| </p> |
| </dd> |
| </dl> |
| |
| |
| |
| <!-- The Provider Element --> |
| <h2 id="ProviderElement">O elemento <provider></h2> |
| <p> |
| Como os componentes {@link android.app.Activity} e {@link android.app.Service}, |
| a subclasse de {@link android.content.ContentProvider} |
| deve ser definida no arquivo de manifesto do aplicativo |
| pelo elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. O sistema Android obtém as seguintes informações |
| do elemento: |
| <dl> |
| <dt> |
| Autoridade |
| (<a href="{@docRoot}guide/topics/manifest/provider-element.html#auth">{@code |
| android:authorities}</a>) |
| </dt> |
| <dd> |
| Nomes simbólicos que identificam todo o provedor dentro do sistema. Esse |
| atributo é descrito com mais detalhes na seção |
| <a href="#ContentURI">Projeto de URIs de conteúdo</a>. |
| </dd> |
| <dt> |
| Nome da classe do provedor |
| (<code> |
| <a href="{@docRoot}guide/topics/manifest/provider-element.html#nm">android:name</a> |
| </code>) |
| </dt> |
| <dd> |
| A classe que implementa {@link android.content.ContentProvider}. Esta classe é |
| abordada com mais detalhes na seção |
| <a href="#ContentProvider">Implementação da classe ContentProvider</a>. |
| </dd> |
| <dt> |
| Permissões |
| </dt> |
| <dd> |
| Atributos que especificam as permissões que outros aplicativos precisam ter para acessar |
| os dados do provedor: |
| <ul> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn"> |
| android:grantUriPermssions</a></code>: Sinalizador de permissão temporária. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn"> |
| android:permission</a></code>: Permissão única de leitura/gravação por todo o provedor. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn"> |
| android:readPermission</a></code>: Permissão de leitura por todo o provedor. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn"> |
| android:writePermission</a></code>: Permissão de gravação por todo o provedor. |
| </li> |
| </ul> |
| <p> |
| As permissões e os atributos correspondentes são abordados com mais |
| detalhes na seção |
| <a href="#Permissions">Implementação de permissões do Provedor de conteúdo</a>. |
| </p> |
| </dd> |
| <dt> |
| Atributos de início e controle |
| </dt> |
| <dd> |
| Esses atributos determinam como e quando o sistema Android inicia o provedor, |
| as características do processo do provedor e outras configurações de tempo de execução: |
| <ul> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#enabled"> |
| android:enabled</a></code>: sinalizador que permite ao sistema iniciar o provedor. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#exported"> |
| android:exported</a></code>: sinalizador que permite a outros aplicativos usarem esse provedor. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#init"> |
| android:initOrder</a></code>: a ordem em que esse provedor deve ser iniciado, |
| relativa a outros provedores no mesmo processo. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#multi"> |
| android:multiProcess</a></code>: sinalizador que permite ao sistema iniciar o provedor |
| no mesmo processo que o cliente chama. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#proc"> |
| android:process</a></code>: o nome do processo em que o provedor deve |
| ser executado. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#sync"> |
| android:syncable</a></code>: sinalizador que indica que os dados do provedor devem ser |
| sincronizados com os dados em um servidor. |
| </li> |
| </ul> |
| <p> |
| os atributos estão totalmente documentados no tópico do guia de desenvolvimento |
| do elemento |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. |
| </p> |
| </dd> |
| <dt> |
| Atributos informacionais |
| </dt> |
| <dd> |
| Um ícone e um rótulo opcionais para o provedor: |
| <ul> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#icon"> |
| android:icon</a></code>: um recurso desenhável contendo um ícone para o provedor. |
| O ícone aparece próximo ao rótulo do provedor na lista de aplicativos |
| em <em>Configurações</em> > <em>Aplicativos</em> > <em>Todos</em>. |
| </li> |
| <li> |
| <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#label"> |
| android:label</a></code>: um rótulo informacional que descreve o provedor, |
| seus dados ou ambos. O rótulo aparece na lista de aplicativos |
| em <em>Configurações</em> > <em>Aplicativos</em> > <em>Todos</em>. |
| </li> |
| </ul> |
| <p> |
| Os atributos estão totalmente documentados no tópico do guia de desenvolvimento |
| do elemento <code><a href="{@docRoot}guide/topics/manifest/provider-element.html"> |
| <provider></a></code>. |
| </p> |
| </dd> |
| </dl> |
| |
| <!-- Intent Access --> |
| <h2 id="Intents">Intenções e acesso a dados</h2> |
| <p> |
| Os aplicativos podem acessar um provedor de conteúdo indiretamente com uma {@link android.content.Intent}. |
| O aplicativo não chama nenhum método de {@link android.content.ContentResolver} |
| nem de {@link android.content.ContentProvider}. Em vez disso, ele envia uma intenção que inicia uma atividade, |
| que, em geral, é parte do aplicativo do próprio provedor. A atividade de destino é responsável |
| pela recuperação e exibição dos dados na IU. Conforme a ação na intenção, |
| a atividade de destino também pode levar o usuário a realizar modificações nos dados do provedor. |
| Uma intenção também pode conter dados "extras" que a atividade de destino exibe |
| na IU; o usuário terá, então, a opção de alterar esses dados antes de usá-los para modificar |
| os dados no provedor. |
| </p> |
| <p> |
| |
| </p> |
| <p> |
| Pode ser necessário usar acesso de intenções para ajudar a garantir a integridade deles. O provedor pode depender |
| de ter dados inseridos, atualizados e excluídos de acordo com a lógica de negócio rigorosamente definida. Se |
| for o caso, a permissão para que outros aplicativos modifiquem os dados diretamente pode levar |
| à invalidação dos dados. Se você deseja que os desenvolvedores usem o acesso via intenções, certifique-se de documentá-lo minuciosamente. |
| Explique por que o acesso via intenções pela IU do aplicativo é melhor do que tentar |
| modificar os dados com códigos. |
| </p> |
| <p> |
| O tratamento das intenções recebidas com a intenção de modificar os dados do provedor não é diferente |
| de tratar de outras intenções. Para saber mais sobre o uso de intenções, leia o tópico |
| <a href="{@docRoot}guide/components/intents-filters.html">Intenções e filtros de intenções</a>. |
| </p> |