Error de permiso de almacenamiento en Marshmallow
En Lollipop, la funcionalidad de descarga funciona bien en mi aplicación, pero cuando actualizé a Marshmallow, mi aplicación se bloquea y da este error cuando intento descargar desde Internet a la tarjeta SD:
Neither user nor current process has android.permission.WRITE_EXTERNAL_STORAGE
Se queja de esta línea de código:
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
Tengo los permisos en la aplicación externa del manifiesto:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Limpié y reconstruí el proyecto, pero todavía se bloquea.
11 answers
Usted debe comprobar si el usuario ha concedido permiso de almacenamiento externo mediante:
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
//File write logic here
return true;
}
Si no es así, debes pedirle al usuario que conceda un permiso a tu app:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Por supuesto, estos son solo para dispositivos marshmallow, por lo que debe verificar si su aplicación se está ejecutando en Marshmallow:
if (Build.VERSION.SDK_INT >= 23) {
//do your check here
}
Asegúrese también de que su actividad implementa OnRequestPermissionResult
Todo el permiso se ve así:
public boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
} else {
Log.v(TAG,"Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG,"Permission is granted");
return true;
}
}
Devolución de llamada del resultado del permiso:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
//resume tasks needing this permission
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-04 07:52:18
Sistema de permisos de Android es una de las mayores preocupaciones de seguridad todos a lo largo ya que esos permisos se solicitan en el momento de la instalación. Una vez instalado, la aplicación será capaz de acceder a todas las cosas concedido sin el reconocimiento de ningún usuario qué aplicación exactamente lo hace con el permiso.
Android 6.0 Marshmallow introduce uno de los mayores cambios en el modelo de permisos con la adición de permisos de tiempo de ejecución, un nuevo modelo de permiso que reemplaza los permisos de tiempo de instalación existentes modelo cuando te diriges a API 23 y la aplicación se ejecuta en un Android 6.0+ dispositivo
La cortesía va a Solicitar Permisos en Tiempo de Ejecución .
Ejemplo
Declare esto como Global
private static final int PERMISSION_REQUEST_CODE = 1;
Añadir esto en su onCreate()
sección
Después de setContentView(R. layout.your_xml);
if (Build.VERSION.SDK_INT >= 23)
{
if (checkPermission())
{
// Code for above or equal 23 API Oriented Device
// Your Permission granted already .Do next code
} else {
requestPermission(); // Code for permission
}
}
else
{
// Code for Below 23 API Oriented Device
// Do next code
}
Ahora añadiendo checkPermission () y requestPermission()
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void requestPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(Your_Activity.this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(Your_Activity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("value", "Permission Granted, Now you can use local drive .");
} else {
Log.e("value", "Permission Denied, You cannot use local drive .");
}
break;
}
}
FYI
Resultados de las misiones a petición
Esta interfaz es el contrato para recibir los resultados de solicitudes de permiso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-17 11:19:13
A menos que haya un requisito definido de escribir en almacenamiento externo, siempre puede elegir guardar archivos en el directorio de aplicaciones. En mi caso tuve que guardar archivos y después de perder 2 a 3 días me enteré si cambio la ruta de almacenamiento de
Environment.getExternalStorageDirectory()
A
getApplicationContext().getFilesDir().getPath() //which returns the internal app files directory path
Funciona como encanto en todos los dispositivos. Esto se debe a que para escribir en almacenamiento externo necesita permisos adicionales, pero escribir en el directorio interno de la aplicación es simple.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-02 11:31:55
Comprobar permisos múltiples en el nivel de API 23 Paso 1:
String[] permissions = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.VIBRATE,
Manifest.permission.RECORD_AUDIO,
};
Paso 2:
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(this, p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100);
return false;
}
return true;
}
Paso 3:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == 100) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do something
}
return;
}
}
Paso 4: en onCreate de Actividad checkPermissions ();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-19 10:48:41
Necesita usar el permiso de tiempo de ejecución en marshmallow https://developer.android.com/training/permissions/requesting.html
Puede consultar la información de la aplicación - > permiso
Es su aplicación obtener permiso para escribir almacenamiento externo o no
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-16 03:42:06
Parece que el usuario ha rechazado el permiso y la aplicación intenta escribir en el disco externo, causando un error.
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Compruebe https://developer.android.com/training/permissions/requesting.html
Este video le dará una mejor idea sobre UX, manejando permisos de tiempo de ejecución https://www.youtube.com/watch?v=iZqDdvhTZj0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-16 03:50:39
Desde la versión de marshmallow, los desarrolladores necesitan pedir permisos de tiempo de ejecución al usuario. Déjame darte todo el proceso para pedir permisos de tiempo de ejecución.
Estoy usando una referencia desde aquí : marshmallow runtime permissions android.
Primero cree un método que verifique si todos los permisos se otorgan o no
private boolean checkAndRequestPermissions() {
int camerapermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int writepermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int permissionLocation = ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION);
int permissionRecordAudio = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camerapermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (writepermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionLocation != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionRecordAudio != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.RECORD_AUDIO);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
Ahora aquí está el código que se ejecuta después del método anterior. Vamos a anular onRequestPermissionsResult()
método:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.RECORD_AUDIO, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
// process the normal flow
Intent i = new Intent(MainActivity.this, WelcomeActivity.class);
startActivity(i);
finish();
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
|| ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
showDialogOK("Service Permissions are required for this app",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
finish();
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?");
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
Si el usuario hace clic en la opción Deny luego se utilizará el método showDialogOK()
para mostrar el diálogo
Si el usuario hace clic en Deny y también hace clic en una casilla de verificación que dice "nunca preguntar de nuevo", entonces se utilizará el método explain()
para mostrar el diálogo.
Métodos para mostrar diálogos:
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
private void explain(String msg){
final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this);
dialog.setMessage(msg)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// permissionsclass.requestPermission(type,code);
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission")));
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
finish();
}
});
dialog.show();
}
El fragmento de código anterior solicita cuatro permisos a la vez. También puede solicitar cualquier número de permisos en cualquier actividad según sus requisitos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 06:37:36
Después de muchas búsquedas Este código funciona para mí:
Compruebe que el permiso ya tiene: Comprobar permiso WRITE_EXTERNAL_STORAGE Permitido o no?
if(isReadStorageAllowed()){
//If permission is already having then showing the toast
//Toast.makeText(SplashActivity.this,"You already have the permission",Toast.LENGTH_LONG).show();
//Existing the method with return
return;
}else{
requestStoragePermission();
}
private boolean isReadStorageAllowed() {
//Getting the permission status
int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
//If permission is granted returning true
if (result == PackageManager.PERMISSION_GRANTED)
return true;
//If permission is not granted returning false
return false;
}
//Requesting permission
private void requestStoragePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){
//If the user has denied the permission previously your code will come to this block
//Here you can explain why you need this permission
//Explain here why you need this permission
}
//And finally ask for the permission
ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_WRITE_STORAGE);
}
Implementar Override onRequestPermissionsResult método para comprobar es el usuario permitir o denie
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//Checking the request code of our request
if(requestCode == REQUEST_WRITE_STORAGE){
//If permission is granted
if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Displaying a toast
Toast.makeText(this,"Permission granted now you can read the storage",Toast.LENGTH_LONG).show();
}else{
//Displaying another toast if permission is not granted
Toast.makeText(this,"Oops you just denied the permission",Toast.LENGTH_LONG).show();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-25 03:06:58
Ha funcionado para mí
boolean hasPermission = (ContextCompat.checkSelfPermission(AddContactActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(AddContactActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case REQUEST_WRITE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//reload my activity with permission granted or use the features what required the permission
} else
{
Toast.makeText(AddContactActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-25 05:19:08
Try this
int permission = ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
Log.i("grant", "Permission to record denied");
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.permsg))
.setTitle(getString(R.string.permtitle));
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.i("grant", "Clicked");
makeRequest();
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
//makeRequest1();
makeRequest();
}
}
protected void makeRequest() {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
500);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 500: {
if (grantResults.length == 0
|| grantResults[0] !=
PackageManager.PERMISSION_GRANTED) {
Log.i("1", "Permission has been denied by user");
} else {
Log.i("1", "Permission has been granted by user");
}
return;
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 13:17:40
Antes de iniciar su descarga compruebe sus permisos de tiempo de ejecución y si no tiene permiso, solicite permisos como este método
requestStoragePermission()
private void requestStoragePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE))
{
}
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
STORAGE_PERMISSION_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if(requestCode == STORAGE_PERMISSION_CODE){
if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
}
else{
Toast.makeText(this,
"Oops you just denied the permission",
Toast.LENGTH_LONG).show();
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 10:24:53