shouldShowRequestPermissionRationale é um método da API do Android que indica ao desenvolvedor se deve mostrar uma explicação ao usuário antes de solicitar uma permissão perigosa. De acordo com a Referência do Desenvolvedor Android, 2024, o método retorna true se o usuário negou a solicitação anteriormente, mas não marcou a opção Never Ask Again. É uma ferramenta essencial para construir uma UX educada ao trabalhar com permissões em tempo de execução.
Pontos Principais
shouldShowRequestPermissionRationale é um método das classes Activity e Fragment no Android, disponível através do ActivityCompat para compatibilidade. Ele recebe um nome de permissão e retorna um Boolean indicando se deve mostrar ao usuário uma explicação adicional antes de solicitar novamente. O método apareceu no Android 6.0 Marshmallow junto com o modelo de permissões em tempo de execução.
O mecanismo de justificativa é baseado no rastreamento do histórico de interação do usuário com os diálogos de permissão. O sistema lembra se o usuário negou a solicitação anteriormente. Se a negação ocorreu sem marcar a opção Never Ask Again, shouldShowRequestPermissionRationale retorna true. Este é um sinal para o desenvolvedor: o usuário não entende por que a permissão é necessária, e uma explicação adicional é necessária. De acordo com as Diretrizes de Design Material do Google, mostrar um diálogo de justificativa após a primeira negação aumenta a probabilidade de conceder a permissão novamente em 35 por cento.
É importante entender a semântica dos valores retornados: true significa que mostrar o diálogo faz sentido, false significa que o diálogo não é necessário (a permissão já foi concedida ou nunca foi solicitada) ou é inútil (Never Ask Again ativo). O método não é uma garantia de que o diálogo será mostrado — ele apenas dá uma recomendação. O desenvolvedor decide qual UI mostrar em resposta.
shouldShowRequestPermissionRationale foi introduzido no Nível de API 23 junto com um grupo de métodos para permissões em tempo de execução. Antes do Android 6.0, todas as permissões eram solicitadas na instalação, e nenhum mecanismo de explicação era necessário — o usuário aceitava ou rejeitava a lista inteira de uma vez. O modelo de execução tornou possível que um usuário negasse uma solicitação sem entender o contexto, e é exatamente por isso que a justificativa é necessária.
A lógica do método funciona da seguinte forma. Na primeira chamada a requestPermissions para uma permissão específica, shouldShowRequestPermissionRationale retorna false — o usuário ainda não encontrou o diálogo. Se o usuário negar a solicitação (pressionar Negar), o método começa a retornar true. Após uma negação repetida com a opção Never Ask Again, o método retorna false.
Tabela completa de estados:
| Estado | shouldShowRationale | checkSelfPermission | Ação do desenvolvedor |
|---|---|---|---|
| Não solicitado | false | DENIED | Mostrar diálogo do sistema |
| Concedido | false | GRANTED | Executar função |
| Negado primeira vez | true | DENIED | Mostrar justificativa, depois diálogo do sistema |
| Never Ask Again | false | DENIED | Redirecionar para Configurações |
A combinação shouldShowRequestPermissionRationale = false e checkSelfPermission = DENIED é o caso mais difícil de tratar. Significa que a permissão nunca foi solicitada ou que Never Ask Again está ativado. O desenvolvedor precisa distinguir esses dois estados. A única maneira é armazenar um sinalizador isFirstRequest no SharedPreferences ou usando SavedStateHandle. Defina o sinalizador na primeira solicitação, e se shouldShowRationale retornar false enquanto o sinalizador já é true — significa Never Ask Again.
shouldShowRequestPermissionRationale é redefinido se o usuário desinstalar e reinstalar o aplicativo, limpar os dados do aplicativo ou redefinir as configurações de permissão. Após a reinstalação, o método retornará false novamente para a primeira solicitação. Atualizações do sistema e mudanças de versão do Android não redefinem o histórico — ele é armazenado nos dados do aplicativo.
Uma implementação adequada da justificativa inclui três componentes: verificar shouldShowRequestPermissionRationale após a negação, mostrar um diálogo personalizado com uma explicação e chamar requestPermissions novamente após uma resposta positiva do usuário. O diálogo deve ser breve, específico e explicar por que o aplicativo precisa dessa permissão em particular.
private fun requestLocationWithRationale() {
val permission = Manifest.permission.ACCESS_FINE_LOCATION
when {
ContextCompat.checkSelfPermission(
this, permission
) == PackageManager.PERMISSION_GRANTED -> {
startLocationTracking()
}
ActivityCompat.shouldShowRequestPermissionRationale(
this, permission
) -> {
showRationaleDialog(permission)
}
else -> {
requestPermissionLauncher.launch(permission)
}
}
}
private fun showRationaleDialog(
permission: String
) {
AlertDialog.Builder(this)
.setTitle("Por que o acesso à localização é necessário")
.setMessage(
"O aplicativo usa a localização para marcar" +
" lugares no mapa. Sem esta permissão," +
" a função não funcionará."
)
.setPositiveButton("Permitir") { _, _ ->
requestPermissionLauncher.launch(permission)
}
.setNegativeButton("Cancelar", null)
.show()
}
As melhores práticas do Material Design recomendam usar uma folha inferior ou banner inline em vez de um diálogo modal para a justificativa. Uma folha inferior é menos intrusiva e dá contexto ao usuário. Um elemento inline na tela (por exemplo, um cartão com explicação e um botão Permitir) mostra que a função não está disponível sem a permissão, mas não bloqueia o resto da interface.
O texto da justificativa deve ser localizado e adaptado à função específica. Não use frases genéricas como “Isso é necessário para o aplicativo funcionar.” Especifique concretamente: “Para mostrar o clima perto de você” ou “Para salvar fotos na galeria.” Explicações específicas aumentam a probabilidade de conceder a permissão em 50 por cento, de acordo com a Pesquisa de UX do Google.
A diferença entre shouldShowRequestPermissionRationale = true (primeira negação) e false com DENIED (Never Ask Again) é um ponto crucial no tratamento de permissões. No primeiro caso, o usuário estava hesitante, e uma explicação adicional pode convencê-lo a conceder acesso. No segundo, o usuário tomou uma decisão final, e repetir o diálogo do sistema só causará irritação.
O algoritmo de tratamento após a negação deve ser o seguinte:
É importante não confundir a ordem: verificar shouldShowRequestPermissionRationale primeiro, não checkSelfPermission. checkSelfPermission continuará retornando DENIED em ambos os casos. Apenas shouldShowRequestPermissionRationale distingue a primeira negação de Never Ask Again. Use SavedStateHandle ou SharedPreferences para armazenar o sinalizador “primeira solicitação foi feita” — esta é a única maneira confiável de distinguir “nunca solicitado” de “bloqueado.”
Mostre a justificativa apenas uma vez. Se o usuário negar a solicitação novamente após ver a justificativa, não mostre a explicação novamente. Vá direto para oferecer a abertura de Configurações. Mostrar a justificativa repetidamente é percebido como irritante e reduz a classificação do aplicativo. O cenário ideal: solicitação — negação — justificativa — solicitação repetida — negação — Configurações.
Não mostre a justificativa antes da primeira solicitação. Alguns desenvolvedores mostram erroneamente uma explicação antes do primeiro diálogo, argumentando que “o usuário deve entender.” Isso prejudica a UX: o usuário vê dois diálogos consecutivos em vez de um. O Google recomenda mostrar o diálogo do sistema imediatamente, e a justificativa apenas após a negação.
Use uma justificativa contextual vinculada ao momento em que a função é realmente necessária. Não solicite todas as permissões na inicialização do aplicativo — esta tem a menor taxa de concessão. Solicite CÂMERA quando o usuário tocar em “Tirar Foto” e LOCALIZAÇÃO quando ele abrir o mapa. A solicitação contextual combinada com a justificativa aumenta as concessões para 80 por cento contra 30 por cento quando solicitada na inicialização.
Testar shouldShowRequestPermissionRationale requer verificar os quatro estados da tabela: não solicitado, concedido, negado, Never Ask Again. Em testes unitários, use FakePermissionHandler com comportamento configurável de shouldShowRationale. Em testes de instrumentação, use UiAutomator ou Espresso com emulação de respostas de diálogo.
class RationaleViewModelTest {
private val handler = FakePermissionHandler()
private val viewModel = PermissionsViewModel(handler)
fun testFirstDenial_shouldShowRationale() {
handler.shouldShowRationale = true
handler.cameraResult =
PermissionResult.DENIED(true)
viewModel.onCameraRequested()
assertEquals(
PermissionUiState.Denied(true),
viewModel.uiState.value
)
}
fun testNeverAskAgain_redirectToSettings() {
handler.shouldShowRationale = false
handler.cameraResult =
PermissionResult.DENIED(false)
viewModel.onCameraRequested()
assertEquals(
PermissionUiState.RedirectToSettings,
viewModel.uiState.value
)
}
}
O cenário principal para um teste de instrumentação é verificar se o diálogo de justificativa realmente aparece após a primeira negação. Use Espresso com idling resources para aguardar o diálogo do sistema, então pressione Negar, verifique o aparecimento do diálogo de justificativa personalizado e pressione Permitir — verifique a concessão. UIAutomator permite interagir com o diálogo do sistema pelo texto do botão, tornando o teste mais estável.
Também deve testar o cenário de negação dentro do diálogo de justificativa. Se o usuário pressionar Negar na explicação personalizada, shouldShowRequestPermissionRationale deve retornar true novamente, pois Never Ask Again ainda não foi ativado. A melhor prática é redirecionar para Configurações após duas negações consecutivas para evitar irritar o usuário com explicações repetidas e reduzir a classificação do aplicativo.
Perguntas Frequentes
true — se a solicitação foi negada anteriormente e Never Ask Again não está definido. false — se a permissão nunca foi solicitada, concedida ou bloqueada permanentemente. A combinação false + DENIED requer verificação através de um sinalizador adicional.
Mostre a justificativa apenas após a primeira negação do usuário, quando shouldShowRequestPermissionRationale retornou true. Antes da primeira solicitação, a justificativa não é necessária — isso prejudica a UX e cria diálogos desnecessários.
Armazene um sinalizador isFirstRequest no SharedPreferences ou SavedStateHandle. Se shouldShowRationale = false, checkSelfPermission = DENIED e o sinalizador for true — Never Ask Again está ativo. Se o sinalizador for false — é a primeira solicitação.
Mostre um diálogo com um botão “Abrir Configurações” que redireciona o usuário para ACTION_APPLICATION_DETAILS_SETTINGS. Não chame requestPermissions novamente — o diálogo não aparecerá e o resultado virá como DENIED sem mensagem.
Em testes unitários, use FakePermissionHandler com um campo shouldShowRationale configurável. Em testes de instrumentação, use Espresso ou UIAutomator com emulação de diálogo do sistema. Verifique todos os 4 estados da tabela.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também