| page.title=Provedor de Contatos |
| @jd:body |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>Visualização rápida</h2> |
| <ul> |
| <li>Repositório de informações sobre pessoas do Android.</li> |
| <li> |
| Sincronização com a web. |
| </li> |
| <li> |
| Integração de dados de fluxos sociais. |
| </li> |
| </ul> |
| <h2>Neste documento</h2> |
| <ol> |
| <li> |
| <a href="#InformationTypes">Organização do Provedor de Contatos</a> |
| </li> |
| <li> |
| <a href="#RawContactBasics">Contatos brutos</a> |
| </li> |
| <li> |
| <a href="#DataBasics">Dados</a> |
| </li> |
| <li> |
| <a href="#ContactBasics">Contatos</a> |
| </li> |
| <li> |
| <a href="#Sources">Dados de adaptadores de sincronização</a> |
| </li> |
| <li> |
| <a href="#Permissions">Permissões necessárias</a> |
| </li> |
| <li> |
| <a href="#UserProfile">O perfil do usuário</a> |
| </li> |
| <li> |
| <a href="#ContactsProviderMetadata">Metadados do Provedor de Contatos</a> |
| </li> |
| <li> |
| <a href="#Access">Acesso ao Provedor de Contatos</a> |
| <li> |
| </li> |
| <li> |
| <a href="#SyncAdapters">Adaptadores de sincronização do Provedor de Contatos</a> |
| </li> |
| <li> |
| <a href="#SocialStream">Dados de fluxos sociais</a> |
| </li> |
| <li> |
| <a href="#AdditionalFeatures">Recursos adicionais do Provedor de Contatos</a> |
| </li> |
| </ol> |
| <h2>Classes principais</h2> |
| <ol> |
| <li>{@link android.provider.ContactsContract.Contacts}</li> |
| <li>{@link android.provider.ContactsContract.RawContacts}</li> |
| <li>{@link android.provider.ContactsContract.Data}</li> |
| <li>{@code android.provider.ContactsContract.StreamItems}</li> |
| </ol> |
| <h2>Exemplos relacionados</h2> |
| <ol> |
| <li> |
| <a href="{@docRoot}resources/samples/ContactManager/index.html"> |
| Gerente de contatos |
| </a> |
| </li> |
| <li> |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html"> |
| Exemplo de adaptador de sincronização</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> |
| </ol> |
| </div> |
| </div> |
| <p> |
| O Provedor de Contatos é um componente poderoso e flexível do Android que gerencia |
| o principal repositório de dados sobre pessoas do dispositivo. O Provedor de Contatos é a fonte dos dados |
| vistos nos aplicativos de contatos do dispositivo e, por ele, também é possível acessar os dados |
| no próprio aplicativo e transferi-los entre o dispositivo e serviços on-line. O provedor fornece |
| uma grande variedade de fontes de dados e tenta gerenciar o máximo de dados possíveis para cada pessoa, |
| uma vez que organizá-los é algo complexo. Por isso, a API do provedor contém |
| um conjunto extensivo de classes e interfaces de contrato que facilitam a recuperação e a modificação |
| dos dados. |
| </p> |
| <p> |
| Este guia descreve o seguinte: |
| </p> |
| <ul> |
| <li> |
| A estrutura básica do provedor. |
| </li> |
| <li> |
| Como recuperar dados por um provedor. |
| </li> |
| <li> |
| Como modificar dados no provedor. |
| </li> |
| <li> |
| Como criar um adaptador de sincronização para sincronizar dados do servidor com |
| o Provedor de Contatos. |
| </li> |
| </ul> |
| <p> |
| Este guia considera que o leitor conhece os preceitos dos provedores de conteúdo do Android. Para saber mais |
| sobre provedores de conteúdo do Android, leia o guia |
| <a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a>. |
| O aplicativo <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Exemplo de adaptador de sincronização</a> |
| é um exemplo de uso de um adaptador de sincronização que transfere dados entre o Provedor |
| de contatos e um aplicativo de amostra hospedado pelo Google Web Services. |
| </p> |
| <h2 id="InformationTypes">Organização do Provedor de Contatos</h2> |
| <p> |
| O Provedor de Contatos é um componente do provedor de conteúdo do Android. Ele mantém três tipos de |
| dados sobre uma pessoa, sendo cada um deles correspondente a uma tabela fornecida pelo provedor, como |
| ilustrado na figura 1: |
| </p> |
| <img src="{@docRoot}images/providers/contacts_structure.png" alt="" height="364" id="figure1" /> |
| <p class="img-caption"> |
| <strong>Figura 1.</strong> Estrutura da tabela do Provedor de Contatos. |
| </p> |
| <p> |
| As três tabelas são comumente identificadas pelo nome de suas classes de contrato. As classes |
| definem constantes para URIs de conteúdo e nomes e valores de colunas usados pela tabela: |
| </p> |
| <dl> |
| <dt> |
| Tabela {@link android.provider.ContactsContract.Contacts} |
| </dt> |
| <dd> |
| As linhas representam pessoas diferentes com base em agregações de linhas de contatos brutos. |
| </dd> |
| <dt> |
| Tabela {@link android.provider.ContactsContract.RawContacts} |
| </dt> |
| <dd> |
| As linhas contêm um resumo dos dados de uma pessoa, específicos a um tipo e uma conta de usuário. |
| </dd> |
| <dt> |
| Tabela {@link android.provider.ContactsContract.Data} |
| </dt> |
| <dd> |
| As linhas contêm os detalhes dos contatos brutos, como endereços de e-mail ou números de telefone. |
| </dd> |
| </dl> |
| <p> |
| As outras tabelas representadas pelas classes de contrato em {@link android.provider.ContactsContract} |
| são tabelas auxiliares que o Provedor de Contatos usa para gerenciar suas operações ou compatibilizar |
| funções específicas nos contatos do dispositivo ou em aplicativos de telefonia. |
| </p> |
| <h2 id="RawContactBasics">Contatos brutos</h2> |
| <p> |
| Os contatos brutos representam os dados de uma pessoa provenientes de um tipo único de conta e um nome |
| de conta. Como o Provedor de Contatos permite mais de um serviço on-line como fonte |
| de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa. |
| Diversos contatos brutos também permitem que um usuário combine os dados de uma pessoa de mais de uma conta |
| a partir do mesmo tipo de conta. |
| </p> |
| <p> |
| A maioria dos dados de um contato bruto não é armazenada |
| na tabela {@link android.provider.ContactsContract.RawContacts}. Em vez disso, é armazenada em uma ou mais |
| linhas na tabela {@link android.provider.ContactsContract.Data}. Cada linha de dados tem uma coluna |
| {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID} que |
| contém o valor {@code android.provider.BaseColumns#_ID RawContacts._ID} de sua |
| linha {@link android.provider.ContactsContract.RawContacts} pai. |
| </p> |
| <h3 id="RawContactsColumns">Colunas importantes de contatos brutos</h3> |
| <p> |
| As colunas importantes na tabela {@link android.provider.ContactsContract.RawContacts} são |
| listadas na tabela 1. Leia as observações que se seguem após a tabela: |
| </p> |
| <p class="table-caption" id="table1"> |
| <strong>Tabela 1.</strong> Importantes colunas de contatos brutos. |
| </p> |
| <table> |
| <tr> |
| <th scope="col">Nome da coluna</th> |
| <th scope="col">Uso</th> |
| <th scope="col">Observações</th> |
| </tr> |
| <tr> |
| <td> |
| {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_NAME} |
| </td> |
| <td> |
| O nome da conta para o tipo de conta que é a fonte desse contato bruto. |
| Por exemplo: o nome da conta de uma conta da Google é um dos endereços do Gmail do proprietário |
| do dispositivo. Para obter mais informações, |
| acesse o próximo item |
| {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}. |
| </td> |
| <td> |
| O formato desse nome é específico deste tipo de conta. |
| Não se trata necessariamente de um endereço de e-mail. |
| </td> |
| </tr> |
| <tr> |
| <td> |
| {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} |
| </td> |
| <td> |
| O tipo de conta que é a fonte desse contato bruto. Por exemplo: o tipo |
| de conta de uma conta da Google é <code>com.google</code>. Sempre qualifique o tipo de conta |
| com um identificador de domínio para um domínio que você controla ou possui. Isso garantirá que seu |
| tipo de conta seja único. |
| </td> |
| <td> |
| Os tipos de conta que fornecem dados de contatos normalmente têm um adaptador de sincronização associado que |
| sincroniza-se com o Provedor de Contatos. |
| </tr> |
| <tr> |
| <td> |
| {@link android.provider.ContactsContract.RawContactsColumns#DELETED} |
| </td> |
| <td> |
| O sinalizador "excluído" de um contato bruto. |
| </td> |
| <td> |
| Esse sinalizador permite que o Provedor de Contatos mantenha a linha internamente até |
| que os adaptadores de sincronização possam excluí-la dos servidores e, em seguida, excluí-la |
| do repositório. |
| </td> |
| </tr> |
| </table> |
| <h4>Observações</h4> |
| <p> |
| As observações a seguir sobre a tabela |
| {@link android.provider.ContactsContract.RawContacts} são importantes: |
| </p> |
| <ul> |
| <li> |
| O nome de um contato bruto não é armazenado em sua linha em |
| {@link android.provider.ContactsContract.RawContacts}. Em vez disso, é armazenado na |
| tabela {@link android.provider.ContactsContract.Data}, em uma |
| linha {@link android.provider.ContactsContract.CommonDataKinds.StructuredName}. Os contatos brutos |
| têm apenas uma linha desse tipo na tabela {@link android.provider.ContactsContract.Data}. |
| </li> |
| <li> |
| <strong>Atenção:</strong> para usar os dados da própria conta em uma linha de contato bruto, é necessário |
| registrá-la primeiro com o {@link android.accounts.AccountManager}. Para isso, faça com que |
| os usuários adicionem o tipo e o nome da conta à lista de contas. Caso |
| contrário, o Provedor de Contatos excluirá a linha do contato bruto automaticamente. |
| <p> |
| Por exemplo: se quiser que o aplicativo mantenha dados de contato do seu serviço baseado em web |
| com o {@code com.example.dataservice} de domínio e com a conta do usuário do serviço |
| {@code becky.sharp@dataservice.example.com}, o usuário precisa, primeiramente, adicionar o "tipo" |
| de conta ({@code com.example.dataservice}) e o "nome" da conta |
| ({@code becky.smart@dataservice.example.com}) antes que o aplicativo adicione linhas de contato bruto. |
| Você pode explicar esse requisito ao usuário em documentações ou pode exigir que o |
| usuário adicione o tipo ou o nome ou ambos. Tipos e nomes de conta |
| são descritos com mais detalhes na próxima seção. |
| </li> |
| </ul> |
| <h3 id="RawContactsExample">Fontes de dados de contatos brutos</h3> |
| <p> |
| Para compreender como os contatos brutos funcionam, considere a usuária "Emily Dickinson" que tem as seguintes |
| três contas de usuário definidas no seu dispositivo: |
| </p> |
| <ul> |
| <li><code>emily.dickinson@gmail.com</code></li> |
| <li><code>emilyd@gmail.com</code></li> |
| <li>Conta do twitter "belle_of_amherst"</li> |
| </ul> |
| <p> |
| Essa usuária ativou <em>Sincronizar contatos</em> para todas as três contas nas |
| Configurações da <em>conta</em>. |
| </p> |
| <p> |
| Suponhamos que Emily Dickinson abra uma janela do navegador, acesse o Gmail como |
| <code>emily.dickinson@gmail.com</code>, abra |
| Contatos e adicione "Thomas Higginson". Mais tarde, ela acessa o Gmail como |
| <code>emilyd@gmail.com</code> e envia um e-mail para "Thomas Higginson", o que automaticamente |
| o adiciona como um contato. Ela também segue "colonel_tom" (ID do twitter de Thomas Higginson) no |
| Twitter. |
| </p> |
| <p> |
| O Provedor de Contatos cria três contatos brutos como resultado desse trabalho: |
| </p> |
| <ol> |
| <li> |
| Um contato bruto de "Thomas Higginson" associado a <code>emily.dickinson@gmail.com</code>. |
| O tipo de conta do usuário é Google. |
| </li> |
| <li> |
| Um segundo contato bruto de "Thomas Higginson" associado a <code>emilyd@gmail.com</code>. |
| O tipo de conta do usuário também é Google. Há um segundo contato bruto, |
| embora o nome seja idêntico a um nome anterior porque a pessoa foi adicionada |
| a uma conta de usuário diferente. |
| </li> |
| <li> |
| Um terceiro contato bruto de "Thomas Higginson" associado a "belle_of_amherst". O tipo |
| de conta de usuário é Twitter. |
| </li> |
| </ol> |
| <h2 id="DataBasics">Dados</h2> |
| <p> |
| Como observado anteriormente, os dados de um contato bruto são armazenados |
| em uma linha {@link android.provider.ContactsContract.Data} vinculada ao valor <code>_ID</code> |
| do contato bruto. Isso permite que um único contato bruto tenha diversas instâncias do mesmo |
| tipo de dados, como endereços de e-mail ou números de telefone. Por exemplo: se |
| "Thomas Higginson" para {@code emilyd@gmail.com} (a linha do contato bruto de Thomas Higginson |
| associada à conta Google <code>emilyd@gmail.com</code>) tem um endereço de e-mail pessoal |
| <code>thigg@gmail.com</code> e um de trabalho |
| <code>thomas.higginson@gmail.com</code>, o Provedor de Contatos armazena as duas linhas de endereço de e-mail |
| e vincula ambas ao contato bruto. |
| </p> |
| <p> |
| Observe que diferentes tipos de dados são armazenados nessa única tabela. Linhas de nome de exibição, |
| número de telefone, e-mail, endereço postal, foto e detalhes de site são encontradas |
| na tabela {@link android.provider.ContactsContract.Data}. Para ajudar a gerenciar isso, |
| a tabela {@link android.provider.ContactsContract.Data} tem algumas colunas com nomes descritivos |
| e outras com nomes genéricos. O conteúdo de uma coluna de nome descritivo tem o mesmo significado |
| independente do tipo de dado da linha, enquanto o conteúdo de uma coluna de nome genérico tem |
| diferentes significados dependendo do tipo de dados. |
| </p> |
| <h3 id="DescriptiveColumns">Nomes de coluna descritiva</h3> |
| <p> |
| A seguir há alguns exemplos de nomes descritivos de colunas: |
| </p> |
| <dl> |
| <dt> |
| {@link android.provider.ContactsContract.Data#RAW_CONTACT_ID} |
| </dt> |
| <dd> |
| O valor da coluna <code>_ID</code> do contato bruto para estes dados. |
| </dd> |
| <dt> |
| {@link android.provider.ContactsContract.Data#MIMETYPE} |
| </dt> |
| <dd> |
| O tipo de dado armazenado nessa linha, expresso como um tipo MIME personalizado. O Provedor de Contatos |
| usa os tipos MIME definidos nas subclasses de |
| {@link android.provider.ContactsContract.CommonDataKinds}. Esses tipos MIME têm código aberto |
| e podem ser usados por qualquer aplicativo ou adaptador de sincronização que funcione com o Provedor de Contatos. |
| </dd> |
| <dt> |
| {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} |
| </dt> |
| <dd> |
| Se esse tipo de linha de dados puder ocorrer mais do que uma vez em um contato bruto, |
| a coluna {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} sinaliza |
| a linha de dados que contém os dados primários do tipo. Por exemplo: se |
| o usuário pressionar por algum tempo um número de telefone de um contato e selecionar <strong>Definir padrão</strong>, |
| a linha {@link android.provider.ContactsContract.Data} que contém esse número |
| tem sua coluna {@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} definida |
| como um valor diferente de zero. |
| </dd> |
| </dl> |
| <h3 id="GenericColumns">Nomes de coluna genérica</h3> |
| <p> |
| Há 15 colunas genéricas de nome <code>DATA1</code> a |
| <code>DATA15</code> que estão, em geral, disponíveis e quatro colunas genéricas |
| adicionais <code>SYNC1</code> a <code>SYNC4</code> que devem ser usadas somente por adaptadores |
| de sincronização. As constantes de nome da coluna genérica sempre funcionam independentemente do tipo |
| de dados que a linha contenha. |
| </p> |
| <p> |
| A coluna <code>DATA1</code> é indexada. O Provedor de Contatos sempre usa essa coluna para |
| os dados que o provedor espera serem os alvos mais frequentes de uma consulta. Por exemplo: |
| em uma linha de e-mail, essa coluna contém o endereço de e-mail atual. |
| </p> |
| <p> |
| Por convenção, a coluna <code>DATA15</code> é reservada para armazenar dados de BLOBs |
| (Binary Large Object), como miniaturas de fotos. |
| </p> |
| <h3 id="TypeSpecificNames">Nomes de coluna de tipo específico</h3> |
| <p> |
| Para facilitar o trabalho com as colunas para um tipo específico de linha, o Provedor de Contatos |
| também fornece constantes de nome de colunas de tipo específico, definidas em subclasses de |
| {@link android.provider.ContactsContract.CommonDataKinds}. As constantes simplesmente dão |
| um nome de constante diferente para o mesmo nome de coluna, o que ajuda no acesso aos dados em uma linha |
| de um tipo específico. |
| </p> |
| <p> |
| Por exemplo: a classe {@link android.provider.ContactsContract.CommonDataKinds.Email} define |
| constantes de nome de coluna de tipo específico para uma linha {@link android.provider.ContactsContract.Data} |
| que tem o tipo MIME |
| {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE |
| Email.CONTENT_ITEM_TYPE}. A classe contém a constante |
| {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} para a coluna de endereço |
| de e-mail. O valor atual |
| de {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS} é "data1", que é |
| igual ao nome genérico da coluna. |
| </p> |
| <p class="caution"> |
| <strong>Atenção:</strong> não adicione seus dados personalizados |
| à tabela {@link android.provider.ContactsContract.Data} usando uma linha que tenha um dos |
| tipos de MIME predefinidos do provedor. Caso contrário, há o risco de perda de dados ou mau funcionamento |
| do provedor. Por exemplo: não se deve adicionar uma linha com o tipo MIME |
| {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE |
| Email.CONTENT_ITEM_TYPE} que contenha um nome de usuário em vez de um endereço de e-mail na |
| coluna <code>DATA1</code>. Se for usado um tipo MIME personalizado para a linha, será possível |
| definir os próprios nomes de coluna de tipo específico e usar as colunas como quiser. |
| </p> |
| <p> |
| A figura 2 mostra como colunas descritivas e colunas de dados aparecem |
| em uma linha {@link android.provider.ContactsContract.Data} e como os nomes de coluna de tipo específico se "sobrepõem" |
| aos nomes de coluna genérica. |
| </p> |
| <img src="{@docRoot}images/providers/data_columns.png" alt="How type-specific column names map to generic column names" height="311" id="figure2" /> |
| <p class="img-caption"> |
| <strong>Figura 2.</strong> Nomes de coluna de tipo específico e nomes de coluna genérica. |
| </p> |
| <h3 id="ColumnMaps">Classes de nome de coluna de tipo específico</h3> |
| <p> |
| A tabela 2 lista as classes de nome de coluna de tipo específico mais usadas: |
| </p> |
| <p class="table-caption" id="table2"> |
| <strong>Tabela 2.</strong> Classes de nome de coluna de tipo específico</p> |
| <table> |
| <tr> |
| <th scope="col">Classes de mapeamento</th> |
| <th scope="col">Tipo de dados</th> |
| <th scope="col">Observações</th> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredName}</td> |
| <td>Os dados de nome do contato bruto associados a essa linha de dados.</td> |
| <td>Os contatos brutos têm apenas uma dessas linhas.</td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.CommonDataKinds.Photo}</td> |
| <td>A foto principal do contato bruto associada a essa linha de dados.</td> |
| <td>Os contatos brutos têm apenas uma dessas linhas.</td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.CommonDataKinds.Email}</td> |
| <td>Um endereço de e-mail do contato bruto associado a essa linha de dados.</td> |
| <td>Os contatos brutos podem ter diversos endereços de e-mail.</td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal}</td> |
| <td>Um endereço postal do contato bruto associado a essa linha de dados.</td> |
| <td>Os contatos brutos podem ter diversos endereços postais.</td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}</td> |
| <td>Um identificador que vincula o contato bruto a um dos grupos no Provedor de Contatos.</td> |
| <td> |
| Grupos são um recurso opcional de um tipo e um nome de conta. Eles são descritos |
| mais detalhadamente na seção <a href="#Groups">Grupos de contato</a>. |
| </td> |
| </tr> |
| </table> |
| <h3 id="ContactBasics">Contatos</h3> |
| <p> |
| O Provedor de Contatos combina as linhas do contato bruto entre todos os tipos e nomes de conta |
| para formar um <strong>contato</strong>. Isso facilita a exibição e modificação de todos os dados de uma pessoa que um |
| usuário tenha coletado. O Provedor de Contatos gerencia a criação de linhas |
| de novos contatos e a agregação de contatos brutos a uma linha de contato existente. Nem os aplicativos, nem |
| os adaptadores de sincronização têm permissão para adicionar contatos, e algumas colunas em uma linha de contato são de somente leitura. |
| </p> |
| <p class="note"> |
| <strong>Observação:</strong> a tentativa de adicionar um contato ao Provedor de Contatos com um |
| {@link android.content.ContentResolver#insert(Uri,ContentValues) insert()} gerará |
| uma exceção {@link java.lang.UnsupportedOperationException}. A tentativa de atualizar uma coluna |
| listada como "somente leitura" será ignorada. |
| </p> |
| <p> |
| O Provedor de Contatos cria um novo contato em resposta à adição de um novo contato bruto |
| que não corresponda a nenhum contato existente. O provedor também faz isso se os dados de um |
| contato bruto existente mudam de modo a não corresponder mais ao contato |
| inserido anteriormente. Se um aplicativo ou um adaptador de sincronização criar um novo contato bruto que |
| <em>corresponda</em> a um contato existente, o novo contato bruto será agregado ao contato |
| existente. |
| </p> |
| <p> |
| O Provedor de Contatos liga uma linha do contato às linhas do contato bruto com a coluna <code>_ID</code> |
| da linha do contato na tabela |
| {@link android.provider.ContactsContract.Contacts Contacts}. A coluna <code>CONTACT_ID</code> da tabela de contatos brutos |
| {@link android.provider.ContactsContract.RawContacts} contém valores <code>_ID</code> para |
| a linha dos contatos associados a cada linha dos contatos brutos. |
| </p> |
| <p> |
| A tabela {@link android.provider.ContactsContract.Contacts} também tem a coluna |
| {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}, que é |
| um vínculo "permanente" com a linha do contato. Como o Provedor de Contatos mantém contatos |
| automaticamente, ele pode mudar o valor de {@code android.provider.BaseColumns#_ID} da linha do contato |
| em resposta a uma agregação ou sincronização. Mesmo que isso aconteça, a URI de conteúdo |
| {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} combinada com |
| {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} do contato continuará |
| apontado para a linha do contato para permitir o uso de |
| {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} |
| e manter ligações com contatos "favoritos" e assim por diante. Essa coluna tem o próprio formato, que |
| não tem nenhuma relação com o formato da coluna {@code android.provider.BaseColumns#_ID}. |
| </p> |
| <p> |
| A figura 3 mostra como as três tabelas principais se relacionam entre si. |
| </p> |
| <img src="{@docRoot}images/providers/contacts_tables.png" alt="Contacts provider main tables" height="514" id="figure4" /> |
| <p class="img-caption"> |
| <strong>Figura 3.</strong> Contatos, contatos brutos e relacionamentos da tabela de detalhes. |
| </p> |
| <h2 id="Sources">Dados de adaptadores de sincronização</h2> |
| <p> |
| Os usuários inserem dados de contato diretamente no dispositivo, mas os dados também são direcionados ao Provedor |
| de Contatos a partir de serviços web via <strong>adaptadores de sincronização</strong>, que automatizam |
| a transferência de dados entre dispositivo e serviços. Adaptadores de sincronização funcionam em segundo plano, |
| controlados pelo sistema, e chamam métodos {@link android.content.ContentResolver} |
| para gerenciar os dados. |
| </p> |
| <p> |
| No Android, o serviço web com o qual um adaptador de sincronização trabalha é identificado por um tipo de conta. |
| Cada adaptador de sincronização funciona com um tipo de conta, mas é compatível com diversos nomes de conta |
| para o tipo em questão. Tipos e nomes de conta são descritos brevemente na seção |
| <a href="#RawContactsExample">Fontes de dados de contatos brutos</a>. As definições a seguir fornecem |
| mais detalhes e descrevem como o tipo e o nome de conta se relacionam com adaptadores de sincronização e serviços. |
| </p> |
| <dl> |
| <dt> |
| Tipo de conta |
| </dt> |
| <dd> |
| Identifica um serviço em que o usuário tenha armazenado dados. Na maior parte do tempo, o usuário deve |
| autenticar com o serviço. Por exemplo: Google Contacts é um tipo de conta, identificado |
| pelo código <code>google.com</code>. Esse valor corresponde ao tipo de conta usado pelo |
| {@link android.accounts.AccountManager}. |
| </dd> |
| <dt> |
| Nome da conta |
| </dt> |
| <dd> |
| Identifica uma conta ou login específico de um tipo de conta. As contas Google Contacts |
| são idênticas às contas Google, que têm um endereço de e-mail como nome da conta. |
| Outros serviços podem usar um nome de usuário com só uma palavra ou ID numérico. |
| </dd> |
| </dl> |
| <p> |
| Os tipos de conta não precisam ser exclusivos. Um usuário pode configurar diversas contas Google Contacts |
| e baixar os dados dela para o Provedor de Contatos. Isso pode acontecer se o usuário tiver um grupo de |
| contatos pessoais para um nome de conta pessoal e outro grupo para um de conta de trabalho. Nomes de conta normalmente |
| são exclusivos. Juntos, eles identificam um fluxo de dados específicos entre o Provedor de Contatos e |
| um serviço externo. |
| </p> |
| <p> |
| Se você desejar transferir os dados do serviço ao Provedor de Contatos, precisará criar seu |
| próprio adaptador de sincronização. Isso é descrito com mais detalhes na seção |
| <a href="#SyncAdapters">Adaptadores de sincronização do Provedor de Contatos</a>. |
| </p> |
| <p> |
| A figura 4 mostra como o Provedor de Contatos se insere no fluxo de dados |
| sobre pessoas. Na caixa marcada "adaptadores de sincronização", cada adaptador é etiquetado pelo tipo de conta. |
| </p> |
| <img src="{@docRoot}images/providers/ContactsDataFlow.png" alt="Flow of data about people" height="252" id="figure5" /> |
| <p class="img-caption"> |
| <strong>Figura 4.</strong> Fluxo de dados do Provedor de Contatos. |
| </p> |
| <h2 id="Permissions">Permissões necessárias</h2> |
| <p> |
| Os aplicativos que queiram acessar o Provedor de Contatos devem solicitar as seguintes |
| permissões: |
| </p> |
| <dl> |
| <dt>Acesso de leitura a uma ou mais tabelas</dt> |
| <dd> |
| {@link android.Manifest.permission#READ_CONTACTS}, especificado em |
| <code>AndroidManifest.xml</code> com |
| o elemento <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"> |
| <uses-permission></a></code> |
| como <code><uses-permission android:name="android.permission.READ_CONTACTS"></code>. |
| </dd> |
| <dt>Acesso de gravação a uma ou mais tabelas</dt> |
| <dd> |
| {@link android.Manifest.permission#WRITE_CONTACTS}, especificado em |
| <code>AndroidManifest.xml</code> com |
| o elemento <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"> |
| <uses-permission></a></code> |
| como <code><uses-permission android:name="android.permission.WRITE_CONTACTS"></code>. |
| </dd> |
| </dl> |
| <p> |
| Essas permissões não se estendem aos dados do perfil do usuário. O perfil do usuário |
| e suas permissões necessárias são abordados na seção a seguir: |
| <a href="#UserProfile">O perfil do usuário</a>. |
| </p> |
| <p> |
| Lembre-se de que os dados de contato do usuário são pessoais e confidenciais. Os usuários se preocupam |
| com a privacidade e, por isso, não querem aplicativos que coletem dados sobre eles ou seus contatos. |
| Se não for óbvio o motivo da necessidade de permissões para acessar os dados de contato de um usuário, eles podem atribuir |
| avaliações ruins ao seu aplicativo ou simplesmente não instalá-lo. |
| </p> |
| <h2 id="UserProfile">O perfil do usuário</h2> |
| <p> |
| A tabela {@link android.provider.ContactsContract.Contacts} tem uma única linha contendo |
| os dados do perfil do usuário do dispositivo. Esses dados descrevem o <code>user</code> do dispositivo em vez |
| de um dos contatos do usuário. A linha de contatos do perfil é vinculada a uma linha |
| de contatos brutos para cada sistema que usa um perfil. |
| Cada linha de contato bruto de perfil pode ter diversas linhas de dados. Constantes de acesso ao perfil |
| do usuário estão disponíveis na classe {@link android.provider.ContactsContract.Profile}. |
| </p> |
| <p> |
| O acesso ao perfil do usuário exige permissões especiais. Além das permissões |
| {@link android.Manifest.permission#READ_CONTACTS} e |
| {@link android.Manifest.permission#WRITE_CONTACTS} necessárias para ler e gravar, o acesso |
| ao perfil do usuário requer as permissões {@code android.Manifest.permission#READ_PROFILE} e |
| {@code android.Manifest.permission#WRITE_PROFILE}, respectivamente, para ler e |
| gravar. |
| </p> |
| <p> |
| Lembre-se de que é preciso considerar a confidencialidade de um perfil do usuário. A permissão |
| {@code android.Manifest.permission#READ_PROFILE} permite o acesso aos dados de identificação |
| pessoal do usuário do dispositivo. Certifique-se de informar ao usuário o motivo |
| da necessidade de permissões de acesso ao perfil do usuário na descrição do aplicativo. |
| </p> |
| <p> |
| Para recuperar a linha de contato que contém o perfil do usuário, |
| chame {@link android.content.ContentResolver#query(Uri,String[], String, String[], String) |
| ContentResolver.query()}. Defina a URI de conteúdo como |
| {@link android.provider.ContactsContract.Profile#CONTENT_URI} e não forneça nenhum |
| critério de seleção. Também é possível usar essa URI de conteúdo como base para recuperar |
| contatos brutos ou dados do perfil. Por exemplo, esse fragmento recupera dados do perfil: |
| </p> |
| <pre> |
| // Sets the columns to retrieve for the user profile |
| mProjection = new String[] |
| { |
| Profile._ID, |
| Profile.DISPLAY_NAME_PRIMARY, |
| Profile.LOOKUP_KEY, |
| Profile.PHOTO_THUMBNAIL_URI |
| }; |
| |
| // Retrieves the profile from the Contacts Provider |
| mProfileCursor = |
| getContentResolver().query( |
| Profile.CONTENT_URI, |
| mProjection , |
| null, |
| null, |
| null); |
| </pre> |
| <p class="note"> |
| <strong>Observação:</strong> se você recuperar diversas linhas de contato e quiser determinar se uma delas |
| é o perfil do usuário, teste a coluna |
| {@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} da linha. Essa coluna |
| é definida como "1" se o contato for o perfil do usuário. |
| </p> |
| <h2 id="ContactsProviderMetadata">Metadados do Provedor de Contatos</h2> |
| <p> |
| O Provedor de Contatos gerencia dados que acompanham o estado dos dados de contatos |
| no repositório. Esses metadados sobre o repositório são armazenados em vários locais, inclusive |
| os contatos brutos, os dados e as linhas da tabela de contatos, |
| a tabela {@link android.provider.ContactsContract.Settings} |
| e a tabela {@link android.provider.ContactsContract.SyncState}. A tabela a seguir mostra |
| o efeito de cada uma dessas partes de metadados: |
| </p> |
| <p class="table-caption" id="table3"> |
| <strong>Tabela 3.</strong> Metadados no Provedor de Contatos</p> |
| <table> |
| <tr> |
| <th scope="col">Tabela</th> |
| <th scope="col">Coluna</th> |
| <th scope="col">Valores</th> |
| <th scope="col">Significado</th> |
| </tr> |
| <tr> |
| <td rowspan="2">{@link android.provider.ContactsContract.RawContacts}</td> |
| <td rowspan="2">{@link android.provider.ContactsContract.SyncColumns#DIRTY}</td> |
| <td>"0" - sem modificação desde a última sincronização.</td> |
| <td rowspan="2"> |
| Sinaliza contatos brutos que não mudaram no dispositivo e devem ser sincronizados com |
| o servidor. O valor é definido automaticamente pelo Provedor de Contatos quando os aplicativos |
| do Android atualizam uma linha. |
| <p> |
| Adaptadores de sincronização que modificam o contato bruto ou as tabelas de dados sempre devem anexar a |
| string {@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER} |
| à URI de conteúdo usada. Isso evita que o provedor sinalize alguma linha como suja. |
| Caso contrário, as modificações do adaptador de sincronização parecem ser modificações locais e são |
| enviadas ao servidor, mesmo que o servidor seja a origem da modificação. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td>"1" - modificado desde a última sincronização, precisa ser sincronizado com o servidor.</td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.RawContacts}</td> |
| <td>{@link android.provider.ContactsContract.SyncColumns#VERSION}</td> |
| <td>O número da versão dessa linha.</td> |
| <td> |
| O Provedor de Contatos incrementa esse valor automaticamente sempre que a linha ou |
| os dados relacionados a ela mudam. |
| </td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.Data}</td> |
| <td>{@link android.provider.ContactsContract.DataColumns#DATA_VERSION}</td> |
| <td>O número da versão dessa linha.</td> |
| <td> |
| O Provedor de Contatos incrementa esse valor automaticamente sempre que a linha de dados |
| é modificada. |
| </td> |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.RawContacts}</td> |
| <td>{@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}</td> |
| <td> |
| Valor de string que identifica exclusivamente esse contato bruto para a conta em |
| que foi criado. |
| </td> |
| <td> |
| Quando um adaptador de sincronização cria um novo contato bruto, essa coluna deve ser definida como |
| o ID exclusivo do servidor para o contato bruto. Quando um aplicativo do Android cria um novo |
| contato bruto, o aplicativo deve deixar essa coluna vazia. Isso sinaliza ao adaptador |
| de sincronização que ele deve criar um novo contato bruto no servidor e obter |
| um valor para o {@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}. |
| <p> |
| Em particular, o ID de origem deve ser <strong>exclusivo</strong> de cada tipo |
| de conta e estável em sincronizações: |
| </p> |
| <ul> |
| <li> |
| Exclusivo: cada contato bruto de uma conta deve ter o próprio ID de origem. Se isso |
| não for aplicado, haverá problemas no aplicativo de contatos. |
| Observe que dois contatos brutos do mesmo <em>tipo</em> de conta podem ter |
| o mesmo ID de origem. Por exemplo: o contato bruto "Thomas Higginson" da |
| conta {@code emily.dickinson@gmail.com} pode ter o mesmo ID |
| de origem do contato bruto "Thomas Higginson" da conta |
| {@code emilyd@gmail.com}. |
| </li> |
| <li> |
| Estável: IDs de origem são uma parte permanente dos dados do serviço on-line para |
| o contato bruto. Por exemplo: se o usuário apaga o Armazenamento de Contatos |
| nas configurações dos aplicativos e ressincroniza, os contatos brutos restaurados devem ter os mesmos |
| IDs de origem de antes. Se isso não for aplicado, os atalhos |
| deixarão de funcionar. |
| </li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td rowspan="2">{@link android.provider.ContactsContract.Groups}</td> |
| <td rowspan="2">{@link android.provider.ContactsContract.GroupsColumns#GROUP_VISIBLE}</td> |
| <td>"0" - os contatos nesse grupo não devem ser visíveis em IUs do aplicativo do Android.</td> |
| <td> |
| Essa coluna se destina à compatibilidade com servidores, que permitem que um usuário oculte contatos |
| em determinados grupos. |
| </td> |
| </tr> |
| <tr> |
| <td>"1" - os contatos nesse grupo podem ser visíveis nas IUs do aplicativo.</td> |
| </tr> |
| <tr> |
| <td rowspan="2">{@link android.provider.ContactsContract.Settings}</td> |
| <td rowspan="2"> |
| {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE}</td> |
| <td> |
| "0" - para essa conta e esse tipo de conta, os contatos que não pertencem a um grupo são |
| invisíveis nas IUs do aplicativo do Android. |
| </td> |
| <td rowspan="2"> |
| Por padrão, os contatos são invisíveis se nenhum dos contatos brutos pertencer a algum grupo |
| (a associação de grupo de um contato bruto é indicada por uma ou mais |
| linhas {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} |
| na tabela {@link android.provider.ContactsContract.Data}). |
| Por padrão, é possível fazer com que contatos sem grupos sejam visíveis |
| por meio desse sinalizador na linha da tabela {@link android.provider.ContactsContract.Settings} para um tipo de conta e uma conta. |
| Esse sinalizador serve para exibir contatos de servidores que não usam grupos. |
| </td> |
| </tr> |
| <tr> |
| <td> |
| "1" - para essa conta e esse tipo de conta, os contatos que não pertencem a um grupo são |
| visíveis nas IUs do aplicativo. |
| </td> |
| |
| </tr> |
| <tr> |
| <td>{@link android.provider.ContactsContract.SyncState}</td> |
| <td>(todos)</td> |
| <td> |
| Use essa tabela para armazenar metadados do seu adaptador de sincronização. |
| </td> |
| <td> |
| Com essa tabela, é possível armazenar o estado de sincronização e outros dados relacionados à sincronização persistentes |
| no dispositivo. |
| </td> |
| </tr> |
| </table> |
| <h2 id="Access">Acesso ao Provedor de Contatos</h2> |
| <p> |
| Esta seção descreve orientações quanto ao acesso a dados do Provedor de Contatos, com foco |
| no seguinte: |
| </p> |
| <ul> |
| <li> |
| Consultas de entidade. |
| </li> |
| <li> |
| Modificação em lote. |
| </li> |
| <li> |
| Recuperação e modificação com intenções. |
| </li> |
| <li> |
| Integridade dos dados. |
| </li> |
| </ul> |
| <p> |
| A realização de modificações de um adaptador de sincronização também é abordada na seção |
| <a href="#SyncAdapters">Adaptadores de sincronização do Provedor de Contatos</a>. |
| </p> |
| <h3 id="Entities">Consultas de entidades</h3> |
| <p> |
| A organização hierárquica das tabelas do Provedor de Contatos é muito útil |
| para recuperar uma linha e todas as linhas "filhas" vinculadas. Por exemplo: para exibir |
| todas as informações de uma pessoa, você pode querer recuperar todas |
| as linhas {@link android.provider.ContactsContract.RawContacts} de uma única |
| linha {@link android.provider.ContactsContract.Contacts} ou todas |
| as linhas {@link android.provider.ContactsContract.CommonDataKinds.Email} de uma única |
| linha {@link android.provider.ContactsContract.RawContacts}. Para facilitar isso, o Provedor |
| de contatos oferece a ideia de <strong>entidade</strong>, que atua como uma junção dos bancos de dados entre |
| tabelas. |
| </p> |
| <p> |
| Entidade é como uma tabela composta de colunas selecionadas de uma tabela pai e uma tabela filha. |
| Ao consultar uma entidade, fornece-se uma projeção e buscam-se critérios com base nas colunas |
| disponíveis da entidade. O resultado é um {@link android.database.Cursor} que contém |
| uma linha para cada linha recuperada da tabela filha. Por exemplo: ao consultar |
| {@link android.provider.ContactsContract.Contacts.Entity} de um nome de contato |
| e todas as linhas {@link android.provider.ContactsContract.CommonDataKinds.Email} de todos os |
| contatos brutos por esse nome, você obterá um {@link android.database.Cursor} contendo uma linha |
| para cada linha {@link android.provider.ContactsContract.CommonDataKinds.Email}. |
| </p> |
| <p> |
| As entidades simplificam as consultas. Usando uma entidade, é possível recuperar todos os dados de contatos |
| de um contato ou contato bruto de uma vez, sem precisar consultar primeiro a tabela pai para obter |
| um ID e, em seguida, ter que consultar a tabela filha com esse ID. Além disso, o Provedor de Contatos processa |
| uma consulta com uma entidade em uma transação única, o que garante que os dados recuperados |
| sejam consistentes internamente. |
| </p> |
| <p class="note"> |
| <strong>Observação:</strong> uma entidade normalmente não contém todas as colunas da tabela pai e |
| da tabela filha. Se você tentar trabalhar com um nome de coluna que não esteja na lista de constantes de nomes de coluna |
| da entidade, será gerada uma {@link java.lang.Exception}. |
| </p> |
| <p> |
| O fragmento a seguir mostra como recuperar todas as linhas de contato bruto de um contato. O fragmento |
| é parte de um aplicativo maior que tem duas atividades: "principal" e “de detalhes". A atividade principal |
| exibe uma lista de linhas de contato. Quando um usuário seleciona uma delas, a atividade envia o ID correspondente à atividade |
| de detalhes. A atividade de detalhes usa {@link android.provider.ContactsContract.Contacts.Entity} |
| para exibir todas as linhas de dados de todos os contatos brutos associados ao contato |
| selecionado. |
| </p> |
| <p> |
| Esse fragmento é extraído da atividade "de detalhes": |
| </p> |
| <pre> |
| ... |
| /* |
| * Appends the entity path to the URI. In the case of the Contacts Provider, the |
| * expected URI is content://com.google.contacts/#/entity (# is the ID value). |
| */ |
| mContactUri = Uri.withAppendedPath( |
| mContactUri, |
| ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); |
| |
| // Initializes the loader identified by LOADER_ID. |
| getLoaderManager().initLoader( |
| LOADER_ID, // The identifier of the loader to initialize |
| null, // Arguments for the loader (in this case, none) |
| this); // The context of the activity |
| |
| // Creates a new cursor adapter to attach to the list view |
| mCursorAdapter = new SimpleCursorAdapter( |
| this, // the context of the activity |
| R.layout.detail_list_item, // the view item containing the detail widgets |
| mCursor, // the backing cursor |
| mFromColumns, // the columns in the cursor that provide the data |
| mToViews, // the views in the view item that display the data |
| 0); // flags |
| |
| // Sets the ListView's backing adapter. |
| mRawContactList.setAdapter(mCursorAdapter); |
| ... |
| @Override |
| public Loader<Cursor> onCreateLoader(int id, Bundle args) { |
| |
| /* |
| * Sets the columns to retrieve. |
| * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. |
| * DATA1 contains the first column in the data row (usually the most important one). |
| * MIMETYPE indicates the type of data in the data row. |
| */ |
| String[] projection = |
| { |
| ContactsContract.Contacts.Entity.RAW_CONTACT_ID, |
| ContactsContract.Contacts.Entity.DATA1, |
| ContactsContract.Contacts.Entity.MIMETYPE |
| }; |
| |
| /* |
| * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw |
| * contact collated together. |
| */ |
| String sortOrder = |
| ContactsContract.Contacts.Entity.RAW_CONTACT_ID + |
| " ASC"; |
| |
| /* |
| * Returns a new CursorLoader. The arguments are similar to |
| * ContentResolver.query(), except for the Context argument, which supplies the location of |
| * the ContentResolver to use. |
| */ |
| return new CursorLoader( |
| getApplicationContext(), // The activity's context |
| mContactUri, // The entity content URI for a single contact |
| projection, // The columns to retrieve |
| null, // Retrieve all the raw contacts and their data rows. |
| null, // |
| sortOrder); // Sort by the raw contact ID. |
| } |
| </pre> |
| <p> |
| Quando o carregamento é finalizado, {@link android.app.LoaderManager} invoca um retorno de chamada para |
| {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished(Loader, D) |
| onLoadFinished()}. Um dos argumentos de entrada nesse método é um |
| {@link android.database.Cursor} com os resultados da consulta. No seu aplicativo, você pode obter os |
| dados desse {@link android.database.Cursor} para exibi-los ou trabalhar com eles posteriormente. |
| </p> |
| <h3 id="Transactions">Modificação em lote</h3> |
| <p> |
| Sempre que possível, deve-se inserir, atualizar e excluir dados no Provedor de Contatos |
| em "modo de lote", criando um {@link java.util.ArrayList} de |
| objetos {@link android.content.ContentProviderOperation} e chamando |
| {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Como |
| o Provedor de Contatos realiza todas as operações em um |
| {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} em uma única |
| transação, as modificações nunca deixarão o repositório de contatos em um estado |
| inconsistente. As modificações em lote também facilitam a inserção de um contato bruto e seus dados de detalhe |
| ao mesmo tempo. |
| </p> |
| <p class="note"> |
| <strong>Observação:</strong> para modificar um contato bruto <em>exclusivo</em>, considere enviar uma intenção ao |
| aplicativo de contatos do dispositivo em vez de realizar a modificação no aplicativo. |
| Na seção <a href="#Intents">Recuperação e modificação com intenções</a> há mais detalhes |
| sobre como fazer isso. |
| </p> |
| <h4>Pontos de rendimento</h4> |
| <p> |
| As modificações em lote que contiverem muitas operações podem bloquear outros processos, |
| resultando em uma experiência geral ruim para o usuário. Para organizar todas as modificações |
| a realizar no menor número de listas separadas possível e, ao mesmo tempo, evitar |
| o bloqueio do sistema, é preciso definir <strong>pontos de rendimento</strong> para uma ou mais operações. |
| Pontos de rendimento são objetos {@link android.content.ContentProviderOperation} que têm seu |
| valor {@link android.content.ContentProviderOperation#isYieldAllowed()} definido como |
| <code>true</code>. Quando o Provedor de Contatos encontra um ponto de rendimento, ele pausa o trabalho |
| para permitir a execução de outros processos e encerra a transação em curso. Quando o provedor retorna, ele |
| continua na próxima operação da {@link java.util.ArrayList} e inicia |
| uma nova transação. |
| </p> |
| <p> |
| Os pontos de rendimento resultam em mais de uma transação por chamada de |
| {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Por isso, |
| é preciso definir um ponto de rendimento para a última operação de um conjunto de linhas relacionadas. |
| Por exemplo: é preciso definir um ponto de rendimento para a última operação em um conjunto que adicione |
| linhas de um contato bruto e linhas de dados associados a ele, ou para a última operação de um conjunto de linhas relacionadas |
| a um único contato. |
| </p> |
| <p> |
| Os pontos de rendimento também são uma unidade de operação atômica. Todos os acessos entre dois pontos de rendimento |
| terão sucesso ou fracasso como uma unidade. Se não houver pontos de rendimento definidos, a menor |
| operação atômica será todo o lote de operações. Se forem usados pontos de rendimento, eles evitarão |
| que as operações prejudiquem o desempenho do sistema e, ao mesmo tempo, garantirá que o subconjunto |
| de operações seja atômico. |
| </p> |
| <h4>Referências de retorno da modificação</h4> |
| <p> |
| Ao inserir uma nova linha de contato bruto e as linhas de dados associados como um conjunto |
| de objetos {@link android.content.ContentProviderOperation}, é preciso vincular as linhas de dados |
| à linha de contato bruto pela inserção do valor |
| {@code android.provider.BaseColumns#_ID} do contato bruto como |
| o valor {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. Contudo, esse |
| valor não está disponível ao criar a {@link android.content.ContentProviderOperation} |
| para a linha de dados porque |
| {@link android.content.ContentProviderOperation} ainda não foi aplicada à linha de contato bruto. Para trabalhar com isso, |
| a classe {@link android.content.ContentProviderOperation.Builder} tem o método |
| {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}. |
| Esse método permite a inserção ou modificação de uma coluna com |
| o resultado de uma operação anterior. |
| </p> |
| <p> |
| O método {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} |
| tem dois argumentos: |
| </p> |
| <dl> |
| <dt> |
| <code>key</code> |
| </dt> |
| <dd> |
| O principal de um par de valores principais. O valor desse argumento deve ser o nome de uma coluna |
| na tabela que será modificada. |
| </dd> |
| <dt> |
| <code>previousResult</code> |
| </dt> |
| <dd> |
| O índice com base 0 de um valor em uma matriz |
| de objetos {@link android.content.ContentProviderResult} |
| de {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. Quando |
| as operações em lote são aplicadas, o resultado de cada operação é armazenado |
| em uma matriz intermediária de resultados. O valor <code>previousResult</code> é o índice |
| de um desses resultados, que é recuperado e armazenado com o valor |
| <code>key</code>. Isso permite a inserção de um novo registro de contato bruto e a recuperação do seu |
| valor {@code android.provider.BaseColumns#_ID}, seguido de uma "referência de retorno" ao |
| valor ao adicionar uma linha {@link android.provider.ContactsContract.Data}. |
| <p> |
| Toda a matriz de resultados é criada ao chamar |
| {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} pela primeira vez, |
| com tamanho igual ao da {@link java.util.ArrayList} |
| de objetos {@link android.content.ContentProviderOperation} fornecidos. No entanto, todos |
| os elementos na matriz de resultados são definidos como <code>null</code> e, se houver uma tentativa |
| de referência de retorno a um resultado de uma operação ainda não realizada, |
| {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} |
| gera uma {@link java.lang.Exception}. |
| |
| </p> |
| </dd> |
| </dl> |
| <p> |
| Os fragmentos a seguir mostram como inserir um novo contato bruto e dados em lote. Eles |
| contém o código que estabelece um ponto de rendimento e usam uma referência de retorno. Os fragmentos são |
| uma versão expandida do método <code>createContacEntry()</code>, que é parte |
| da classe <code>ContactAdder</code> |
| no aplicativo de exemplo de <code><a href="{@docRoot}resources/samples/ContactManager/index.html"> |
| Contact Manager</a></code>. |
| </p> |
| <p> |
| O primeiro fragmento recupera dados de contato da IU. Nesse momento, o usuário já |
| selecionou a conta na qual o novo contato bruto deve ser adicionado. |
| </p> |
| <pre> |
| // Creates a contact entry from the current UI values, using the currently-selected account. |
| protected void createContactEntry() { |
| /* |
| * Gets values from the UI |
| */ |
| String name = mContactNameEditText.getText().toString(); |
| String phone = mContactPhoneEditText.getText().toString(); |
| String email = mContactEmailEditText.getText().toString(); |
| |
| int phoneType = mContactPhoneTypes.get( |
| mContactPhoneTypeSpinner.getSelectedItemPosition()); |
| |
| int emailType = mContactEmailTypes.get( |
| mContactEmailTypeSpinner.getSelectedItemPosition()); |
| </pre> |
| <p> |
| O próximo fragmento cria uma operação para inserir a linha de contato bruto |
| na tabela {@link android.provider.ContactsContract.RawContacts}: |
| </p> |
| <pre> |
| /* |
| * Prepares the batch operation for inserting a new raw contact and its data. Even if |
| * the Contacts Provider does not have any data for this person, you can't add a Contact, |
| * only a raw contact. The Contacts Provider will then add a Contact automatically. |
| */ |
| |
| // Creates a new array of ContentProviderOperation objects. |
| ArrayList<ContentProviderOperation> ops = |
| new ArrayList<ContentProviderOperation>(); |
| |
| /* |
| * Creates a new raw contact with its account type (server type) and account name |
| * (user's account). Remember that the display name is not stored in this row, but in a |
| * StructuredName data row. No other data is required. |
| */ |
| ContentProviderOperation.Builder op = |
| ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) |
| .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()) |
| .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()); |
| |
| // Builds the operation and adds it to the array of operations |
| ops.add(op.build()); |
| </pre> |
| <p> |
| Em seguida, o código cria linhas de dados para as linhas de nome de exibição, telefone e e-mail. |
| </p> |
| <p> |
| Cada objeto construtor de operações usa |
| {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} |
| para obter |
| o {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. Os pontos de referência |
| voltam ao objeto {@link android.content.ContentProviderResult} a partir da primeira operação, |
| que adiciona a linha de contato bruto e retorna seu novo valor |
| {@code android.provider.BaseColumns#_ID}. Como resultado, cada linha de dados é automaticamente vinculada por meio do |
| {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} |
| à nova linha {@link android.provider.ContactsContract.RawContacts} à qual ela pertence. |
| </p> |
| <p> |
| O objeto {@link android.content.ContentProviderOperation.Builder} que adiciona a linha de e-mail é |
| sinalizado com {@link android.content.ContentProviderOperation.Builder#withYieldAllowed(boolean) |
| withYieldAllowed()}, que define um ponto de rendimento: |
| </p> |
| <pre> |
| // Creates the display name for the new raw contact, as a StructuredName data row. |
| op = |
| ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) |
| /* |
| * withValueBackReference sets the value of the first argument to the value of |
| * the ContentProviderResult indexed by the second argument. In this particular |
| * call, the raw contact ID column of the StructuredName data row is set to the |
| * value of the result returned by the first operation, which is the one that |
| * actually adds the raw contact row. |
| */ |
| .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) |
| |
| // Sets the data row's MIME type to StructuredName |
| .withValue(ContactsContract.Data.MIMETYPE, |
| ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) |
| |
| // Sets the data row's display name to the name in the UI. |
| .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); |
| |
| // Builds the operation and adds it to the array of operations |
| ops.add(op.build()); |
| |
| // Inserts the specified phone number and type as a Phone data row |
| op = |
| ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) |
| /* |
| * Sets the value of the raw contact id column to the new raw contact ID returned |
| * by the first operation in the batch. |
| */ |
| .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) |
| |
| // Sets the data row's MIME type to Phone |
| .withValue(ContactsContract.Data.MIMETYPE, |
| ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) |
| |
| // Sets the phone number and type |
| .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) |
| .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType); |
| |
| // Builds the operation and adds it to the array of operations |
| ops.add(op.build()); |
| |
| // Inserts the specified email and type as a Phone data row |
| op = |
| ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) |
| /* |
| * Sets the value of the raw contact id column to the new raw contact ID returned |
| * by the first operation in the batch. |
| */ |
| .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) |
| |
| // Sets the data row's MIME type to Email |
| .withValue(ContactsContract.Data.MIMETYPE, |
| ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) |
| |
| // Sets the email address and type |
| .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) |
| .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType); |
| |
| /* |
| * Demonstrates a yield point. At the end of this insert, the batch operation's thread |
| * will yield priority to other threads. Use after every set of operations that affect a |
| * single contact, to avoid degrading performance. |
| */ |
| op.withYieldAllowed(true); |
| |
| // Builds the operation and adds it to the array of operations |
| ops.add(op.build()); |
| </pre> |
| <p> |
| O último fragmento exibe a chamada |
| a {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} que |
| insere as novas linhas de contato bruto e de dados. |
| </p> |
| <pre> |
| // Ask the Contacts Provider to create a new contact |
| Log.d(TAG,"Selected account: " + mSelectedAccount.getName() + " (" + |
| mSelectedAccount.getType() + ")"); |
| Log.d(TAG,"Creating contact: " + name); |
| |
| /* |
| * Applies the array of ContentProviderOperation objects in batch. The results are |
| * discarded. |
| */ |
| try { |
| |
| getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); |
| } catch (Exception e) { |
| |
| // Display a warning |
| Context ctx = getApplicationContext(); |
| |
| CharSequence txt = getString(R.string.contactCreationFailure); |
| int duration = Toast.LENGTH_SHORT; |
| Toast toast = Toast.makeText(ctx, txt, duration); |
| toast.show(); |
| |
| // Log exception |
| Log.e(TAG, "Exception encountered while inserting contact: " + e); |
| } |
| } |
| </pre> |
| <p> |
| As operações de lote também permitem a implementação de <strong>controle otimista de simultaneidade</strong>, |
| um método de aplicar transações de modificação sem precisar bloquear o repositório subjacente. |
| Para usar esse método, aplique a transação e, em seguida, verifique se há outras modificações que |
| possam ter sido realizadas ao mesmo tempo. Se ficar determinado que houve uma modificação incoerente, |
| reverte-se a transação e tenta-se novamente. |
| </p> |
| <p> |
| O controle otimista de simultaneidade é útil para dispositivos móveis em que haja somente um usuário |
| de uma vez e que sejam raros os acessos simultâneos a um repositório de dados. Como os bloqueios não são usados, |
| não há tempo gasto em bloqueios de configuração nem espera para que outras transações liberem os respectivos bloqueios. |
| </p> |
| <p> |
| Para usar o controle otimista de simultaneidade ao atualizar uma única |
| linha {@link android.provider.ContactsContract.RawContacts}, siga estas etapas: |
| </p> |
| <ol> |
| <li> |
| Recupere a coluna {@link android.provider.ContactsContract.SyncColumns#VERSION} |
| do contato bruto em conjunto com os outros dados recuperados. |
| </li> |
| <li> |
| Crie um objeto {@link android.content.ContentProviderOperation.Builder} adequado para |
| forçar uma restrição com o método |
| {@link android.content.ContentProviderOperation#newAssertQuery(Uri)}. Para a URI de conteúdo, |
| use {@link android.provider.ContactsContract.RawContacts#CONTENT_URI |
| RawContacts.CONTENT_URI} |
| com o {@code android.provider.BaseColumns#_ID} do contato bruto anexado a ela. |
| </li> |
| <li> |
| Para o objeto {@link android.content.ContentProviderOperation.Builder}, chame |
| {@link android.content.ContentProviderOperation.Builder#withValue(String, Object) |
| withValue()} para comparar a coluna |
| {@link android.provider.ContactsContract.SyncColumns#VERSION} com o número da versão recém-recuperado. |
| </li> |
| <li> |
| Para o mesmo {@link android.content.ContentProviderOperation.Builder}, chame |
| {@link android.content.ContentProviderOperation.Builder#withExpectedCount(int) |
| withExpectedCount()} para garantir que somente uma linha seja testada por essa instrução. |
| </li> |
| <li> |
| Chame {@link android.content.ContentProviderOperation.Builder#build()} para criar |
| o objeto {@link android.content.ContentProviderOperation}; em seguida, adicione esse objeto como |
| o primeiro objeto na {@link java.util.ArrayList} passada para |
| {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}. |
| </li> |
| <li> |
| Aplique a transação em lote. |
| </li> |
| </ol> |
| <p> |
| Se a linha de contato bruto for atualizada por outra operação entre o momento da leitura da linha |
| e o momento de sua modificação, a "assert" {@link android.content.ContentProviderOperation} |
| falhará e todo o lote de operações será cancelado. Depois disso, as opções são tentar novamente |
| ou tomar outra medida. |
| </p> |
| <p> |
| O fragmento a seguir demonstra como criar uma "assert" |
| {@link android.content.ContentProviderOperation} após consultar um contato bruto exclusivo usando |
| um {@link android.content.CursorLoader}: |
| </p> |
| <pre> |
| /* |
| * The application uses CursorLoader to query the raw contacts table. The system calls this method |
| * when the load is finished. |
| */ |
| public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { |
| |
| // Gets the raw contact's _ID and VERSION values |
| mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); |
| mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); |
| } |
| |
| ... |
| |
| // Sets up a Uri for the assert operation |
| Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactID); |
| |
| // Creates a builder for the assert operation |
| ContentProviderOperation.Builder assertOp = ContentProviderOperation.netAssertQuery(rawContactUri); |
| |
| // Adds the assertions to the assert operation: checks the version and count of rows tested |
| assertOp.withValue(SyncColumns.VERSION, mVersion); |
| assertOp.withExpectedCount(1); |
| |
| // Creates an ArrayList to hold the ContentProviderOperation objects |
| ArrayList ops = new ArrayList<ContentProviderOperationg>; |
| |
| ops.add(assertOp.build()); |
| |
| // You would add the rest of your batch operations to "ops" here |
| |
| ... |
| |
| // Applies the batch. If the assert fails, an Exception is thrown |
| try |
| { |
| ContentProviderResult[] results = |
| getContentResolver().applyBatch(AUTHORITY, ops); |
| |
| } catch (OperationApplicationException e) { |
| |
| // Actions you want to take if the assert operation fails go here |
| } |
| </pre> |
| <h3 id="Intents">Recuperação e modificação com intenções</h3> |
| <p> |
| Enviar uma intenção ao aplicativo de contatos do dispositivo permite o acesso indireto ao Provedor |
| de contatos. A intenção inicia a IU do aplicativo de contatos do dispositivo, na qual os usuários podem |
| fazer tarefas relacionadas a contatos. Com esse tipo de acesso, os usuários podem: |
| <ul> |
| <li>Selecionar um contato de uma lista e retorná-lo ao aplicativo para trabalhos futuros.</li> |
| <li>Editar dados de um contato existente.</li> |
| <li>Inserir um novo contato bruto para quaisquer das suas contas.</li> |
| <li>Excluir um contato ou dados dos contatos.</li> |
| </ul> |
| <p> |
| Se o usuário estiver inserindo ou atualizando dados, é possível coletar os dados antes e enviá-los como |
| parte da intenção. |
| </p> |
| <p> |
| Ao usar intenções para acessar o Provedor de Contatos por meio do aplicativo de contatos do dispositivo, |
| não é necessário criar a própria IU ou código para acessar o provedor. Também não é necessário |
| solicitar permissão de leitura e gravação ao provedor. O aplicativo de contatos do dispositivo pode |
| delegar a você permissões de leitura de um contato e, pelo fato de você fazer modificações |
| no provedor por meio de outro aplicativo, não é necessário ter permissões de gravação. |
| </p> |
| <p> |
| O processo geral de envio de uma intenção para acessar um provedor é descrito detalhadamente |
| no guia<a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a>, seção "Acesso a dados via intenções". Os valores |
| de ação, do tipo MIME e dos dados usados para as tarefas disponíveis são resumidos na tabela 4 |
| e os valores extras que podem ser usados com |
| {@link android.content.Intent#putExtra(String, String) putExtra()} são listados na |
| documentação de referência de {@link android.provider.ContactsContract.Intents.Insert}: |
| </p> |
| <p class="table-caption" id="table4"> |
| <strong>Tabela 4.</strong> Intenções do Provedor de Contatos |
| </p> |
| <table style="width:75%"> |
| <tr> |
| <th scope="col" style="width:10%">Tarefa</th> |
| <th scope="col" style="width:5%">Ação</th> |
| <th scope="col" style="width:10%">Dados</th> |
| <th scope="col" style="width:10%">Tipo MIME</th> |
| <th scope="col" style="width:25%">Observações</th> |
| </tr> |
| <tr> |
| <td><strong>Selecionar um contato de uma lista</strong></td> |
| <td>{@link android.content.Intent#ACTION_PICK}</td> |
| <td> |
| Um dos seguintes: |
| <ul> |
| <li> |
| {@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI}, |
| que exibe uma lista de contatos. |
| </li> |
| <li> |
| {@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI}, |
| que exibe uma lista de números de telefone de um contato bruto. |
| </li> |
| <li> |
| {@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal#CONTENT_URI |
| StructuredPostal.CONTENT_URI}, |
| que exibe uma lista de endereços postais de um contato bruto. |
| </li> |
| <li> |
| {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI}, |
| que exibe uma lista de endereços de e-mail de um contato bruto. |
| </li> |
| </ul> |
| </td> |
| <td> |
| Não usado |
| </td> |
| <td> |
| Exibe uma lista de contatos brutos ou uma lista de dados de um contato bruto conforme |
| o tipo da URI de conteúdo fornecido. |
| <p> |
| Chame |
| {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}, |
| que retorna a URI de conteúdo da linha selecionada. O formulário da URI é a |
| URI de conteúdo da tabela com o <code>LOOKUP_ID</code> da linha anexado a ela. |
| O aplicativo de contatos do dispositivo delega permissões de leitura e gravação a essa URI de conteúdo |
| pelo tempo que a atividade durar. Consulte |
| o guia<a href="{@docRoot}guide/topics/providers/content-provider-basics.html"> |
| Preceitos do provedor de conteúdo</a> para obter mais detalhes. |
| </p> |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Inserir um novo contato bruto</strong></td> |
| <td>{@link android.provider.ContactsContract.Intents.Insert#ACTION Insert.ACTION}</td> |
| <td>Não aplicável</td> |
| <td> |
| {@link android.provider.ContactsContract.RawContacts#CONTENT_TYPE |
| RawContacts.CONTENT_TYPE}, tipo MIME para um grupo de contatos brutos. |
| </td> |
| <td> |
| Exibe a tela <strong>Adicionar contato</strong> do aplicativo de contatos do dispositivo. |
| São exibidos os valores extras adicionados à intenção. Se enviada com |
| {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}, |
| a URI de conteúdo do contato bruto recentemente adicionado é passada de volta |
| ao método de retorno de chamada |
| {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()}no argumento {@link android.content.Intent}, |
| no campo "dados". Para obter o valor, chame {@link android.content.Intent#getData()}. |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Editar um contato</strong></td> |
| <td>{@link android.content.Intent#ACTION_EDIT}</td> |
| <td> |
| {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} |
| do contato. A atividade do editor permitirá que o usuário edite os dados associados |
| a esse contato. |
| </td> |
| <td> |
| {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE |
| Contacts.CONTENT_ITEM_TYPE}, um único contato.</td> |
| <td> |
| Exibe a tela Editar contato no aplicativo de contatos. São exibidos os valores extras |
| adicionados à intenção. Quando o usuário clica em <strong>Concluído</strong> para salvar |
| as edições, a atividade retorna ao primeiro plano. |
| </td> |
| </tr> |
| <tr> |
| <td><strong>Exibir um seletor que também pode adicionar dados.</strong></td> |
| <td>{@link android.content.Intent#ACTION_INSERT_OR_EDIT}</td> |
| <td> |
| Não aplicável |
| </td> |
| <td> |
| {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE} |
| </td> |
| <td> |
| Essa intenção sempre exibe a tela do seletor do aplicativo de contatos. </strong>O usuário pode |
| selecionar um contato para editar ou adicionar um novo. É exibida a tela de edição ou de adição, |
| conforme a escolha do usuário e são exibidos os dados extras passados |
| para a intenção. Se o aplicativo exibe dados de contato como um e-mail ou número de telefone, use |
| essa intenção para permitir que o usuário adicione os dados a um contato existente. |
| |
| <p class="note"> |
| <strong>Observação:</strong> Não é necessário enviar nenhum valor de nome dos extras da intenção |
| porque o usuário sempre seleciona um nome existente ou adiciona um novo. Além disso, |
| se você enviar um nome e o usuário escolher editar, o aplicativo de contatos |
| exibirá o nome enviado, substituindo o valor anterior. Se o usuário |
| não notar isso e salvar a edição, o valor antigo será perdido. |
| </p> |
| </td> |
| </tr> |
| </table> |
| <p> |
| O aplicativo de contatos do dispositivo não permite a exclusão de um contato bruto ou de seus dados |
| com uma intenção. Em vez disso, para excluir um contato bruto, use |
| {@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()} |
| ou {@link android.content.ContentProviderOperation#newDelete(Uri) |
| ContentProviderOperation.newDelete()}. |
| </p> |
| <p> |
| O fragmento a seguir mostra como construir e enviar uma intenção que insira um novo |
| contato bruto e dados: |
| </p> |
| <pre> |
| // Gets values from the UI |
| String name = mContactNameEditText.getText().toString(); |
| String phone = mContactPhoneEditText.getText().toString(); |
| String email = mContactEmailEditText.getText().toString(); |
| |
| String company = mCompanyName.getText().toString(); |
| String jobtitle = mJobTitle.getText().toString(); |
| |
| // Creates a new intent for sending to the device's contacts application |
| Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION); |
| |
| // Sets the MIME type to the one expected by the insertion activity |
| insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); |
| |
| // Sets the new contact name |
| insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name); |
| |
| // Sets the new company and job title |
| insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); |
| insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle); |
| |
| /* |
| * Demonstrates adding data rows as an array list associated with the DATA key |
| */ |
| |
| // Defines an array list to contain the ContentValues objects for each row |
| ArrayList<ContentValues> contactData = new ArrayList<ContentValues>(); |
| |
| |
| /* |
| * Defines the raw contact row |
| */ |
| |
| // Sets up the row as a ContentValues object |
| ContentValues rawContactRow = new ContentValues(); |
| |
| // Adds the account type and name to the row |
| rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType()); |
| rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()); |
| |
| // Adds the row to the array |
| contactData.add(rawContactRow); |
| |
| /* |
| * Sets up the phone number data row |
| */ |
| |
| // Sets up the row as a ContentValues object |
| ContentValues phoneRow = new ContentValues(); |
| |
| // Specifies the MIME type for this data row (all data rows must be marked by their type) |
| phoneRow.put( |
| ContactsContract.Data.MIMETYPE, |
| ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE |
| ); |
| |
| // Adds the phone number and its type to the row |
| phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); |
| |
| // Adds the row to the array |
| contactData.add(phoneRow); |
| |
| /* |
| * Sets up the email data row |
| */ |
| |
| // Sets up the row as a ContentValues object |
| ContentValues emailRow = new ContentValues(); |
| |
| // Specifies the MIME type for this data row (all data rows must be marked by their type) |
| emailRow.put( |
| ContactsContract.Data.MIMETYPE, |
| ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE |
| ); |
| |
| // Adds the email address and its type to the row |
| emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email); |
| |
| // Adds the row to the array |
| contactData.add(emailRow); |
| |
| /* |
| * Adds the array to the intent's extras. It must be a parcelable object in order to |
| * travel between processes. The device's contacts app expects its key to be |
| * Intents.Insert.DATA |
| */ |
| insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData); |
| |
| // Send out the intent to start the device's contacts app in its add contact activity. |
| startActivity(insertIntent); |
| </pre> |
| <h3 id="DataIntegrity">Integridade dos dados</h3> |
| <p> |
| Como o repositório de contatos contém dados importantes e confidenciais que usuários esperam que estejam |
| corretos e atualizados, o Provedor de Contatos tem regras bem definidas para a integridade dos dados. É de |
| sua responsabilidade adequar-se a essas regras ao modificar dados de contatos. As regras |
| importantes são listadas a seguir: |
| </p> |
| <dl> |
| <dt> |
| Sempre adicione uma linha {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} |
| para cada linha {@link android.provider.ContactsContract.RawContacts} adicionada. |
| </dt> |
| <dd> |
| Uma linha {@link android.provider.ContactsContract.RawContacts} sem uma |
| linha {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} |
| na tabela {@link android.provider.ContactsContract.Data} pode causar problemas durante |
| a agregação. |
| </dd> |
| <dt> |
| Sempre conecte novas linhas {@link android.provider.ContactsContract.Data} às respectivas |
| linhas pai {@link android.provider.ContactsContract.RawContacts}. |
| </dt> |
| <dd> |
| Uma linha {@link android.provider.ContactsContract.Data} que não esteja conectada a um |
| {@link android.provider.ContactsContract.RawContacts} não será visível no aplicativo |
| de contatos do dispositivo, o que pode causar problemas com adaptadores de sincronização. |
| </dd> |
| <dt> |
| Altere dados somente para os seus contatos brutos. |
| </dt> |
| <dd> |
| Lembre-se de que o Provedor de Contatos normalmente gerencia dados de diversos tipos de conta |
| e serviços on-line diferentes. É preciso garantir que o aplicativo modifique |
| ou exclua somente dados de linhas que pertencem a você e que ele insira dados apenas |
| com um tipo e nome de conta que você controla. |
| </dd> |
| <dt> |
| Sempre use as constantes definidas em {@link android.provider.ContactsContract} e suas |
| subclasses de autoridades, URIs de conteúdo, caminhos de URI, nomes de coluna, tipos MIME e |
| valores {@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE}. |
| </dt> |
| <dd> |
| O uso dessas constantes ajuda a evitar erros. Você também será notificado com avisos |
| do compilador se uma das constantes não for aprovada. |
| </dd> |
| </dl> |
| <h3 id="CustomData">Linhas de dados personalizados</h3> |
| <p> |
| Ao criar e usar seus próprios tipos MIME personalizados, você pode inserir, editar, excluir e recuperar |
| suas linhas de dados na tabela {@link android.provider.ContactsContract.Data}. As linhas |
| são limitadas a usar a coluna definida em |
| {@link android.provider.ContactsContract.DataColumns}, embora seja possível mapear |
| os nomes de coluna de tipo específico para os nomes de coluna padrão. No aplicativo de contatos do dispositivo, |
| os dados das linhas são exibidos, mas não podem ser editados nem excluídos e os usuários não podem inserir |
| dados adicionais. Para permitir que usuários modifiquem suas linhas de dados personalizados, é necessário fornecer |
| uma atividade do editor no próprio aplicativo. |
| </p> |
| <p> |
| Para exibir os dados personalizados, forneça um arquivo <code>contacts.xml</code> contendo |
| um elemento <code><ContactsAccountType></code> ou um ou mais |
| dos elementos filho <code><ContactsDataKind></code>. Isso é abordado com mais detalhes na |
| seção <a href="#SocialStreamDataKind"><code><ContactsDataKind> element</code></a>. |
| </p> |
| <p> |
| Para saber mais sobre tipos MIME personalizados, leia o |
| guia <a href="{@docRoot}guide/topics/providers/content-provider-creating.html"> |
| Criação de um provedor de conteúdo</a>. |
| </p> |
| <h2 id="SyncAdapters">Adaptadores de sincronização do Provedor de Contatos</h2> |
| <p> |
| O Provedor de Contatos foi projetado especificamente para tratar a <strong>sincronização</strong> |
| de dados de contatos entre um dispositivo e um serviço on-line. Isso permite que usuários baixem |
| dados existentes em um novo dispositivo e transfiram dados existentes a uma nova conta. |
| A sincronização também garante que usuários tenham os dados mais recentes à mão, independentemente |
| da origem de adições e alterações. Outra vantagem da sincronização é |
| a disponibilidade dos dados dos contatos mesmo quando o dispositivo não está conectado à rede. |
| </p> |
| <p> |
| Embora seja possível implementar a sincronização de diversos modos, o sistema Android fornece |
| uma estrutura de sincronização de extensão que automatiza as seguintes tarefas: |
| <ul> |
| |
| <li> |
| Verificação da disponibilidade da rede. |
| </li> |
| <li> |
| Agendamento e execução de sincronizações, com base nas preferências do usuário. |
| </li> |
| <li> |
| Reinicialização de sincronizações que foram interrompidas. |
| </li> |
| </ul> |
| <p> |
| Para usar essa estrutura, deve-se fornecer uma extensão do adaptador de sincronização. Cada adaptador de sincronização é exclusivo |
| de um serviço e um provedor de conteúdo, mas pode tratar diversos nomes de conta do mesmo serviço. |
| A estrutura também permite diversos adaptadores de sincronização para o mesmo serviço e provedor. |
| </p> |
| <h3 id="SyncClassesFiles">Classes e arquivos do adaptador de sincronização</h3> |
| <p> |
| O adaptador de sincronização é implementado como uma subclasse |
| de {@link android.content.AbstractThreadedSyncAdapter} e instalado como parte do aplicativo |
| do Android. O sistema coleta dados do adaptador de sincronização a partir de elementos no manifesto |
| do aplicativo e de um arquivo XML especial direcionado pelo manifesto. O arquivo XML define |
| o tipo de conta do serviço on-line e a autoridade do provedor de conteúdo que, juntos, |
| identificam exclusivamente o adaptador. O adaptador de sincronização não fica ativo até que o usuário adicione |
| uma conta para o tipo de conta do adaptador de sincronização e habilite a sincronização para |
| o provedor de conteúdo com o qual o adaptador se sincroniza. Nesse ponto, o sistema começa a gerenciar o adaptador, |
| chamando-o quando necessário para estabelecer a sincronização entre o provedor de conteúdo e o servidor. |
| </p> |
| <p class="note"> |
| <strong>Observação:</strong> usar um tipo de conta como parte da identificação do adaptador de sincronização permite |
| que o sistema detecte e agrupe adaptadores de sincronização que acessam diferentes serviços |
| da mesma organização. Por exemplo, todos os adaptadores de sincronização dos serviços on-line da Google têm o mesmo |
| tipo de conta <code>com.google</code>. Quando o usuário adiciona uma conta Google aos dispositivos, todos |
| os adaptadores de sincronização dos serviços Google instalados são listados juntos; cada um |
| dos listados sincroniza-se com um provedor de conteúdo diferente no dispositivo. |
| </p> |
| <p> |
| Como a maioria dos serviços exige que usuários verifiquem a identidade antes de acessar |
| os dados, o sistema Android oferece uma estrutura de autenticação similar à estrutura |
| dos adaptadores de sincronização e muitas vezes usada junto com eles. A estrutura de autenticação usa |
| autenticadores de extensão que são subclasses |
| de {@link android.accounts.AbstractAccountAuthenticator}. Um autenticador verifica |
| a identidade do usuário nas seguintes etapas: |
| <ol> |
| <li> |
| Coleta nome, senha ou informação similar do usuário (as <strong>credenciais</strong> |
| do usuário). |
| </li> |
| <li> |
| Envia as credenciais para o serviço |
| </li> |
| <li> |
| Avalia a resposta do serviço. |
| </li> |
| </ol> |
| <p> |
| Se o serviço aceitar as credenciais, o autenticador pode |
| armazená-las para uso futuro. Devido à estrutura do autenticador de extensão, |
| o {@link android.accounts.AccountManager} pode conferir acesso a quaisquer tokens de autenticação compatíveis com |
| um autenticador que escolha expô-los, como os tokens de autenticação OAuth2. |
| </p> |
| <p> |
| Embora as autenticações não sejam necessárias, a maioria dos serviços de contato as usam. |
| Contudo, não é obrigatório usar a estrutura de autenticação do Android para efetuá-las. |
| </p> |
| <h3 id="SyncAdapterImplementing">Implementação do adaptador de sincronização</h3> |
| <p> |
| Para implementar um adaptador de sincronização para o Provedor de Contatos, primeiramente é necessário criar |
| um aplicativo do Android que contenha o seguinte: |
| </p> |
| <dl> |
| <dt> |
| Um componente {@link android.app.Service} que responda a solicitações do sistema para |
| vincular ao adaptador de sincronização. |
| </dt> |
| <dd> |
| Quando o sistema quer executar uma sincronização, ele chama o método |
| {@link android.app.Service#onBind(Intent) onBind()} do serviço para obter |
| um {@link android.os.IBinder} para o adaptador de sincronização. Isso permite que o sistema efetue chamadas |
| entre processos aos métodos do adaptador. |
| <p> |
| No aplicativo |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Exemplo de adaptador de sincronização</a>, o nome de classe desse serviço é |
| <code>com.example.android.samplesync.syncadapter.SyncService</code>. |
| </p> |
| </dd> |
| <dt> |
| O adaptador de sincronização atual, implementado como uma subclasse concreta de |
| {@link android.content.AbstractThreadedSyncAdapter}. |
| </dt> |
| <dd> |
| Essa classe realiza o trabalho de baixar dados do servidor, atualizar dados |
| do dispositivo e resolver conflitos. A principal tarefa do adaptador é |
| feita no método {@link android.content.AbstractThreadedSyncAdapter#onPerformSync( |
| Account, Bundle, String, ContentProviderClient, SyncResult) |
| onPerformSync()}. Essa classe deve ser instanciada como um singleton. |
| <p> |
| No aplicativo |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Exemplo de adaptador de sincronização</a>, o adaptador de sincronização é definido na classe |
| <code>com.example.android.samplesync.syncadapter.SyncAdapter</code>. |
| </p> |
| </dd> |
| <dt> |
| Uma subclasse de {@link android.app.Application}. |
| </dt> |
| <dd> |
| Essa classe atua como uma fábrica para o singleton do adaptador de sincronização. Use |
| o método {@link android.app.Application#onCreate()} para instanciar o adaptador de sincronização |
| e fornecer um método "coletor" estático para retornar o singleton ao |
| método {@link android.app.Service#onBind(Intent) onBind()} do serviço do adaptador |
| de sincronização. |
| </dd> |
| <dt> |
| <strong>Opcional:</strong> um componente {@link android.app.Service} que responda a |
| solicitações do sistema para autenticação do usuário. |
| </dt> |
| <dd> |
| O {@link android.accounts.AccountManager} ativa esse serviço para iniciar o processo |
| de autenticação. O método {@link android.app.Service#onCreate()} do serviço instancia |
| um objeto autenticador. Quando o sistema quer autenticar uma conta de usuário para |
| o adaptador de sincronização do aplicativo, ele chama o método |
| {@link android.app.Service#onBind(Intent) onBind()} do serviço para obter um |
| {@link android.os.IBinder} para o autenticador. Isso permite que o sistema efetue chamadas |
| entre processos aos métodos do autenticador. |
| <p> |
| No aplicativo |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Exemplo de adaptador de sincronização</a>, o nome de classe desse serviço é |
| <code>com.example.android.samplesync.authenticator.AuthenticationService</code>. |
| </p> |
| </dd> |
| <dt> |
| <strong>Opcional:</strong> uma subclasse concreta de |
| {@link android.accounts.AbstractAccountAuthenticator} que trate de solicitações de |
| autenticação. |
| </dt> |
| <dd> |
| Essa classe fornece métodos que chamam {@link android.accounts.AccountManager} |
| para autenticar as credenciais do usuário no servidor. Os detalhes |
| desse processo de autenticação variam amplamente, com base na tecnologia em uso no servidor. Consulte |
| a documentação do software do servidor para ver mais informações sobre autenticação. |
| <p> |
| No aplicativo |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Exemplo de adaptador de sincronização</a>, o autenticador é definido na classe |
| <code>com.example.android.samplesync.authenticator.Authenticator</code>. |
| </p> |
| </dd> |
| <dt> |
| Os arquivos XML que definem o adaptador de sincronização e o autenticador para o sistema. |
| </dt> |
| <dd> |
| Os componentes de serviço do adaptador de sincronização e do autenticador descritos anteriormente são |
| definidos em |
| elementos <code><<a href="{@docRoot}guide/topics/manifest/service-element.html">service</a>></code> |
| no manifesto do aplicativo. Esses elementos |
| contêm |
| elementos filho <code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> |
| que fornecem dados específicos ao |
| sistema: |
| <ul> |
| <li> |
| O |
| elemento <code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> |
| de serviço do adaptador de sincronização direciona-se |
| ao <code>res/xml/syncadapter.xml</code> do arquivo XML. Em troca, esse arquivo especifica |
| uma URI para o serviço web que será sincronizado com o Provedor de Contatos |
| e um tipo de conta. |
| </li> |
| <li> |
| <strong>Opcional:</strong> o |
| elemento <code><<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">meta-data</a>></code> |
| do autenticador aponta para o arquivo XML |
| <code>res/xml/authenticator.xml</code>. Em troca, esse arquivo especifica |
| o tipo de conta compatível com esse autenticador, bem como recursos de IU |
| que aparecem durante o processo de autenticação. O tipo de conta especificado |
| nesse elemento deve ser o mesmo que o especificado para |
| o adaptador de sincronização. |
| </li> |
| </ul> |
| </dd> |
| </dl> |
| <h2 id="SocialStream">Dados de fluxos sociais</h2> |
| <p> |
| As tabelas {@code android.provider.ContactsContract.StreamItems} |
| e {@code android.provider.ContactsContract.StreamItemPhotos} |
| gerenciam dados advindos de redes sociais. É possível criar um adaptador de sincronização que adicione dados de fluxo |
| da sua própria rede a essas tabelas ou ler dados de fluxo dessas tabelas |
| e exibi-los no seu aplicativo, ou ambos. Com esses recursos, os serviços e aplicativos |
| de redes sociais podem ser integrados na experiência das redes sociais no Android. |
| </p> |
| <h3 id="StreamText">Textos de fluxos sociais</h3> |
| <p> |
| Itens de fluxo sempre são associados a um contato bruto. |
| O {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} conecta-se ao |
| valor <code>_ID</code> do contato bruto. O tipo e o nome da conta do contato |
| bruto também são armazenados na linha do item de fluxo. |
| </p> |
| <p> |
| Armazene os dados do seu fluxo nas colunas a seguir: |
| </p> |
| <dl> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE} |
| </dt> |
| <dd> |
| <strong>Obrigatório.</strong> O tipo de conta do usuário do contato bruto associado a esse |
| item de fluxo. Lembre-se de definir esse valor ao inserir um item de fluxo. |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME} |
| </dt> |
| <dd> |
| <strong>Obrigatório.</strong> O nome de conta do usuário do contato bruto associado |
| a esse item de fluxo. Lembre-se de definir esse valor ao inserir um item de fluxo. |
| </dd> |
| <dt> |
| Colunas identificadoras |
| </dt> |
| <dd> |
| <strong>Obrigatório.</strong> É necessário inserir as colunas identificadoras a seguir |
| ao inserir um item de fluxo: |
| <ul> |
| <li> |
| {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}: |
| o valor {@code android.provider.BaseColumns#_ID} do contato ao qual esse item |
| de fluxo está associado. |
| </li> |
| <li> |
| {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}: |
| o valor{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} do |
| contato ao qual esse item de fluxo está associado. |
| </li> |
| <li> |
| {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}: |
| o valor {@code android.provider.BaseColumns#_ID} do contato bruto ao qual esse item |
| de fluxo está associado. |
| </li> |
| </ul> |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemsColumns#COMMENTS} |
| </dt> |
| <dd> |
| Opcional. Armazena informações resumidas que podem ser exibidas no início do item de fluxo. |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemsColumns#TEXT} |
| </dt> |
| <dd> |
| O texto do item de fluxo, o conteúdo que foi publicado pela fonte do item |
| ou uma descrição de alguma ação que gerou o item de fluxo. Essa coluna pode conter |
| imagens de recurso incorporadas e de qualquer formato que possam ser renderizadas |
| {@link android.text.Html#fromHtml(String) fromHtml()}. O provedor pode truncar |
| ou abreviar conteúdos longos, mas ele tentará evitar quebrar as tags. |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} |
| </dt> |
| <dd> |
| Uma string de texto contendo o tempo em que o item de fluxo foi inserido ou atualizado, em forma |
| de <em>milissegundos</em> desde a época. Aplicativos que inserem ou atualizam itens de fluxo são |
| responsáveis por manter essa coluna, ela não é mantida automaticamente pelo |
| Provedor de Contatos. |
| </dd> |
| </dl> |
| <p> |
| Para exibir informações de identificação para os itens de fluxo, use |
| {@code android.provider.ContactsContract.StreamItemsColumns#RES_ICON}, |
| {@code android.provider.ContactsContract.StreamItemsColumns#RES_LABEL} e |
| {@code android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE} para vincular a recursos |
| no aplicativo. |
| </p> |
| <p> |
| A tabela {@code android.provider.ContactsContract.StreamItems} também contém as colunas |
| {@code android.provider.ContactsContract.StreamItemsColumns#SYNC1} por meio de |
| {@code android.provider.ContactsContract.StreamItemsColumns#SYNC4} para uso exclusivo |
| dos adaptadores de sincronização. |
| </p> |
| <h3 id="StreamPhotos">Fotos de fluxos sociais</h3> |
| <p> |
| A tabela {@code android.provider.ContactsContract.StreamItemPhotos} armazena fotos associadas |
| a um item de fluxo. A coluna |
| {@code android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID} da tabela |
| vincula-se a valores na coluna {@code android.provider.BaseColumns#_ID} |
| da tabela {@code android.provider.ContactsContract.StreamItems}. Referências de fotografias são armazenadas |
| na tabela nessas colunas: |
| </p> |
| <dl> |
| <dt> |
| Coluna {@code android.provider.ContactsContract.StreamItemPhotos#PHOTO} (um BLOB). |
| </dt> |
| <dd> |
| Representação binária da foto, redimensionada pelo provedor para armazenar e exibir. |
| Essa coluna está disponível para compatibilidade retroativa com versões anteriores do Provedor |
| de Contatos que a usavam para armazenar fotos. Contudo, na versão atual, |
| não se deve usar essa coluna para armazenar fotos. Em vez disso, use |
| {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} ou |
| {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (ambas são |
| descritas nos pontos a seguir) para armazenar fotos em um arquivo. Essa coluna |
| passa a conter uma miniatura da foto, que estará disponível para leitura. |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} |
| </dt> |
| <dd> |
| Identificador numérico de uma foto de um contato bruto. Anexe esse valor à constante |
| {@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI} |
| para obter uma URI de conteúdo direcionada para um único arquivo de foto e, em seguida, chame |
| {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) |
| openAssetFileDescriptor()} para obter um identificador para o arquivo de foto. |
| </dd> |
| <dt> |
| {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} |
| </dt> |
| <dd> |
| URI de conteúdo direcionada diretamente para o arquivo de foto da foto representada por essa linha. |
| Chame {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) |
| openAssetFileDescriptor()} com essa URI para obter um identificador para o arquivo de foto. |
| </dd> |
| </dl> |
| <h3 id="SocialStreamTables">Uso de tabelas de fluxos sociais</h3> |
| <p> |
| Essas tabelas funcionam como as outras tabelas principais do Provedor de Contatos, exceto que: |
| </p> |
| <ul> |
| <li> |
| Exigem permissões de acesso adicionais. Para ler o conteúdo delas, o aplicativo |
| deve ter a permissão {@code android.Manifest.permission#READ_SOCIAL_STREAM}. Para |
| modificá-las, o aplicativo precisa ter a permissão |
| {@code android.Manifest.permission#WRITE_SOCIAL_STREAM}. |
| </li> |
| <li> |
| Para a tabela {@code android.provider.ContactsContract.StreamItems}, o número de linhas |
| armazenadas para cada contato bruto é limitado. Ao atingir o limite, |
| o Provedor de Contatos abre espaço para novas linhas de itens de fluxo excluindo automaticamente |
| as linhas que têm |
| o {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP} mais antigo. Para conhecer |
| o limite, faça uma consulta à URI de conteúdo |
| {@code android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}. É possível deixar |
| todos os argumentos, exceto a URI de conteúdo, definidos como <code>null</code>. A consulta |
| retorna um Cursor contendo uma linha única com a coluna única |
| {@code android.provider.ContactsContract.StreamItems#MAX_ITEMS}. |
| </li> |
| </ul> |
| |
| <p> |
| A classe {@code android.provider.ContactsContract.StreamItems.StreamItemPhotos} define |
| uma subtabela de {@code android.provider.ContactsContract.StreamItemPhotos} que contém as linhas |
| de foto de um único item de fluxo. |
| </p> |
| <h3 id="SocialStreamInteraction">Interações de fluxos sociais</h3> |
| <p> |
| Os dados de fluxos sociais gerenciados pelo Provedor de Contatos, em conjunto com o |
| aplicativo de contatos do dispositivo, oferecem um método poderoso de conexão ao sistema de redes sociais |
| com contatos existentes. Os seguintes recursos estão disponíveis: |
| </p> |
| <ul> |
| <li> |
| Ao sincronizar seu serviço de rede social com o Provedor de Contatos com um adaptador |
| de sincronização, é possível recuperar atividades recentes de contatos de um usuário e armazená-las |
| nas tabelas {@code android.provider.ContactsContract.StreamItems} |
| e {@code android.provider.ContactsContract.StreamItemPhotos} para uso posterior. |
| </li> |
| <li> |
| Além da sincronização regular, é possível ativar o adaptador de sincronização para recuperar |
| dados adicionais quando o usuário seleciona um contato para exibir. Isso permite que o adaptador de sincronização |
| recupere fotos de alta resolução e os itens de fluxo mais recentes do contato. |
| </li> |
| <li> |
| Ao registrar uma notificação com o aplicativo de contatos do dispositivo e o Provedor |
| de Contatos, é possível <em>recuperar</em> uma intenção quando um contato é exibido e, nesse ponto, |
| atualizar o status do contato pelo serviço. Essa abordagem pode ser mais rápida e usar menos |
| largura de banda do que realizar uma sincronização completa com um adaptador de sincronização. |
| </li> |
| <li> |
| Os usuários podem adicionar um contato ao seu serviço de rede social enquanto exibem-no |
| no aplicativo de contatos do dispositivo. É possível ativar isso com o recurso "convidar contato", |
| que é ativado com uma combinação de uma atividade que adiciona um contato existente à sua |
| rede, um arquivo XML que fornece o aplicativo de contatos do dispositivo |
| e o Provedor de Contatos com os detalhes do aplicativo. |
| </li> |
| </ul> |
| <p> |
| A sincronização regular de itens de fluxo com o Provedor de Contatos é igual |
| a outras sincronizações. Para saber mais sobre sincronizações, consulte a seção |
| <a href="#SyncAdapters">Adaptadores de sincronização do Provedor de Contatos</a>. O registro de notificações |
| e o convite a contatos são abordados nas próximas duas seções. |
| </p> |
| <h4>Registro para manipular exibições de redes sociais</h4> |
| <p> |
| Para registrar o adaptador de sincronização para receber notificações quando o usuário exibe um contato que é |
| gerenciado pelo adaptador de sincronização: |
| </p> |
| <ol> |
| <li> |
| Crie um arquivo chamado <code>contacts.xml</code> no diretório <code>res/xml/</code> |
| do projeto. Se você já tiver esse arquivo, pule esta etapa. |
| </li> |
| <li> |
| Nesse arquivo, adicione o elemento |
| <code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code>. |
| Se esse elemento já existir, pule esta etapa. |
| </li> |
| <li> |
| Para registrar um serviço que seja notificado quando o usuário abre uma página de detalhes do contato |
| no aplicativo de contatos do dispositivo, adicione o atributo |
| <code>viewContactNotifyService="<em>serviceclass</em>"</code> ao elemento, em que |
| <code><em>serviceclass</em></code> é o nome de classe totalmente qualificado do serviço |
| que deve receber a intenção do aplicativo de contatos do dispositivo. Para o serviço |
| de notificação, use a classe que estende {@link android.app.IntentService} para permitir que o serviço |
| receba intenções. Os dados nas intenções recebidas contêm a URI de conteúdo do contato |
| bruto em que o usuário clicou. No serviço de notificação, é possível vincular e chamar |
| o adaptador de sincronização para atualizar os dados do contato bruto. |
| </li> |
| </ol> |
| <p> |
| Para registrar uma atividade a ser chamada quando o usuário clica em um item de fluxo ou foto, ou ambos: |
| </p> |
| <ol> |
| <li> |
| Crie um arquivo chamado <code>contacts.xml</code> no diretório <code>res/xml/</code> |
| do projeto. Se você já tiver esse arquivo, pule esta etapa. |
| </li> |
| <li> |
| Nesse arquivo, adicione o elemento |
| <code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code>. |
| Se esse elemento já existir, pule esta etapa. |
| </li> |
| <li> |
| Para registrar uma das atividades para tratar do usuário que clica em um item de fluxo |
| no aplicativo de contatos do dispositivo, adicione o atributo |
| <code>viewStreamItemActivity="<em>activityclass</em>"</code> ao elemento, em que |
| <code><em>activityclass</em></code> é o nome de classe totalmente qualificado da atividade |
| que deve receber a intenção do aplicativo de contatos do dispositivo. |
| </li> |
| <li> |
| Para registrar uma das atividades para tratar do usuário que clica em uma foto de fluxo |
| no aplicativo de contatos do dispositivo, adicione o atributo |
| <code>viewStreamItemPhotoActivity="<em>activityclass</em>"</code> ao elemento, em que |
| <code><em>activityclass</em></code> é o nome de classe totalmente qualificado da atividade |
| que deve receber a intenção do aplicativo de contatos do dispositivo. |
| </li> |
| </ol> |
| <p> |
| O elemento <code><ContactsAccountType></code> é descrito em mais detalhes |
| na seção <a href="#SocialStreamAcctType">Elemento <ContactsAccountType></a>. |
| </p> |
| <p> |
| A intenção recebida contém a URI de conteúdo do item ou foto em que o usuário clicou. |
| Para ter atividades separadas para itens de texto e para fotos, use os dois atributos no mesmo arquivo. |
| </p> |
| <h4>Interação com o serviço de redes sociais</h4> |
| <p> |
| Os usuários não precisam sair do aplicativo de contatos do dispositivo para convidar um contato para |
| seu site de contatos. Em vez disso, o aplicativo de contatos do dispositivo pode enviar uma intenção de convidar |
| o contato para uma das atividades. Para configurar isso: |
| </p> |
| <ol> |
| <li> |
| Crie um arquivo chamado <code>contacts.xml</code> no diretório <code>res/xml/</code> |
| do projeto. Se você já tiver esse arquivo, pule esta etapa. |
| </li> |
| <li> |
| Nesse arquivo, adicione o elemento |
| <code><ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"></code>. |
| Se esse elemento já existir, pule esta etapa. |
| </li> |
| <li> |
| Adicione os seguintes atributos: |
| <ul> |
| <li><code>inviteContactActivity="<em>activityclass</em>"</code></li> |
| <li> |
| <code>inviteContactActionLabel="@string/<em>invite_action_label</em>"</code> |
| </li> |
| </ul> |
| O valor <code><em>activityclass</em></code> é o nome de classe totalmente qualificado |
| da atividade que deve receber a intenção. O valor <code><em>invite_action_label</em></code> |
| é uma string de texto exibida no menu <strong>Adicionar conexão</strong> |
| no aplicativo de contatos do dispositivo. |
| </li> |
| </ol> |
| <p class="note"> |
| <strong>Observação:</strong> <code>ContactsSource</code> é um nome de tag reprovado para |
| <code>ContactsAccountType</code>. |
| </p> |
| <h3 id="ContactsFile">Referência do contacts.xml</h3> |
| <p> |
| O arquivo <code>contacts.xml</code> contém elementos XML que controlam a interação |
| do adaptador de sincronização e o aplicativo com o aplicativo de contatos e o Provedor de Contatos. Esses |
| elementos são descritos nas seções a seguir. |
| </p> |
| <h4 id="SocialStreamAcctType">Elemento <ContactsAccountType></h4> |
| <p> |
| O elemento <code><ContactsAccountType></code> controla a interação |
| do aplicativo com o aplicativo de contatos. Ele tem a seguinte sintaxe: |
| </p> |
| <pre> |
| <ContactsAccountType |
| xmlns:android="http://schemas.android.com/apk/res/android" |
| inviteContactActivity="<em>activity_name</em>" |
| inviteContactActionLabel="<em>invite_command_text</em>" |
| viewContactNotifyService="<em>view_notify_service</em>" |
| viewGroupActivity="<em>group_view_activity</em>" |
| viewGroupActionLabel="<em>group_action_text</em>" |
| viewStreamItemActivity="<em>viewstream_activity_name</em>" |
| viewStreamItemPhotoActivity="<em>viewphotostream_activity_name</em>"> |
| </pre> |
| <p> |
| <strong>contido em:</strong> |
| </p> |
| <p> |
| <code>res/xml/contacts.xml</code> |
| </p> |
| <p> |
| <strong>pode conter:</strong> |
| </p> |
| <p> |
| <strong><code><ContactsDataKind></code></strong> |
| </p> |
| <p> |
| <strong>Descrição:</strong> |
| </p> |
| <p> |
| Declara componentes e etiquetas da IU do Android que permitem aos usuários convidar um dos seus contatos a |
| uma rede social, notificar usuários quando um dos seus fluxos de redes sociais é atualizado |
| etc. |
| </p> |
| <p> |
| Observe que o prefixo <code>android:</code> do atributo não é necessário para os atributos |
| de <code><ContactsAccountType></code>. |
| </p> |
| <p> |
| <strong>Atributos:</strong> |
| </p> |
| <dl> |
| <dt>{@code inviteContactActivity}</dt> |
| <dd> |
| O nome de classe totalmente qualificado da atividade no aplicativo que você deseja |
| ativar quando o usuário seleciona <strong>Adicionar conexão</strong> no aplicativo |
| de contatos do dispositivo. |
| </dd> |
| <dt>{@code inviteContactActionLabel}</dt> |
| <dd> |
| Uma string de texto exibida para a atividade especificada |
| em {@code inviteContactActivity}, no menu <strong>Adicionar conexão</strong>. |
| Por exemplo: você pode usar a string "Siga-me na rede". Você pode usar um identificador |
| do recurso da string nessa etiqueta. |
| </dd> |
| <dt>{@code viewContactNotifyService}</dt> |
| <dd> |
| O nome de classe totalmente qualificado de um serviço no aplicativo que deve receber |
| notificações de quando o usuário exibe um contato. Essa notificação é enviada pelo aplicativo |
| de contatos do dispositivo, isso permite que o aplicativo adie operações de dados intensivos |
| até que elas sejam necessárias. Por exemplo: o aplicativo pode responder a essa notificação |
| lendo e exibindo a foto de alta resolução do contato e os itens de fluxo social |
| mais recentes. Esse recurso é descrito com mais detalhes na seção |
| <a href="#SocialStreamInteraction">Interações de fluxos sociais</a>. É possível ver |
| um exemplo de serviço de notificação no arquivo <code>NotifierService.java</code> |
| no aplicativo de exemplo |
| <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a>. |
| </dd> |
| <dt>{@code viewGroupActivity}</dt> |
| <dd> |
| O nome de classe totalmente qualificado de uma atividade no aplicativo que pode exibir |
| informações de grupo. Quando o usuário clica na etiqueta do grupo no aplicativo |
| de contatos do dispositivo, a IU dessa atividade é exibida. |
| </dd> |
| <dt>{@code viewGroupActionLabel}</dt> |
| <dd> |
| A etiqueta que o aplicativo de contatos exibe para um controle de IU que permite |
| que o usuário veja grupos no seu aplicativo. |
| <p> |
| Por exemplo: se você instalar o aplicativo do Google+ no dispositivo e sincronizá-lo |
| com o aplicativo de contatos, verá os círculos do Google+ listados como grupos |
| na aba <strong>Grupos</strong> do aplicativo de contatos. Ao clicar |
| em um círculo do Google+, você verá pessoas nesse círculo listadas como um "grupo". Na parte superior |
| da tela, você verá um ícone do Google+; ao clicar nele, o controle muda para |
| o aplicativo do Google+. O aplicativo de contatos faz isso com |
| {@code viewGroupActivity} usando o ícone como o valor |
| de {@code viewGroupActionLabel}. |
| </p> |
| <p> |
| Um identificador de recurso de string é permitido para esse atributo. |
| </p> |
| </dd> |
| <dt>{@code viewStreamItemActivity}</dt> |
| <dd> |
| O nome de classe totalmente qualificado de uma atividade no aplicativo que |
| o aplicativo de contatos do dispositivo executa quando o usuário clica em um item de fluxo de um contato bruto. |
| </dd> |
| <dt>{@code viewStreamItemPhotoActivity}</dt> |
| <dd> |
| O nome de classe totalmente qualificado de uma atividade no aplicativo que |
| o aplicativo de contatos do dispositivo executa quando o usuário clica em uma foto no item de fluxo |
| de um contato bruto. |
| </dd> |
| </dl> |
| <h4 id="SocialStreamDataKind">Elemento <ContactsDataKind></h4> |
| <p> |
| O elemento <code><ContactsDataKind></code> controla a tela das linhas de dados |
| personalizados do aplicativo na IU do aplicativo de contatos. Ele tem a seguinte sintaxe: |
| </p> |
| <pre> |
| <ContactsDataKind |
| android:mimeType="<em>MIMEtype</em>" |
| android:icon="<em>icon_resources</em>" |
| android:summaryColumn="<em>column_name</em>" |
| android:detailColumn="<em>column_name</em>"> |
| </pre> |
| <p> |
| <strong>contido em:</strong> |
| </p> |
| <code><ContactsAccountType></code> |
| <p> |
| <strong>Descrição:</strong> |
| </p> |
| <p> |
| Use esse elemento para que o aplicativo de contatos exiba o conteúdo de uma linha de dados personalizados como |
| parte dos detalhes de um contato bruto. Cada elemento filho <code><ContactsDataKind></code> |
| de <code><ContactsAccountType></code> representa um tipo de linha de dados personalizados que o adaptador |
| de sincronização adiciona à tabela {@link android.provider.ContactsContract.Data}. Adicione |
| um elemento <code><ContactsDataKind></code> para cada tipo MIME personalizado usado. Não será necessário |
| adicionar o elemento se você tiver uma linha de dados personalizados para a qual não deseja exibir dados. |
| </p> |
| <p> |
| <strong>Atributos:</strong> |
| </p> |
| <dl> |
| <dt>{@code android:mimeType}</dt> |
| <dd> |
| O tipo MIME personalizado definido para um dos tipos de linha de dados personalizados |
| na tabela {@link android.provider.ContactsContract.Data}. Por exemplo: o valor |
| <code>vnd.android.cursor.item/vnd.example.locationstatus</code> poderia ser um tipo MIME |
| personalizado para uma linha de dados que registra a última localização conhecida do contato. |
| </dd> |
| <dt>{@code android:icon}</dt> |
| <dd> |
| |
| <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Recurso desenhável</a> do Android |
| que o aplicativo de contatos exibe próximo aos dados. Use isso para indicar |
| ao usuário que os dados são advindos do seu serviço. |
| </dd> |
| <dt>{@code android:summaryColumn}</dt> |
| <dd> |
| O nome de coluna do primeiro de dois valores recuperados da linha de dados. |
| O valor é exibido como a primeira linha da entrada para essa linha de dados. A primeira linha |
| destina-se ao uso como um resumo dos dados, mas isso é opcional. Veja também |
| <a href="#detailColumn">android:detailColumn</a>. |
| </dd> |
| <dt>{@code android:detailColumn}</dt> |
| <dd> |
| O nome de coluna do segundo de dois valores recuperados da linha de dados. O valor é |
| exibido como a segunda linha da entrada dessa linha de dados. Veja também |
| {@code android:summaryColumn}. |
| </dd> |
| </dl> |
| <h2 id="AdditionalFeatures">Recursos adicionais do Provedor de Contatos</h2> |
| <p> |
| Além dos principais recursos descritos nas seções anteriores, o Provedor de Contatos oferece |
| estes recursos úteis para trabalhar com dados de contatos: |
| </p> |
| <ul> |
| <li>Grupos de contatos</li> |
| <li>Recursos de foto</li> |
| </ul> |
| <h3 id="Groups">Grupos de contatos</h3> |
| <p> |
| O Provedor de Contatos pode, opcionalmente, etiquetar grupos de contatos relacionados com |
| dados de <strong>grupo</strong>. Se o servidor associado a uma conta de usuário |
| deseja manter grupos, o adaptador de sincronização para o tipo da conta deve transferir |
| dados de grupo entre o Provedor de Contatos e o servidor. Quando o usuário adiciona um novo contato |
| ao servidor e, em seguida, coloca este contato em um novo grupo, o adaptador de sincronização deve adicionar o novo grupo |
| na tabela {@link android.provider.ContactsContract.Groups}. O grupo ou grupos a que um contato |
| bruto pertence são armazenados na tabela {@link android.provider.ContactsContract.Data}, usando |
| o tipo MIME {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership}. |
| </p> |
| <p> |
| Se estiver projetando um adaptador de sincronização que adicionará dados de contato bruto ao Provedor de Contatos |
| a partir de servidores e não estiver usando grupos, será necessário fazer com que |
| o provedor torne os dados visíveis. No código que é executado quando um usuário adiciona uma conta |
| ao dispositivo, atualize a linha {@link android.provider.ContactsContract.Settings} |
| que o Provedor de Contatos adicionou para a conta. Nessa linha, defina o valor da |
| coluna {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE |
| Settings.UNGROUPED_VISIBLE} como 1. Ao fazê-lo, o Provedor de Contatos sempre |
| deixará os dados de contatos visíveis, mesmo sem usar grupos. |
| </p> |
| <h3 id="Photos">Fotos de contatos</h3> |
| <p> |
| A tabela {@link android.provider.ContactsContract.Data} armazena fotos como linhas com tipo MIME |
| {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE |
| Photo.CONTENT_ITEM_TYPE}. A coluna |
| {@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} da linha é vinculada |
| à coluna {@code android.provider.BaseColumns#_ID} do contato bruto à qual pertence. |
| A classe {@link android.provider.ContactsContract.Contacts.Photo} define uma subtabela de |
| {@link android.provider.ContactsContract.Contacts} contendo informações de foto |
| de uma foto principal do contato, que é a foto principal do contato bruto principal do contato. Da mesma forma, |
| a classe {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} define uma subtabela |
| de {@link android.provider.ContactsContract.RawContacts} contendo informações de foto |
| de uma foto principal do contato bruto. |
| </p> |
| <p> |
| A documentação de referência de {@link android.provider.ContactsContract.Contacts.Photo} e |
| {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} contém exemplos |
| de recuperação de informações de foto. Não há classe conveniente para recuperar a miniatura |
| principal de um contato bruto, mas é possível enviar uma consulta |
| à tabela {@link android.provider.ContactsContract.Data}, selecionando no {@code android.provider.BaseColumns#_ID} |
| do contato bruto, o |
| {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE |
| Photo.CONTENT_ITEM_TYPE} e a coluna |
| {@link android.provider.ContactsContract.Data#IS_PRIMARY} para encontrar a linha da foto principal do contato bruto. |
| </p> |
| <p> |
| Dados de fluxos sociais de uma pessoa também podem conter fotos. Elas são armazenadas |
| na tabela {@code android.provider.ContactsContract.StreamItemPhotos}, que é descrita com mais |
| detalhes na seção <a href="#StreamPhotos">Fotos de fluxos sociais</a>. |
| </p> |