Como as bibliotecas podem adicionar silenciosamente permissões ao seu aplicativo Android

Outro dia, eu estava checando pedidos de suporte para o Glucosio , um aplicativo de Diabetes que estou construindo, quando encontrei um e-mail de um usuário reclamando sobre algumas “permissões invasivas” que estávamos pedindo.

Minha primeira reação foi: o que? Estávamos apenas pedindo permissões de gravação de armazenamento (para exportar dados e estatísticas), acesso ao sensor NFC para receber dados de sensores (como FreeStyle Libre) e acesso à rede , para nossa API de pesquisa e feedback do usuário. Eles não eram invasivos, considerando que hoje muitos aplicativos na loja precisam de acesso à Internet.

Então, decidi visitar nosso Console do desenvolvedor do Google Play para verificar as permissões com o apk de produção . Isso é o que eu encontrei:

Mais uma vez, minha reação foi: o quê? Gravar audio? Acesso de microfone? Mesmo?

Eu abri meu editor e verifiquei o Manifesto de Glucosio novamente.

 <? xml version = "1.0" encoding = "utf-8"?> 
<manifest xmlns: android = "http://schemas.android.com/apk/res/android"
xmlns: tools = "http://schemas.android.com/tools"
package = "org.glucosio.android">

<usa-permission android: nome = "android.permission.NFC" android: required = "false" />
<usa-recurso android: nome = "android.hardware.nfc" android: required = "false" />
<uses-permission android: name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

<! - Obrigatório para Instabug ->
<uses-permission android: name = "$ {applicationId} .permission.C2D_MESSAGE" />
<permissão
android: name = "$ {applicationId} .permission.C2D_MESSAGE"
android: protectionLevel = "assinatura" />

Nenhum vestígio dessa permissão de gravação de áudio. Então de onde isso veio?

A resposta é bem simples: as bibliotecas externas que você usa no seu aplicativo podem definir silenciosamente permissões adicionais no seu apk final, mesmo que você não as declare no seu manifesto Android .

Para identificar essas permissões, você tem 2 recursos importantes ao seu lado: o Registro de Fusão de Manifesto e o Manifesto final de seu aplicativo. Cada vez que você cria um aplicativo para Android, uma nova compilação / pasta é gerada no diretório do projeto. O verdadeiro manifesto final está em algum lugar lá. De fato, se olharmos

 app / build / intermediates / manifests / full / debug / AndroidManifest.xml 

você verá o arquivo final do manifesto .

 <? xml version = "1.0" encoding = "utf-8"?> 
<manifest xmlns: android = "http://schemas.android.com/apk/res/android"
package = "org.glucosio.android.daily"
android: versionCode = "12"
android: versionName = "0.10.0-DEVEL">

<uses-sdk
android: minSdkVersion = "16"
android: targetSdkVersion = "23" />

<uses-permission
android: name = "android.permission.NFC"
android: required = "false" />

<uses-feature
android: name = "android.hardware.nfc"
android: required = "false" />

<uses-permission android: name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<! - Obrigatório para Instabug ->
<uses-permission android: name = "org.glucosio.android.daily.permission.C2D_MESSAGE" />

<permissão android: name = "org.glucosio.android.daily.permission.C2D_MESSAGE"
android: protectionLevel = "assinatura" />

<uses-permission android: name = "android.permission.INTERNET" />
<uses-permission android: name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android: name = "android.permission.VIBRATE" />
<uses-permission android: name = "android.permission.ACCESS_WIFI_STATE" />
<uses-permission android: name = "android.permission.RECORD_AUDIO" />
<uses-permission android: name = "android.permission.WAKE_LOCK" />
<uses-permission android: name = "com.google.android.c2dm.permission.RECEIVE" />

<permissão
android: name = "com.instabug.library.permission.C2D_MESSAGE"
android: protectionLevel = "assinatura" />

<uses-permission android: name = "com.instabug.library.permission.C2D_MESSAGE" />

Como você pode ver, finalmente encontramos nossa permissão de gravação de áudio. Esse manifesto é o resultado de uma mesclagem do seu Manifesto principal com os de todas as bibliotecas que você está incluindo no aplicativo. Então, de onde veio exatamente essa permissão de áudio de gravação? Dê uma olhada em

 app / build / outputs / logs / manifesto-merger-debug-report.txt 

Este é um arquivo muito grande, então vou colar aqui as partes interessantes:

 - Mesclando log de árvore de decisão --- 
manifesto
 ADICIONADO de [com.google.android.gms: play-services-analytics: 8.4.0] /home/paolo/dev/glucosio/glucosio-android/app/build/intermediates/exploded-aar/com.google.android. gms / play-services-analytics / 8.4.0 / AndroidManifest.xml: 22: 22–76 
usa permissão # android.permission.VIBRATE
 ADICIONADO de [ com.instabug.library: instabug: 2.1.1 ] /home/paolo/dev/glucosio/glucosio-android/app/build/intermediates/exploded-aar/com.instabug.library/instabug/2.1.1/ AndroidManifest.xml: 12: 22–73 
usa permissão # android.permission.RECORD_AUDIO
 ADICIONADO de [com.instabug.library: instabug: 2.1.1] /home/paolo/dev/glucosio/glucosio-android/app/build/intermediates/exploded-aar/com.instabug.library/instabug/2.1.1/ AndroidManifest.xml: 13: 22–68 
usa permissão # android.permission.WAKE_LOCK

e assim por diante … Portanto, cada biblioteca de terceiros está adicionando uma nova permissão ao seu arquivo de manifesto final. Por exemplo, o Google Play Services adicionou a Vibrate Permission e Instabug (a ferramenta que usamos para o feedback do usuário) está, de fato, solicitando a permissão Gravar áudio.

Eu verifiquei as funcionalidades do Instabug e realmente não há necessidade de pedir uma permissão invasiva como essa. Provavelmente, eles o adicionaram para uma versão futura que possivelmente poderia permitir que o usuário enviasse feedback com reconhecimento de fala (?).

EDIT : Instabug recentemente adicionou um novo recurso que permite adicionar anotações de voz como um anexo a um relatório de bug. Eles me garantem que a próxima versão do SDK deles terá esse recurso como opção, em vez de ser desativada. Obrigado rapazes 🙂

Então, como você pode se livrar disso?

Apenas declare a permissão incriminada em seu (principal) Manifesto com o

 ferramentas: node = "remove" 

atributo (sim, é exatamente assim que consertamos ).

Por exemplo:

 <uses-permission android: name = ”android.permission.RECORD_AUDIO” ferramentas: node = ”remove” /> 

Mesmo que outra biblioteca esteja solicitando essa permissão específica, a compilação será forçada a não mesclá-la no arquivo final do manifesto.

Há outra dica geral embora. Bibliotecas grandes, como o Google Play Services, geralmente exigem muitas permissões para funcionar bem. É por isso que você nunca deve incluir a dependência genérica do Google Play Services no seu aplicativo. Em vez disso, o Google oferece a você bibliotecas mais direcionadas , como análise de serviços de jogos ou mapas de serviços de jogos, que limitarão o número de permissões necessárias e farão com que seu apk final seja menor também.