Android – Como solicitar los permisos en Android 6 y superiores

By | 07/06/2016

Las aplicaciones que desarrollas en Android que requieren permisos necesitan la declaración de estos en el archivo manifiest de tu proyecto.
Por ejemplo  para acceder a la Camara de Fotos debemos incluir un  <uses-permission> en nuestro manifiest. de este modo.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gustavopeiretti.app" >
    <uses-permission android:name="android.permission.CAMERA" />
    ...
</manifest>

android-permissions

Si tu proyecto esta definido para para versiones anteriores targetSdkVersion 22 o menor solo basta con incluir en el “manifiest” los permisos que necesitas. En estas versiones, al instalar la aplicación, Android requiere al usuario la aceptación de los permisos que hemos declarado en nuestro archivo manifiest.

Sin embargo a partir de targetSdkVersion 23 Android 6.0 (API level 23) esto ha cambiado y es necesario que nosotros nos encarguemos de requerir estos permisos para aquellos que son ‘peligrosos’. Android los llama “Dangerous permissions”

.. archivo build.gradle de nuestra app.. 
....
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.examplepermission"
        minSdkVersion 23
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    ...
}

¿Cómo requerir los permisos para Android 6 o superior?

Podemos hacer uso de este metodo “PermissionChecker.checkSelfPermission(..)” que nos dira el estado del permiso. Luego usaremos requestPermissions(..) para solicitar los permisos que nos faltan.

Por ejemplo, para saber si tenemos permisos a la Camara y requerirlos en caso negativo:

        private final int REQUEST_CODE_ASK_PERMISSIONS = 123;
        ...

         int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
            if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {

                // request permission

                requestPermissions(new String[] {Manifest.permission.CAMERA},
                        REQUEST_CODE_ASK_PERMISSIONS);

            }else if (hasWriteContactsPermission == PackageManager.PERMISSION_GRANTED){

                // do something

            }

¿Cómo obtener el resultado del permiso?

El resultado de nuestra solicitud de permisos la podemos evaluar sobreescribiendo “onRequestPermissionsResult(…)”

  @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if(REQUEST_CODE_ASK_PERMISSIONS == requestCode) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // OK Do something with..
            } else {
                // The user does not grant permissions 
            }
        }else{
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

Si intentas abrir la Camara (o lo que necesites) sin permisos otorgados por el usuario, recibiras esta excepción


Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=android/com.android.internal.app.ResolverActivity }

Permisos que necesitan ser verificados.

Puedes solicitar permisos ya sea para el grupo o para un elemento individual del grupo. En el caso de CONTACTS, este tiene tres elementos.

Permission Group Permissions
CONTACTS
  • READ_CONTACTS
  • WRITE_CONTACTS
  • GET_ACCOUNTS

Si tu App solicita permisos para un item en particular del grupo de permisos, por ejemplo READ_CONTACTS, Android solicitara permisos al usuario indicándole que necesita permisos para CONTACTS (el grupo) sin detallar el permiso particular que requeriste.

Si tu app ya tiene permisos a READ_CONTACTS otorgados por el usuario y luego tu app solicita permisos para otro item especifico del mismo grupo, ej. WRITE_CONTACTS, el sistema inmediatamente otorgará permisos sin preguntarle al usuario.

Es decir, si ya recibiste permisos para READ_CONTACTS y luego solicitas para WRITE_CONTACTS inmediatamente recibiras este segundo permiso porque estan en el mismo grupo.

Los permisos se agrupan acorde a la columna “Permission Group” que pueden consultar en este enlace

El codigo completo de ejemplo quedaría así

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_ASK_PERMISSIONS = 123;

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
    }

    public void examplePermission(View view) {
        checkPermission();
    }


    private void checkPermission() {

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {

            Toast.makeText(this, "This version is not Android 6 or later " + Build.VERSION.SDK_INT, Toast.LENGTH_LONG).show();

        } else {

            int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);

            if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {

                requestPermissions(new String[] {Manifest.permission.CAMERA},
                        REQUEST_CODE_ASK_PERMISSIONS);

                Toast.makeText(this, "Requesting permissions", Toast.LENGTH_LONG).show();

            }else if (hasWriteContactsPermission == PackageManager.PERMISSION_GRANTED){

                Toast.makeText(this, "The permissions are already granted ", Toast.LENGTH_LONG).show();
                openCamera();

            }

        }

        return;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if(REQUEST_CODE_ASK_PERMISSIONS == requestCode) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "OK Permissions granted ! 🙂 " + Build.VERSION.SDK_INT, Toast.LENGTH_LONG).show();
                openCamera();
            } else {
                Toast.makeText(this, "Permissions are not granted ! 🙁 " + Build.VERSION.SDK_INT, Toast.LENGTH_LONG).show();
            }
        }else{
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }


    private void openCamera() {

        textView.setText("Thanks !!!");

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivity(intent);

    }

}

Descarga este codigo completo

Referencias:
Android Permissions
Requesting Permissions at Run Time

Compartir esto:

4 thoughts on “Android – Como solicitar los permisos en Android 6 y superiores

  1. Jordi

    Hola buenas estoy intentando recoger el IMEI del dispositivo pero me deja este mensaje cuando implemento tu código:

    ” Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException.
    This check scans through your code and libraries and looks at the APIs being used, and checks this against the set of permissions required to access those APIs. If the code using those APIs is called at runtime, then the program will crash. Furthermore, for permissions that are revocable (with targetSdkVersion 23), client code must also be prepared to handle the calls throwing an exception if the user rejects the request for permission at runtime. ”

    —————————————————————–

    El código es este:

    —————————————————————–

    private void checkPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
    } else {
    int hasPermission = checkSelfPermission(Manifest.permission.READ_PHONE_STATE);

    if (hasPermission != PackageManager.PERMISSION_GRANTED) {

    requestPermissions(new String[] {Manifest.permission.READ_PHONE_STATE},
    REQUEST_CODE_ASK_PERMISSIONS);

    Toast.makeText(this, "Requesting permissions", Toast.LENGTH_SHORT).show();

    }else if (hasPermission == PackageManager.PERMISSION_GRANTED){
    Toast.makeText(this, "The permissions are already granted ", Toast.LENGTH_SHORT).show();
    }
    }
    return;
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if(REQUEST_CODE_ASK_PERMISSIONS == requestCode) {
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(this, "OK Permissions granted ! ? " + Build.VERSION.SDK_INT, Toast.LENGTH_LONG).show();
    —————————————————————–
    userImeiString = telephonyManager.getDeviceId();
    —————————————————————–
    } else {
    Toast.makeText(this, "Permissions are not granted ! ? " + Build.VERSION.SDK_INT, Toast.LENGTH_LONG).show();
    finish();
    }
    }else{
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    }

    Me lanza el error en la línea dentro del recuadro punteado, a la hora de hacer el getDeviceId();

    ¿¿Alguna idea??

    Gracias!

    Reply
    1. Gustavo Post author

      Hola, debes agregar este permiso android.permission.READ_PHONE_STATE a en tu AndroidManifest
      saludos

      Reply
  2. Eloy Duran

    Hola exelente explicacion pero como lo implemento para encender y apagar la linterna de android gracias

    Reply
    1. Gustavo Post author

      Los permisos que necesitas son los de la cámara.

      Reply

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *