He añadido uses-permission
incluyendo WRITE_EXTERNAL_STORAGE
,MOUNT_UNMOUNT_FILESYSTEMS
,READ_EXTERNAL_STORAGE
a AndroidManifest.xml
.
Cuando traté de ejecutar mi aplicación en Nexus5 (Android 6.0), lanzó una excepción como a continuación:
java.io.IOException: open failed: EACCES (Permiso denegado)
Y he intentado otro teléfono Android (Android 5.1), todo estaba OK.Here's el código:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
currentPhotoPath = image.getAbsolutePath();
return image;
}
¿Tiene Android 6.0 diferencia sobre el permiso?
Android ha añadido un nuevo modelo de permisos para Android 6.0 (Marshmallow).
Así que tienes que comprobar Runtime Permission
:
**¿Qué son los permisos en tiempo de ejecución?
Con Android 6.0 Marshmallow, Google introdujo un nuevo modelo de permisos que permite a los usuarios entender mejor por qué una aplicación puede estar solicitando permisos específicos. En lugar de que el usuario acepte ciegamente todos los permisos en el momento de la instalación, ahora se le pide que acepte los permisos a medida que sean necesarios durante el uso de la aplicación.
**¿Cuándo aplicar el nuevo modelo?
no requiere soporte completo hasta que elija la versión 23 en su aplicación. Si te diriges a la versión 22 o inferior, tu aplicación solicitará todos los permisos en el momento de la instalación del mismo modo que lo haría en cualquier dispositivo con un sistema operativo inferior a Marshmallow.
Esta información está tomada de aquí:
Por favor, compruebe Cómo implementar desde este enlace:
En Android 6(Marshmallow), aunque el usuario aceptó todos tus permisos en el momento de la instalación, más tarde puede decidir quitarte algunos de esos permisos.
Solución rápida pero no recomendada: quizás si cambias tu targetSdkVersion
en el gradle a 22
, el problema se solucionará.
¿Cómo Implementar?(Mejores Prácticas)
En primer lugar determinar si el dispositivo del usuario es un dispositivo Marshmallow o no:
private boolean shouldAskPermission(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
}
Si shouldAskPermission()
devuelve true
, pide el permiso que necesites:
String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"};
int permsRequestCode = 200;
requestPermissions(perms, permsRequestCode);
El método requestPermissions(String[] permissions, int requestCode);
es un método público que se encuentra dentro de la clase Android Activity.
Recibirá los resultados de su solicitud en el método onRequestPermissionResult como se muestra a continuación:
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
caso 200:
boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
interrupción;
}
}
Después de recibir los resultados, tendrá que manejarlos adecuadamente.
Flujo de permisos sugerido:
Más información:
Un usuario con un dispositivo Marshmallow ahora tendrá la capacidad de revocar permisos peligrosos a través de la configuración de la aplicación
Android define algunos permisos como "peligrosos" y otros como "normales". Ambos son necesarios en el manifiesto de tu aplicación, pero solo los permisos peligrosos requieren una solicitud en tiempo de ejecución.
Si ha optado por no implementar el nuevo modelo de permisos (solicitud en tiempo de ejecución), la revocación de permisos puede causar experiencias de usuario no deseadas y, en algunos casos, el bloqueo de la aplicación.
La siguiente tabla enumera todos los permisos peligrosos actuales y sus respectivos grupos:
Si el usuario acepta un permiso en un grupo/categoría, ¡acepta todo el grupo!
Fuente:http://www.captechconsulting.com
Usando la Biblioteca Dexter:
Puedes utilizar Dexter. Biblioteca de Android que simplifica el proceso de solicitud de permisos en tiempo de ejecución.
También puede utilizar ActivityCompat.requestPermissions para compatibilidad con versiones anteriores.
ejemplo:
private static final int REQUEST_CODE = 0x11;
String[] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// save file
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
}
}
}