Desde o Android 6.0 Marshmallow, o Android usa um modelo de permissões que otimiza o processo de instalação e atualização automática de apps. As permissões são solicitadas no tempo de execução, e não antes da instalação do app. Além disso, os usuários podem negar permissões específicas. Para oferecer essa flexibilidade aos usuários, verifique se o app se comporta como esperado quando um usuário ativa ou desativa uma permissão específica.
O Google Play Services tem permissões de execução que os usuários podem negar separadamente daquelas especificamente solicitadas pelo app. O Google Play Services recebe automaticamente todas as permissões necessárias para oferecer suporte às APIs. No entanto, o app ainda precisa verificar e solicitar permissões de execução conforme necessário e processar erros adequadamente nos casos em que um usuário negou ao Google Play Services uma permissão necessária para uma API usada pelo app.
É recomendável gerenciar as expectativas do usuário ao definir permissões que o tempo de execução pode exigir. As práticas recomendadas a seguir ajudam a evitar possíveis problemas.
Pré-requisitos
Você precisa declarar as permissões no arquivo AndroidManifest.xml
.
Exemplo:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Diretrizes
Verificar permissões antes de chamar APIs
Depois de declarar as APIs que você quer usar no arquivo AndroidManifest.xml
, verifique se você tem a permissão necessária antes de chamar uma API. Isso pode ser feito usando o método checkSelfPermission
de ActivityCompat
ou ContextCompat
.
Se a chamada retornar "false", isso significa que as permissões não foram concedidas e você
deve usar requestPermissions
para solicitá-las. A resposta a isso é
retornada em uma callback, que você vai ver na próxima etapa.
Exemplo:
Kotlin
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } else { // permission has been granted, continue as usual val locationResult = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION_CODE); } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
Implementar o callback de solicitação de permissão
Se a permissão necessária para o app não tiver sido concedida pelo usuário, chame o método
requestPermissions
para pedir que ele conceda. A resposta do usuário é capturada no callback
onRequestPermissionsResult
. Seu app precisa
implementar isso e sempre verificar os valores de retorno, porque a solicitação pode ser
negada ou cancelada. Também é possível solicitar e verificar várias permissões de
uma só vez. O exemplo a seguir verifica apenas uma permissão.
Kotlin
fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to val locationResult: Task = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation // Request the last known location. } else { // Permission was denied or request was cancelled } } }
Java
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if(grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); // Request the last known location. } else { // Permission was denied or request was cancelled } } }
Mostrar a justificativa da permissão
Se as permissões solicitadas pelo app forem necessárias para os recursos principais dele e o usuário tiver negado a solicitação anteriormente, o app deverá mostrar uma explicação adicional antes de solicitar a permissão novamente. Os usuários têm mais probabilidade de conceder permissões quando entendem por que elas são necessárias e o benefício imediato para eles.
Nesse caso, antes de chamar requestPermissions
, chame
shouldShowRequestPermissionRationale
. Se ele retornar
verdadeiro, crie uma interface para mostrar mais contexto sobre a
permissão.
Por exemplo, seu código pode ser assim:
Kotlin
private const val REQUEST_LOCATION_PERMISSION_CODE = 2 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now if ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_FINE_LOCATION ) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } } else { // Permission has already been granted, continue as usual val locationResult: Task= LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now private static final int REQUEST_LOCATION_PERMISSION_CODE = 2; if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.LOCATION_FINE}, REQUEST_LOCATION_PERMISSION_CODE); } } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
As chamadas de API dos Serviços do Google Play vão mostrar automaticamente uma caixa de diálogo (se o cliente for instanciado com um Activity
) ou uma notificação na bandeja do sistema (se o cliente for instanciado com um Context
) que o usuário pode tocar para iniciar a intent de resolução de permissões. As chamadas serão enfileiradas e repetidas quando a permissão for concedida.