Notícias sobre produtos

Uma maneira mais confiável de adicionar e editar contatos no Android

Leitura de 6 min
Ver o perfil de Roxanna Aliabadi Walker
Roxanna Aliabadi Walker Gerente de produtos, Android

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: 

Figure01_01_Quick_Insert_Half_Sheet_Prefilled.png
Captura de tela 2 - Título: Modelo de tela cheia para criar um novo contato: captura de tela de uma interface do usuário do Android mostrando um editor de contatos em tela cheia com um seletor de avatar, campos de nome, telefone e e-mail. O design está marcado como "UX not Final" (UX não finalizada).

Figura 1: criar um novo contato  *UX não final*

Figure02_01_Add_To_Existing_0_Search_State_Half_Sheet.png
Captura de tela 2 – Título: modelo de página inteira de "Adicionar informações a um contato existente": captura de tela de uma interface do usuário do Android em teste mostrando um editor de contatos em tela cheia com um seletor de avatar e campos de nome, telefone e e-mail. O design de página inteira apresenta ícones de divulgação progressiva para campos secundários. O design está marcado como "UX not Final" (UX não finalizada).

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_ACCOUNT sugere 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_URI transmite 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 WRITE_CONTACTS (resulta em uma SecurityException ou negação de permissão quando o app é destinado à próxima versão do Android).

 

// 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 ACTION_EDIT com o URI desse contato:

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 aplicativoSe 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 eventosSe 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 VoIPEm 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 nuvemSe 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.DATA com tipos MIME diferentes dos tipos ContactsContract.CommonDataKinds padrão, esses tipos MIME serão ignorados pelo editor.
  • SHOW_OR_CREATE_CONTACT nã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, use ACTION_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_CONTACTS vai resultar em um SecurityException 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_URI e applyBatch(ContactsContract.AUTHORITY, …).
  • Substitua cada gravação orientada pelo usuário por uma intent:ACTION_INSERT para novos contatos e ACTION_EDIT ou ACTION_INSERT_OR_EDIT para 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_CONTACTS usando a tabela acima. Se sim, planeje sua declaração do Play Console.
  • Remova WRITE_CONTACTS do manifesto quando nenhum caminho de código precisar dele.

Cronograma

QuandoO que acontece
21 de outubro de 2026O 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 AndroidO 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_CONTACTS se 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.
  • 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_CONTACTS podem excluir contatos diretamente.
  • 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ó.
  • A permissão MANAGE_CONTACTS substitui READ_CONTACTS?
    • MANAGE_CONTACTS inclui acesso de leitura, então não é necessário solicitar ambos, mas muitos apps se qualificam para READ_CONTACTS sem precisar modificar os contatos. Esses apps podem continuar solicitando READ_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_CONTACTS no manifesto com um maxSdkVersion adequado.
Escrito por:
Continue lendo