Uma maneira mais confiável de adicionar e editar contatos no Android
Leitura de 6 min
O que está mudando
Os apps destinados à próxima versão do Android não poderão mais gravar diretamente nos contatos com a permissão WRITE_CONTACTS. Em vez disso, use as intents de contato padrão (ACTION_INSERT, ACTION_EDIT e ACTION_INSERT_OR_EDIT). Para uma implementação de referência completa, consulte o guia para desenvolvedores sobre como modificar contatos usando intents.
Em dispositivos com a próxima versão do Android, essas três intents de contato vão se comportar de maneira consistente e não vão precisar de nenhuma permissão. Se o app for destinado à próxima versão do Android ou mais recente e tentar gravar diretamente nos contatos, essas gravações serão rejeitadas e vão resultar em um SecurityException ou na negação da permissão. Para o pequeno conjunto de apps que exigem acesso amplo para criar e modificar contatos, uma nova permissão especial de acesso a apps, MANAGE_CONTACTS, chega no Android 17 QPR2 (4º trimestre de 2026). O Google Play está publicando hoje diretrizes atualizadas para o acesso a contatos, incluindo o MANAGE_CONTACTS.
Por que estamos fazendo isso
Atualmente, se o app precisa salvar um único contato, talvez você esteja solicitando WRITE_CONTACTS. No entanto, essa permissão concede acesso amplo, permitindo que um app faça mudanças em todos os contatos do dispositivo em segundo plano, mesmo sem interação do usuário. A maioria dos apps não precisa de uma permissão tão ampla.
Embora existam alternativas, vocês nos disseram que elas precisam ser mais padronizadas em todo o ecossistema. Antes, as intents de contato se comportavam de maneira diferente em cada dispositivo. Alguns editores descartaram os dados que você transmitiu, como uma foto de contato. Em alguns dispositivos, o botão "Voltar" salvava o contato sem que o usuário quisesse, ou a opção "Criar novo contato" era difícil de encontrar. Por isso, pedir permissão foi a escolha mais racional. Estamos corrigindo todos esses problemas na próxima versão do Android e exigindo que os dispositivos que a executam sigam os mesmos padrões.
O que usar em vez disso
Adicionar ou editar um contato: use as intents de contato
Quando você usa essas intents (ACTION_INSERT, ACTION_EDIT e ACTION_INSERT_OR_EDIT), o sistema cuida do trabalho pesado apresentando uma experiência de editor de contatos limpa e padronizada. Ele abre um formulário rápido de meia página para novas entradas ou permite que o usuário pesquise e adicione informações a um contato atual. Os usuários podem expandir isso para um editor de página inteira e preencher mais detalhes, sem que o app precise de permissões de gravação direta. Confira abaixo os modelos de UX provisórios:
Figura 1: criar um novo contato *UX não final*
Figura 2: Adicionar informações a um contato atual *UX não final*
Observação:diferentes fabricantes de dispositivos podem modificar a experiência do usuário para corresponder ao estilo do SO, mas o comportamento vai permanecer consistente.
Para simplificar ainda mais o processo de criação, transmita payloads de dados opcionais, conhecidos como Extras, junto com a intent:
EXTRA_ACCOUNTsugere em qual conta o contato será salvo, o que ajuda se o app sincronizar contatos. Esse extra já existia, mas o suporte variava de acordo com o dispositivo. A partir da próxima versão do Android, o suporte será padronizado em todos os dispositivos.EXTRA_PHOTO_URItransmite uma foto para preencher automaticamente a imagem do contato. O editor processa a permissão de leitura do URI para você. Essa é uma novidade da próxima versão do Android e será compatível com todo o ecossistema.
Antes: gravação direta com
// Requires android.permission.WRITE_CONTACTS fun saveContactDirectly(context: Context, name: String, phone: String, account: Account) { val ops = arrayListOf( ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .build() ) context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) }
| Depois: abrir o editor de contatos (nenhuma permissão necessária)
fun saveContactWithEditor( context: Context, name: String, phone: String, account: Account, photoUri: Uri ) { val intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI).apply { putExtra(ContactsContract.Intents.Insert.NAME, name) putExtra(ContactsContract.Intents.Insert.PHONE, phone) // Suggest which account the contact is saved to putExtra(ContactsContract.Intents.Insert.EXTRA_ACCOUNT, account) // New in the upcoming Android release: pre-fill the contact photo putExtra(ContactsContract.Intents.Insert.EXTRA_PHOTO_URI, photoUri) clipData = ClipData.newRawUri("", photoUri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } context.startActivity(intent) }
|
Antes: atualizar um contato diretamente
// Requires android.permission.WRITE_CONTACTS fun addPhoneDirectly(context: Context, rawContactId: Long, phone: String) { val values = ContentValues().apply { put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } context.contentResolver.insert(ContactsContract.Data.CONTENT_URI, values) } | Depois: permitir que o usuário escolha um contato para atualizar ou criar um novo fun addPhoneWithEditor(context: Context, phone: String) { val intent = Intent(Intent.ACTION_INSERT_OR_EDIT).apply { type = ContactsContract.Contacts.CONTENT_ITEM_TYPE putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) } Se você já sabe qual contato atualizar, use fun editKnownContact(context: Context, contactUri: Uri, phone: String) { val intent = Intent(Intent.ACTION_EDIT, contactUri).apply { putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) }
|
Escolher um contato: use o seletor de contatos
Se você só precisa ler os contatos que o usuário escolhe, use o Seletor de Contatos, disponível desde o Android 17. Ele não precisa de permissão.
Apps de ligações e mensagens: use o Diretório de Pessoas
Alguns apps adicionam ações como "Ligar com…" ou "Enviar mensagem com…" aos contatos para que as pessoas possam iniciar uma chamada ou um chat no app Telefone ou Contatos. Se o seu app faz isso hoje gravando entradas extras nos contatos do usuário, mude para o Diretório de pessoas, que será lançado no Android QPR2 (4º trimestre de 2026). É um novo diretório do sistema em que o app publica como as pessoas podem se comunicar umas com as outras no app, sem editar os contatos do usuário.
Exemplos de como os apps podem migrar
Para entender como essas alternativas funcionam na prática, confira alguns exemplos de como diferentes tipos de apps podem abordar o acesso aos contatos:
| Exemplo de tipo de app (não exclusivo). | Caminho de migração recomendado |
| Apps de redes sociais, pagamento P2P e transporte por aplicativo | Se o app permite que os usuários encontrem amigos, dividam uma conta ou compartilhem o status de uma viagem, você não precisa de permissões de acesso aos contatos. Use o seletor de contatos para selecionar um contato uma única vez e inicie ACTION_INSERT com EXTRA_PHOTO_URI quando um usuário tocar em "Salvar nos contatos" em um perfil. |
| Scanners de cartões de visita e apps de networking para eventos | Se o app ler um crachá ou QR code e salvar um novo contato ou adicionar um número de telefone comercial à entrada de um colega, use ACTION_INSERT ou ACTION_INSERT_OR_EDIT. O editor de meia página padronizado preenche automaticamente os campos analisados (nome, empresa, telefone, e-mail e foto) para que o usuário possa verificar e salvar com um toque, sem conceder permissões em segundo plano. |
| Apps de chamadas e mensagens VoIP | Em vez de solicitar que o WRITE_CONTACTS injete linhas personalizadas "Ligar com…" ou "Enviar mensagem com…" na lista de endereços do usuário, publique metadados de acessibilidade pelo Diretório de pessoas e use ACTION_INSERT quando os usuários adicionarem um novo contato de uma conversa. |
| Apps de CRM empresarial e sincronização na nuvem | Se o app realizar a sincronização contínua e bidirecional de contatos em segundo plano com uma conta corporativa ou na nuvem, em que não é viável solicitar ao usuário uma interface de intent para cada registro, ele se qualifica para declarar MANAGE_CONTACTS . |
Mudanças a serem verificadas
- Os tipos de dados personalizados não são compatíveis com o editor. Se você transmitir linhas
Insert.DATAcom tipos MIME diferentes dos tiposContactsContract.CommonDataKindspadrão, esses tipos MIME serão ignorados pelo editor. SHOW_OR_CREATE_CONTACTnão é processado pelo editor do sistema. Os apps Contatos que vêm com o dispositivo ainda podem lidar com isso. Para um comportamento consistente em todos os dispositivos, useACTION_INSERT_OR_EDIT.- As gravações falham por padrão. Depois de segmentar a próxima versão do Android, qualquer gravação direta sem
MANAGE_CONTACTSvai resultar em umSecurityException or permission denial. Faça um teste.
Preciso do MANAGE_CONTACTS?
Provavelmente não. Se o app salva ou edita contatos porque um usuário pediu, as intents acima cobrem você, sem permissão e sem declaração do Play Console.
MANAGE_CONTACTS é para apps que têm como objetivo principal gerenciar contatos, em que as intents não são suficientes. Exemplo:
| Seu app… | Precisa de MANAGE_CONTACTS? |
| Salva um contato de um chat, cartão de visita ou pedido. | Não,use ACTION_INSERT |
| Adiciona um número ou e-mail a um contato. | Não,use ACTION_INSERT_OR_EDIT ou ACTION_EDIT |
| Permite que os usuários escolham contatos para convidar, compartilhar ou pagar. | Não,use o Seletor de contatos |
| Adiciona ações de chamada ou mensagem aos contatos. | Não,usar o Diretório de pessoas |
| Tem uma tela de edição de contatos própria. | Não,uma interface personalizada por si só não se qualifica. |
| É um gerenciador de contatos dedicado ou um app de substituição do discador. | Provavelmente sim |
| É um app de identificador de chamadas e proteção contra spam que atualiza em massa as entradas da lista de endereços. | Provavelmente sim |
| Sincroniza contatos com uma conta corporativa ou na nuvem em segundo plano. | Provavelmente sim |
| Faz backup/restauração de contatos em massa ou transferência de smartphone entre dispositivos. | Provavelmente sim |
| Define toques personalizados para contatos individuais. | Provavelmente sim |
Como funciona:
MANAGE_CONTACTSé uma permissão de acesso especial a apps. Não é uma caixa de diálogo de ambiente de execução. Os usuários podem ativar essa opção em Configurações > Acesso especial para apps > Gerenciar contatos.
// Opens Settings > Apps > Special app access > Manage contacts val intent = Intent(Settings.ACTION_MANAGE_CONTACTS, Uri.fromParts("package", packageName, null)) context.startActivity(intent)
- Isso inclui ler, adicionar, editar e excluir contatos, contas e dados do Diretório de Pessoas. Você também não precisa solicitar
READ_CONTACTS. - Para publicar no Google Play com o
MANAGE_CONTACTS, envie uma declaração no Play Console explicando por que as intents não são suficientes para a funcionalidade principal do app.
Etapas de migração
- Encontre as gravações de contato. Pesquise no código por
WRITE_CONTACTS,ContactsContract.RawContacts.CONTENT_URI,ContactsContract.Data.CONTENT_URIeapplyBatch(ContactsContract.AUTHORITY, …). - Substitua cada gravação orientada pelo usuário por uma intent:
ACTION_INSERTpara novos contatos eACTION_EDITouACTION_INSERT_OR_EDITpara atualizações. - Use apenas tipos de dados padrão no
Insert.DATA. Mover as ações de chamada ou mensagem para o Diretório de Pessoas. - Decida se você realmente precisa do
MANAGE_CONTACTSusando a tabela acima. Se sim, planeje sua declaração do Play Console. - Remova
WRITE_CONTACTSdo manifesto quando nenhum caminho de código precisar dele.
Cronograma
| Quando | O que acontece |
| 21 de outubro de 2026 | O Google Play anuncia a política de MANAGE_CONTACTS |
| 2026 (lançamento trimestral de plataforma 2 do Android 17) | A permissão MANAGE_CONTACTS fica disponível |
| 2027 (próxima versão do Android) | A permissão WRITE_CONTACTS não concede mais acesso de gravação a apps destinados à próxima versão do Android. As intents de contato são padronizadas em todos os dispositivos |
| 2027, não antes da próxima versão do Android | O Play Console pede que os apps que usam MANAGE_CONTACTS enviem uma declaração |
| 2027, não antes da próxima versão do Android | É necessário obedecer às políticas do Google Play |
Perguntas frequentes
- Isso afeta todos os apps?
- A descontinuação do
WRITE_CONTACTSse aplica apenas a apps destinados à próxima versão do Android e posteriores. Os apps destinados a versões mais antigas mantêm o comportamento atual. No entanto, o novo editor de contatos padronizado vai estar disponível para todos os apps em execução no novo SO, independente do SDK de destino.
- A descontinuação do
- Meu app pode excluir contatos com intent?
- Não. Não há uma intent para excluir contatos. Os usuários excluem contatos no app Contatos. Os apps com
MANAGE_CONTACTSpodem excluir contatos diretamente.
- Não. Não há uma intent para excluir contatos. Os usuários excluem contatos no app Contatos. Os apps com
- Já tenho minha própria tela de edição de contatos. Posso ficar com ele?
- Somente se o app se qualificar para o
MANAGE_CONTACTS. Querer manter um design personalizado não é um motivo qualificado por si só.
- Somente se o app se qualificar para o
- A permissão
MANAGE_CONTACTSsubstitui READ_CONTACTS?MANAGE_CONTACTSinclui acesso de leitura, então não é necessário solicitar ambos, mas muitos apps se qualificam paraREAD_CONTACTSsem precisar modificar os contatos. Esses apps podem continuar solicitandoREAD_CONTACTS.
- E os usuários com versões mais antigas do Android?
- As intents de contato também funcionam em versões mais antigas, processadas pelo app de contatos do dispositivo. A maioria dos apps funciona bem em todos os dispositivos que usam essas intents. Se o app for afetado por um problema de consistência específico que só foi resolvido nas versões mais recentes, mantenha a permissão
WRITE_CONTACTSno manifesto com um maxSdkVersion adequado.
- As intents de contato também funcionam em versões mais antigas, processadas pelo app de contatos do dispositivo. A maioria dos apps funciona bem em todos os dispositivos que usam essas intents. Se o app for afetado por um problema de consistência específico que só foi resolvido nas versões mais recentes, mantenha a permissão
-
Notícias sobre produtosNo Google I/O 2026, apresentamos a mudança do Android de um sistema operacional para um sistema de inteligência. Também mostramos como criar experiências inteligentes de forma nativa com o sistema e levar o poder da IA do Google para seus apps.
Jingyu Shi • Leitura de 2 min -
Notícias sobre produtosEste ano, no Google I/O, vamos além das mudanças iterativas, em direção a uma mudança fundamental na forma como os apps são criados. Nossas ferramentas mais recentes foram criadas para a era agêntica, com recursos que aumentam sua produtividade como desenvolvedor Android E turbinam os agentes de IA que você implanta na sua base de código.
Matthew Warner • Leitura de 8 min -
Notícias sobre produtosAnunciado hoje durante o The Android Show, o Android está fazendo a transição de um sistema operacional para um sistema de inteligência, criando mais oportunidades de engajamento com seus apps.
Matthew McCullough • Leitura de 4 min
Receba os insights mais recentes sobre o desenvolvimento para Android na sua caixa de entrada toda semana.