El método checkSelfPermission no funciona en targetSdkVersion 22

El método “CheckSelfPermission” no funciona como se espera y siempre devuelve cero en Android 6.0 (Marshmallow). Debido a que el objective sdk es 22 y estoy usando http Client para la conexión de red. Lo siguiente es el fragmento de código.

“private void insertDummyContactWrapper () {List permissionsNeeded = new ArrayList ();

final List permissionsList = new ArrayList(); if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION)) permissionsNeeded.add("GPS"); if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS)) permissionsNeeded.add("Read Contacts"); if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS)) permissionsNeeded.add("Write Contacts"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "You need to grant access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return; } insertDummyContact(); } @TargetApi(Build.VERSION_CODES.M) private boolean addPermission(List permissionsList, String permission) { if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); // Check for Rationale Option if (!shouldShowRequestPermissionRationale(permission)) return false; } return true; } private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(MainActivity.this) .setMessage(message) .setPositiveButton("OK", okListener) .setNegativeButton("Cancel", null) .create() .show(); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: { Map perms = new HashMap(); // Initial perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED); // Fill with results for (int i = 0; i < permissions.length; i++) perms.put(permissions[i], grantResults[i]); // Check for ACCESS_FINE_LOCATION if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) { // All Permissions Granted insertDummyContact(); } else { // Permission Denied Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT) .show(); } } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }" 

El método Context#checkSelfPermission(String) se agregó a la API 23. También debajo de API 23 no tiene sentido, ya que el permiso siempre se concede. Verifique la versión de la API antes de gestionar los permisos

 private void insertDummyContactWrapper() { // the only way we insert the dummy contact if if we are below M. // Else we continue on and prompt the user for permissions if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { insertDummyContact(); return; } List permissionsNeeded = new ArrayList(); final List permissionsList = new ArrayList(); if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION)) permissionsNeeded.add("GPS"); if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS)) permissionsNeeded.add("Read Contacts"); if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS)) permissionsNeeded.add("Write Contacts"); if (permissionsList.size() > 0) { if (permissionsNeeded.size() > 0) { // Need Rationale String message = "You need to grant access to " + permissionsNeeded.get(0); for (int i = 1; i < permissionsNeeded.size(); i++) message = message + ", " + permissionsNeeded.get(i); showMessageOKCancel(message, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } }); return; } requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); } } 

Referencia: http://developer.android.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)

  1. Si su aplicación apunta a un nivel de API antes de 23 (Android M), entonces: ContextCompat # checkSelfPermission y Context # checkSelfPermission no funciona y siempre devuelve 0 ( PERMISSION_GRANTED ). Incluso si ejecuta la aplicación en Android 6.0 (API 23).

  2. No es del todo cierto que si apunte a un nivel de API anterior a 23, entonces no tenga que ocuparse de los permisos. Si su objective es un nivel de API anterior a 23, entonces:

    • Android <6.0: todo estará bien.
    • Android 6.0: los permisos de tiempo de ejecución de la aplicación se otorgarán de manera predeterminada (se aplica el modo de compatibilidad), pero el usuario puede cambiar los permisos de tiempo de ejecución en la Configuración de Android, entonces es posible que tenga un problema.
  3. Como dije en el primer punto, si apuntas a un nivel de API antes de 23 en Android 6.0, entonces ContextCompat # checkSelfPermission y Context # checkSelfPermission no funciona. Afortunadamente puede usar PermissionChecker # checkSelfPermission para verificar los permisos de tiempo de ejecución.

Código de ejemplo:

  public boolean selfPermissionGranted(String permission) { // For Android < Android M, self permissions are always granted. boolean result = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (targetSdkVersion >= Build.VERSION_CODES.M) { // targetSdkVersion >= Android M, we can // use Context#checkSelfPermission result = context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; } else { // targetSdkVersion < Android M, we have to use PermissionChecker result = PermissionChecker.checkSelfPermission(context, permission) == PermissionChecker.PERMISSION_GRANTED; } } return result; } 

Para obtener la versión de Sdk objective puede usar:

  try { final PackageInfo info = context.getPackageManager().getPackageInfo( context.getPackageName(), 0); targetSdkVersion = info.applicationInfo.targetSdkVersion; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } 

Funciona en Nexus 5 con Android M.

Al apuntar a un nivel de API antes de 23, se aplica un modo de compatibilidad. El antiguo comportamiento de permisos se está ejecutando, incluso en dispositivos con Android 6. Para usar el nuevo sistema de permisos, debe apuntar a la API 23 (o superior en el futuro).

El comportamiento completo se especifica en la documentación: https://developer.android.com/training/permissions/requesting.html