Práticas recomendadas de permissões do app

Solicitações de permissão protegem informações confidenciais disponíveis em um dispositivo e só devem ser usadas quando o acesso às informações é necessário para o funcionamento do app. Este documento fornece dicas sobre como obter os mesmos recursos (ou melhores) sem exigir o acesso a essas informações. Não se trata de uma discussão completa sobre o funcionamento das permissões no sistema operacional Android.

Para uma perspectiva mais geral das permissões do Android, consulte a Visão geral das permissões do app. Para ver detalhes sobre como trabalhar com permissões no seu código, consulte Solicitar permissões do app.

Princípios de como trabalhar com as permissões do Android

Recomendamos seguir estes princípios ao trabalhar com permissões do Android:

Nº 1: use apenas as permissões necessárias para o funcionamento do seu aplicativo. Dependendo de como você usa as permissões, pode haver outra maneira de fazer o que for necessário (intents do sistema, identificadores, coleta de informações para chamadas telefônicas) sem precisar de acesso a informações confidenciais.

Nº 2: preste atenção às permissões exigidas pelas bibliotecas. Ao incluir uma biblioteca, você também herda os requisitos de permissões dela. Você precisa estar ciente do que está incluindo, das permissões necessárias e do uso dessas permissões.

Nº 3: seja transparente. Ao fazer uma solicitação de permissão, seja claro sobre o que você está acessando e por que, para que os usuários possam tomar decisões informadas. Disponibilize essas informações juntamente com a solicitação de permissão, incluindo caixas de diálogo de permissões de instalação, tempo de execução ou atualização.

Nº 4: deixe os acessos do sistema explícitos. Ao fornecer indicações contínuas ao acessar recursos importantes (como a câmera ou o microfone), você deixa claro para os usuários quando está coletando dados e evita a percepção de que essa coleta está sendo feita clandestinamente.

As demais seções deste guia detalham essas regras no contexto do desenvolvimento de aplicativos Android.

Permissões no Android 6.0 e em versões posteriores

O Android 6.0 Marshmallow introduziu um novo modelo de permissões que permite aos apps solicitar permissões do usuário no tempo de execução, em vez de antes da instalação. Os apps compatíveis com o novo modelo solicitam permissões quando de fato precisam dos serviços ou dos dados protegidos pelos serviços. Embora isso não (necessariamente) mude o comportamento geral do app, foram feitas algumas mudanças relevantes na forma de processamento dos dados confidenciais do usuário:

Aumento no contexto situacional: os usuários recebem uma solicitação no tempo de execução, no contexto do app, para concederem permissão de acesso ao recurso incluído nesses grupos de permissões. Os usuários estão mais atentos ao contexto em que a permissão é solicitada e, em caso de incompatibilidade entre a solicitação e o propósito do app, é ainda mais importante fornecer explicações detalhadas sobre o motivo da solicitação de permissão. Sempre que possível, forneça uma explicação no momento da solicitação e em uma caixa de diálogo de acompanhamento se o usuário a negar.

Mais flexibilidade na concessão de permissões: os usuários podem negar acesso a permissões individuais no momento em que são solicitadas e nas configurações, mas ainda assim eles poderão se surpreender se um recurso for inutilizado como resultado. É recomendável monitorar quantos usuários estão negando permissões (por exemplo, usando o Google Analytics) para que você possa adaptar seu aplicativo dependendo da permissão ou fornecer uma explicação melhor sobre a necessidade da permissão para o funcionamento adequado do app. Certifique-se também de que seu app processe as exceções criadas quando os usuários negam solicitações de permissão ou desativam as permissões nas configurações.

Aumento da carga de transações: é solicitado aos usuários que concedam acesso para grupos de permissões individualmente, e não como um conjunto. Dessa forma, é extremamente importante minimizar o número de permissões solicitadas, já que isso aumenta o trabalho do usuário em conceder permissões e a probabilidade de pelo menos uma delas ser negada.

Evite solicitar permissões desnecessárias

Sempre que você pede uma permissão, o usuário é forçado a tomar uma decisão. Diminua o número de solicitações realizadas. Se o usuário estiver executando o Android 6.0 (nível de API 23) ou posterior, sempre que ele testar um novo recurso que exija uma permissão, o app precisará interromper o trabalho do usuário com uma solicitação de permissão. Se o usuário estiver executando uma versão anterior do Android, ele precisará conceder todas as permissões do app ao instalá-lo e, se a lista for longa demais ou parecer inapropriada, o usuário poderá decidir não instalar o app. Por esses motivos, você precisa minimizar o número de permissões necessárias do app.

Esta seção fornece alternativas para casos de uso comuns que ajudarão a limitar o número de solicitações de permissões realizadas. Como o número e o tipo de permissões mostradas para o usuário afetam os downloads em comparação a outros apps semelhantes que solicitam menos permissões, é recomendável evitar a solicitação de permissões para recursos desnecessários.

Use um intent

Em vários casos, é possível escolher entre duas maneiras de realização de uma tarefa por um app. O app pede permissão para realizar a tarefa em si ou pode usar o intent para fazer com que outro app a realize.

Por exemplo, imagine que o app precisa da função de tirar fotos com a câmera do dispositivo. O app pode solicitar a permissão CAMERA, que concede acesso direto à câmera. Assim, o app usará as APIs da câmera para controlá-la e tirar uma foto. Essa abordagem fornece a ele um controle completo sobre o processo de fotografia e permite que você incorpore a IU da câmera no app.

No entanto, se a exigência de acesso aos dados do usuário for pouco frequente, em outras palavras, não causar muito incômodo para o usuário receber uma caixa de diálogo de tempo de execução toda vez que o acesso aos dados for necessário, você poderá usar uma solicitação baseada em intent. O Android fornece alguns intents de sistema que os aplicativos podem usar sem solicitar permissões, já que o usuário escolhe o que quer compartilhar com o app, se for o caso, no momento em que a solicitação baseada em intent é emitida.

Por exemplo, um tipo de ação de intent de MediaStore.ACTION_IMAGE_CAPTURE ou MediaStore.ACTION_VIDEO_CAPTURE pode ser usado para capturar imagens ou vídeos sem usar diretamente o objeto Camera (ou solicitar a permissão). Nesse caso, o intent do sistema solicitará a permissão do usuário em seu nome sempre que uma imagem for capturada.

De forma semelhante, caso você precise fazer uma chamada, acessar os contatos do usuário etc., é possível realizar essas ações criando um intent adequado ou solicitar a permissão e o acesso aos objetos relevantes diretamente. Há vantagens e desvantagens em cada abordagem.

Uso de permissões:

  • O app tem controle total sobre a experiência do usuário quando você realiza a operação. No entanto, esse controle amplo aumenta a complexidade do seu código, levando em consideração a necessidade de projetar uma IU adequada.
  • É solicitado que o usuário conceda permissão uma vez no tempo de execução ou no momento da instalação, dependendo da versão do Android utilizada. Depois, o app pode realizar a operação sem precisar de mais interações do usuário. No entanto, se o usuário não conceder a permissão (ou revogá-la posteriormente), o app não conseguirá realizar a operação.

Uso de intent:

  • Você não precisa projetar a IU para a operação. O app que processa o intent fornece a IU.
  • O usuário pode usar o app que preferir para a tarefa. Por exemplo, o usuário pode selecionar o app de fotos favorito dele para tirar uma foto.
  • Se o usuário não tiver um app padrão para a operação, o sistema solicitará que ele escolha um. Caso o usuário não designe um gerenciador padrão, talvez ele passe por outra caixa de diálogo sempre que realizar a operação.

Não sobrecarregue o usuário

Se o usuário estiver usando a versão 6.0 do Android (nível de API 23) ou posterior, ele precisará conceder as permissões do app durante a execução. Se forem exibidas várias solicitações de permissão de uma só vez ao usuário, é possível que ele se sinta sobrecarregado e saia do app. Em vez disso, solicite as permissões somente quando necessário.

Em alguns casos, uma ou mais permissões podem ser absolutamente essenciais para o app. Pode parecer sensato solicitar todas essas permissões assim que o app é iniciado. Por exemplo, se você criar um app de fotografia, ele precisará de acesso à câmera do dispositivo. Quando o usuário iniciar o app pela primeira vez, ele não se surpreenderá quando receber uma solicitação de permissão para usar a câmera. Mas, se o mesmo app tiver um recurso para compartilhar fotos com os contatos do usuário, o ideal é não pedir a permissão READ_CONTACTS na primeira inicialização. Em vez disso, espere o usuário tentar usar o recurso de compartilhamento para solicitar a permissão.

Se o app fornecer um tutorial, faz sentido solicitar as permissões necessárias no final da sequência do tutorial.

Pause a mídia quando o áudio de outro app for selecionado para o primeiro plano

Neste caso, seu app precisa ser executado em segundo plano quando o usuário recebe uma chamada e voltar ao foco somente quando a chamada for finalizada.

A abordagem comum nesses casos, por exemplo, pausar ou silenciar um player de mídia durante uma chamada, é ouvir as mudanças no estado da chamada usando PhoneStateListener ou ouvir a transmissão de android.intent.action.PHONE_STATE. O problema com essa solução é que ela exige a permissão READ_PHONE_STATE, que força o usuário a conceder acesso a uma grande seção de dados confidenciais, como os códigos do hardware do dispositivo e do chip e o número de telefone da chamada recebida.

Você pode detectar se um usuário está em uma chamada telefônica sem as permissões READ_PHONE_STATE ou MODIFY_PHONE_STATE: solicite AudioFocus para seu app, o que não exige permissões explícitas, já que não há acesso a informações confidenciais. Basta inserir o código necessário para colocar o áudio em segundo plano no manipulador de eventos onAudioFocusChange(), e ele será executado automaticamente quando o SO alterar a seleção do áudio. Encontre aqui uma documentação mais detalhada sobre como fazer isso.

Determine o dispositivo em que sua instância está sendo executada

Neste caso, você precisa de um identificador exclusivo para determinar em qual dispositivo a instância do seu app está sendo executada.

Os aplicativos podem ter preferências ou mensagens específicas do dispositivo, por exemplo, salvar uma playlist específica do dispositivo na nuvem para que o usuário possa ter uma playlist diferente no carro e em casa. Uma solução comum é usar identificadores de dispositivos, como Device IMEI, mas isso exige o grupo de permissões Device ID and call information (PHONE no M+). Também é possível usar um identificador que não pode ser redefinido e que é compartilhado em todos os apps.

Existem duas alternativas para o uso desses tipos de identificadores:

  1. Use a API InstanceID com.google.android.gms.iid. getInstance(Context context).getID() retornará um identificador exclusivo do dispositivo para a instância do seu aplicativo. O resultado é um identificador com o escopo da instância do app que pode ser usado como chave ao armazenar informações sobre o app e que será redefinido se o usuário reinstalar o app.
  2. Crie seu próprio identificador com escopo do armazenamento do seu app usando funções básicas como randomUUID().

Crie um identificador exclusivo para análises de publicidade ou de usuários

Neste caso, você precisa de um identificador exclusivo para criar um perfil para usuários que não se conectaram ao seu app (por exemplo, para direcionar anúncios ou medir as conversões).

Às vezes, a criação de um perfil para análise de publicidade e de usuários exige um identificador compartilhado por outros aplicativos. Soluções comuns para isso envolvem o uso de identificadores de dispositivo como Device IMEI, que exige o grupo de permissões Device ID and call information (PHONE no nível de API 23 e superiores) e que não pode ser redefinido pelo usuário. Em qualquer um desses casos, além de usar um identificador que não pode ser redefinido e solicitar uma permissão que pode parecer estranha aos usuários, você também estará violando as Políticas do programa pra desenvolvedores do Google Play.

Infelizmente, nesses casos, o uso das funções do sistema ou da API InstanceID com.google.android.gms.iid para criar um código com o escopo do app não é uma solução apropriada, já que o código pode precisar ser compartilhado entre apps. Uma solução alternativa é usar o Advertising Identifier disponível na classe AdvertisingIdClient.Info pelo método getId(). Você pode criar um objeto AdvertisingIdClient.Info usando o método getAdvertisingIdInfo(Context) e chamar o método getId() para usar o identificador. Esse método é bloqueador, portanto, não o chame pela thread principal. Encontre aqui uma explicação detalhada sobre esse método.

Conheça as bibliotecas com que está trabalhando

Às vezes, as bibliotecas que você usa no seu aplicativo exigem permissões. Por exemplo, bibliotecas de anúncios ou de análise podem exigir acesso aos grupos de permissões Location ou Identity para implementar os recursos necessários. No entanto, do ponto de vista do usuário, a solicitação de permissão é enviada pelo seu app, não pela biblioteca.

Assim como os usuários selecionam apps que usam menos permissões para proporcionar os mesmos recursos, os desenvolvedores precisam analisar as bibliotecas e selecionar SDKs de terceiros que não usem permissões desnecessárias. Por exemplo, procure evitar bibliotecas que exijam o grupo de permissões Identity, a não ser que exista uma razão clara e compreensível para o usuário da necessidade dessas permissões. Especificamente, para bibliotecas que fornecem o recurso de localização, certifique-se de que não seja necessário solicitar a permissão FINE_LOCATION a não ser que você esteja usando recursos de segmentação baseados na localização.

Explique por que as permissões são necessárias

A caixa de diálogo de permissões exibida pelo sistema ao chamar requestPermissions() informa quais permissões o app solicita, mas não explica o motivo. Em alguns casos, o usuário pode achar isso confuso. É uma boa ideia explicar ao usuário por que as permissões são necessárias para o app antes de chamar requestPermissions().

Pesquisas mostram que os usuários se sentem muito mais à vontade com solicitações de permissões quando sabem por que o app precisa delas. Um estudo com usuários revelou que:

...a disposição de um usuário de conceder determinada permissão a um app para dispositivos móveis é fortemente influenciada pelo propósito associado a essa permissão. Por exemplo, a disposição de um usuário de permitir o acesso à localização varia de acordo com o motivo da solicitação: se ela é necessária para oferecer suporte a um recurso essencial do app ou se é usada para compartilhar a informação com uma rede de publicidade ou empresa de análise.1

Com base na pesquisa realizada pelo grupo dele, o Professor Jason Hong da CMU concluiu que, de forma geral:

... quando as pessoas sabem por que um app está utilizando uma informação tão importante quanto a localização, por exemplo, para anúncios segmentados, elas ficam mais à vontade do que ficariam ao serem simplesmente informadas de que um app está usando a localização delas.1

Consequentemente, se você só estiver usando uma fração das chamadas de API que se encaixam em um grupo de permissões, será relevante listar de maneira explícita quais permissões estão sendo usadas e o porquê. Exemplo:

  • Se você só estiver usando a localização aproximada, informe isso ao usuário na descrição do app ou em artigos de ajuda sobre ele.
  • Se você precisar de acesso a mensagens SMS para receber códigos de autenticação que protejam o usuário contra fraude, informe isso na descrição do app e/ou na primeira vez que acessar os dados.

    Observação: se o app for destinado ao Android 8.0 (nível de API 26) ou posterior, não solicite a permissão READ_SMS como parte da verificação das credenciais de um usuário. Em vez disso, gere um token específico do app usando createAppSpecificSmsToken() e passe esse token para outro app ou serviço que possa enviar uma mensagem SMS de verificação.

Em certas condições, também é pertinente informar os usuários sobre acessos a dados confidenciais em tempo real. Por exemplo, caso você esteja acessando a câmera ou o microfone, geralmente é recomendável informar o usuário com um ícone de notificação em algum lugar do app ou na bandeja de notificações (se o aplicativo estiver sendo executado em segundo plano) para que não pareça que os dados estão sendo coletados clandestinamente.

Por fim, se você precisar solicitar permissão para que um recurso do seu app seja executado, mas o motivo não estiver claro para o usuário, encontre uma maneira de informar por que você precisa das permissões mais confidenciais.

Teste ambos os modelos de permissões

A partir do Android 6.0 (nível de API 23), os usuários concedem e revogam permissões do app no tempo de execução, em vez de fazerem isso durante a instalação. Consequentemente, você precisará testar seu app em um conjunto mais amplo de condições. Antes do Android 6.0, você podia presumir que, se seu app estivesse em execução, ele tinha todas as permissões declaradas no manifest. A partir do Android 6.0, o usuário pode ativar ou desativar qualquer app, até mesmo um app com nível de API 22 ou inferior. Você precisa testar para garantir que seu app funcione corretamente, independentemente de ter ou não permissões.

As dicas a seguir ajudarão você a encontrar problemas de código relacionados a permissões em dispositivos com o nível de API 23 ou superior:

  • Identifique as permissões atuais do aplicativo e os caminhos de código relacionados.
  • Teste o fluxo de usuários entre serviços e dados protegidos por permissão.
  • Teste várias combinações de permissões concedidas ou revogadas. Por exemplo, um app de câmera pode listar CAMERA, READ_CONTACTS e ACCESS_FINE_LOCATION no manifest. Você precisa testar o app com cada uma das permissões ativada e desativada para garantir que ele possa funcionar em todas as configurações de permissão corretamente.
  • Use a ferramenta adb para gerenciar permissões na linha de comando:
    • Liste as permissões e os status por grupo:
      $ adb shell pm list permissions -d -g
    • Conceda ou revogue uma ou mais permissões:
      $ adb shell pm [grant|revoke] <permission-name> ...
  • Analise o aplicativo para descobrir os serviços que usam permissões.

Recursos adicionais

Referências

[1] Modeling Users’ Mobile App Privacy Preferences: Restoring Usability in a Sea of Permission Settings, de J. Lin B. Liu, N. Sadeh e J. Hong. Nos procedimentos do SOUPS 2014.