Eccezione "apertura non riuscita: EACCES (autorizzazione negata)" su Android


297

Sto ottenendo

apertura fallita: EACCES (Permission denied)

sulla linea OutputStream myOutput = new FileOutputStream(outFileName);

Ho controllato il root e ho provato android.permission.WRITE_EXTERNAL_STORAGE.

Come posso risolvere questo problema?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

Ho avuto lo stesso problema su un tablet Android, ma la mia situazione potrebbe essere unica, quindi riporto la mia soluzione qui in un commento. L'errore si è verificato quando l'app ha tentato di accedere alla directory / data / data / myapp / foo con oltre 50 file XML. L'app non ha pulito la cartella a causa di un bug. Dopo l'eliminazione di alcuni vecchi file, l'errore è scomparso. Non so perché. Potrebbe essere un problema del dispositivo Android generico.
Hong

Risposte:


236

Ho avuto lo stesso problema ... <uses-permissionEra nel posto sbagliato. È giusto:

 <manifest>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        ...
        <application>
            ...
            <activity> 
                ...
            </activity>
        </application>
    </manifest> 

Il uses-permissiontag deve essere esterno al applicationtag.


2
è che il permesso d'uso deve essere esterno all'applicazione
user462990

3
Ricevo un avviso: " <uses-permission>tag appare dopo <application>tag"
mr5

11
ATTENZIONE In Android 4.4.4 non utilizzare il parametro android:maxSdkVersion="18".
Stava

1
Questa autorizzazione viene applicata a partire dal livello API 19. Prima del livello API 19, questa autorizzazione non viene applicata e tutte le app hanno ancora accesso alla lettura da memoria esterna.
Zar E Ahmer,

1
sto usando API lvl 15, sto ottenendo un errore durante il tentativo di spostare il file su chiavetta USB OTG
Ravi Mehta

330

Per API 23+ è necessario richiedere le autorizzazioni di lettura / scrittura anche se sono già presenti nel manifest.

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Per la documentazione ufficiale sulla richiesta di autorizzazioni per API 23+, consultare https://developer.android.com/training/permissions/requesting.html


13
Solo per chiarire, affinché questo funzioni, l'attività deve gestire la risposta alla richiesta delle autorizzazioni attività. Vedi developer.android.com/training/permissions/… per maggiori dettagli.
kldavis4,

Link utili con spiegazioni ed esempi qui in thecheesefactory.com/blog/…
Paul Alexander

1
non è una brutta cosa? rispetto all'esperienza dell'utente.
M. Usman Khan,

5
Ma dove lo uso? ad esempio, se voglio scattare una foto, devo eseguire verificando StorePermissions prima di startActivityForResult o su onActivityResult? mi confonde davvero.
Kiwi Lee,

3
Grazie questo risolve il mio problema. solo una nota: se qualcuno non riesce a risolvere "Manifest.permission" devi solo importare "import android.Manifest".
Oubaida AlQuraan,

167

Google ha una nuova funzionalità su Android Q : visualizzazione filtrata per archiviazione esterna. Una soluzione rapida è quella di aggiungere questo codice nel file AndroidManifest.xml:

<manifest ... >
    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true" ... >
     ...
    </application>
</manifest>

Puoi leggere di più qui: https://developer.android.com/training/data-storage/compatibility


@Billy ho notato che succede solo su dispositivi con API 29. Quindi ho cercato modifiche nel fornitore di file
Uriel Frankel,

Finalmente ho ottenuto il cloudtestingscreenshotter_lib.aar a lavorare con questa linea aggiunta al manifest AndroidTest, grazie mille per questa scoperta.
bko,

6
Signore, mi ha fatto risparmiare un sacco di tempo. Molte cose sono diventate una seccatura per uno sviluppatore in Q. Penso che questa risposta dovrebbe essere pubblicata come una domanda separata e merita più voti.
sanjeev

Vorrei leggere di più su questo piccolo trucco di magia nera, ma sfortunatamente il link restituisce un errore 404 ... Grazie comunque
SadSido

sta dando un avvertimento android:requestLegacyExternalStorage="true"questo non romperà le versioni inferiori ryt? @UrielFrankel
Santanu Sur

58

L'ho osservato una volta durante l'esecuzione dell'applicazione all'interno dell'emulatore. Nelle impostazioni dell'emulatore, è necessario specificare correttamente le dimensioni della memoria esterna ("Scheda SD"). Per impostazione predefinita, il campo "memoria esterna" è vuoto e ciò probabilmente significa che non esiste tale dispositivo e EACCES viene lanciato anche se le autorizzazioni sono concesse nel manifest.


51

Oltre a tutte le risposte, assicurati di non utilizzare il telefono come memoria USB.

Stavo avendo lo stesso problema su HTC Sensation in modalità di archiviazione USB abilitata. Posso ancora eseguire il debug / eseguire l'app, ma non riesco a salvare su memoria esterna.


Grazie amico, anche se avevo richiesto i permessi dell'utente in fase di esecuzione. Questo errore si è verificato sull'emulatore.
Sharp Edge,

1
Quando collego il dispositivo Samsung Galaxy S6, viene prima fornita l'opzione "Consenti accesso ai dati del dispositivo" con "DENY" o "ALLOW" e anche dalla barra di notifica ottengo un'opzione Usa USB per 1. MTP 2. PTP 3. MIDI Dispositivi 4. Ricarica. Quale scegliere?
test del

34

Aggiungere Android: requestLegacyExternalStorage = "true" al di Android Manifest E 'lavorato con Android 10 (Q) al SDK 29+
o Dopo la migrazione Android X .

 <application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon=""
    android:label=""
    android:largeHeap="true"
    android:supportsRtl=""
    android:theme=""
    android:requestLegacyExternalStorage="true">

Wow funziona perfettamente, questa è stata la risposta che stavo cercando, fantastico, grazie @rhaldar, mi hai salvato la giornata
Ayush Katuwal

29

Il mio problema era con "TargetApi (23)" che è necessario se minSdkVersion è inferiore a 23.

Quindi, ho l'autorizzazione richiesta con il seguente frammento

protected boolean shouldAskPermissions() {
    return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}

@TargetApi(23)
protected void askPermissions() {
    String[] permissions = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"
    };
    int requestCode = 200;
    requestPermissions(permissions, requestCode);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// ...
    if (shouldAskPermissions()) {
        askPermissions();
    }
}

28

Soluzione per Android Q :

<application ...
    android:requestLegacyExternalStorage="true" ... >

Mi hai salvato la giornata. L'autorizzazione è concessa, ma Glide non è in grado di leggere le immagini fino a quando non lo imposto.
leegor,

Attenzione: Android 11 rimuoverà completamente l'accesso legacy nell'agosto 2020, quindi migliora l'accesso ai file per utilizzare Storage Access Framework (SAF) per le tue app
dimib

16

Sto vivendo lo stesso. Quello che ho scoperto è che se vai su Impostazioni -> Gestione applicazioni -> La tua app -> Autorizzazioni -> Abilita archiviazione , risolve il problema.


1
Non riesco a trovare questa sezione?
Evan Sevy,

13

Si è scoperto, è stato uno stupido errore dal momento che il mio telefono era ancora collegato al PC desktop e non me ne sono reso conto.

Quindi ho dovuto disattivare la connessione USB e tutto ha funzionato bene.


ha funzionato anche per me. Ma perché funziona? che differenza fa la connessione USB al PC.
user13107

Buona domanda. Non l'ho mai più indagato. Immagino che ci sia un blocco in scrittura dal sistema nel momento in cui colleghi il dispositivo (quindi potrebbe emulare un dispositivo USB sul tuo computer). Forse questo è per evitare dati incoerenti. Non sono sicuro però.
Tobias Reich,

Ho trovato il motivo per qui stackoverflow.com/questions/7396757/... anche vedere la mia risposta stackoverflow.com/a/43863548/1729501
user13107

13

Ho avuto lo stesso problema su Samsung Galaxy Note 3, con CM 12.1. Il problema per me era che avevo

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>

e ho dovuto usarlo per scattare e archiviare le foto degli utenti. Quando ho provato a caricare quelle stesse foto in ImageLoader ho ricevuto l' (Permission denied)errore. La soluzione era quella di aggiungere esplicitamente

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

poiché l'autorizzazione di cui sopra limita solo l'autorizzazione di scrittura fino all'API versione 18 e con essa l'autorizzazione di lettura.


Non mi ha aiutato! Vale la pena provare! Grazie.
Sakiboy,

9

Oltre a tutte le risposte, se i client utilizzano Android 6.0, Android ha aggiunto un nuovo modello di autorizzazione per (Marshmallow).

Trucco: se si utilizza come target la versione 22 o precedente, l'applicazione richiederà tutte le autorizzazioni al momento dell'installazione esattamente come su qualsiasi dispositivo che esegue un sistema operativo al di sotto di Marshmallow. Se stai provando l'emulatore, da Android 6.0 in poi devi esplicitamente andare alle impostazioni-> app-> YOURAPP -> permessi e modificare le autorizzazioni se ne hai dato uno.


2
Incredibile, ho trascorso 2 giorni a cercare di capirlo. Ogni volta che sento che le cose funzionano senza intoppi su Android, succede qualcosa del genere.
Jaime Ivan Cervantes,

7

Stranamente dopo aver messo una barra "/" prima del mio nuovo file il mio problema è stato risolto. Ho cambiato questo:

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");

a questa:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");

1
Niente di strano qui. Con la prima riga si sta tentando di creare un file nella stessa directory di quella che contiene la directory di archiviazione esterna. vale a dire /storage/.../somethingnewfile invece di /storage/.../something/newfile
Stéphane

@ Stéphane L'errore stesso è strano se si guarda alla vasta gamma di risposte.
Darush,

3
Il modo corretto per farlo è usare il cosntruttore di File (dir, file)
Nick Cardoso,

@NickCardoso Puoi anche usare File (String pathname). Sembra che non stai capendo il punto qui. La domanda non riguarda l'uso della classe File. La gamma di risposte in questo thread mostra quanto sia fuorviante questo errore e in quanti modi possibili per risolverlo. Nel mio caso l'errore era la barra mancante. Alcune persone l'hanno trovato utile. Sicuro che potresti usare il tuo metodo di accesso a un file. Vai avanti e pubblica la tua risposta. Potrebbe risolvere il problema di qualcuno.
Darush,

Non stai capendo il punto. Se usi il costruttore corretto, il tuo hack non è richiesto. Il mio commento è stato aggiunto in modo che possa aiutare qualsiasi futuro lettore fuorviato dal tuo errore. Non è stata una critica personale e non ha avuto bisogno di una risposta
Nick Cardoso,

6

Ho avuto lo stesso problema e nessuno dei suggerimenti mi ha aiutato. Ma ho trovato un motivo interessante per questo, su un dispositivo fisico, Galaxy Tab .

Quando la memoria USB è attiva, le autorizzazioni di lettura e scrittura della memoria esterna non hanno alcun effetto. Disattiva l'archiviazione USB e, con le autorizzazioni corrette, avrai risolto il problema.


2
Dannazione, ho appena trascorso circa 3 ore a lavorare in giro. Inoltre, ho dovuto riavviare il dispositivo e ha funzionato. Grazie mille
crgarridos,

5

Mi aspetto che tutto quanto segue /dataappartenga alla "memoria interna". Tuttavia, dovresti essere in grado di scrivere /sdcard.


5
Ho provato anche <usi-permesso android: nome = "android.permission.WRITE_INTERNAL_STORAGE" />. sempre lo stesso.
Mert

1
La partizione / data è generalmente protetta da scrittura per gli utenti ordinari (non root) che tentano di accedere ai file ordinari. Per l'archiviazione interna, esistono metodi specializzati per farlo, specialmente se si desidera accedere ai database. Il pagine degli sviluppatori Android dovrebbero aiutarti in questo problema.
bakror,

5

Modifica una proprietà di autorizzazione nel tuo /system/etc/permission/platform.xml
gruppo e devi menzionarla come di seguito.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>

platform.xml è bloccato fino in fondo, tentando questo tramite shell adb ma necessita di qualsiasi script ADB mi permetterà di utilizzare per la mod.
Giovanni,

Fallire. Metti il ​​mio dispositivo in un ciclo di avvio.
Tobse,

5

Ho avuto lo stesso errore durante il tentativo di scrivere un'immagine nella cartella DCIM / fotocamera su Galaxy S5 (Android 6.0.1) e ho capito che solo questa cartella è soggetta a restrizioni. Potrei semplicemente scrivere in DCIM / qualsiasi cartella ma non nella fotocamera. Questo dovrebbe essere una restrizione / personalizzazione basata sul marchio.


4

Quando l'applicazione appartiene all'applicazione di sistema, non può accedere alla scheda SD.


4

tieni presente che anche se imposti tutte le autorizzazioni corrette nel manifest: L'unico posto in cui le app di terze parti sono autorizzate a scrivere sulla tua scheda esterna sono le "loro directory" (es. / sdcard / Android / data /) che provano a scrivere su altrove: riceverai un'eccezione: EACCES (autorizzazione negata)


3

Forse la risposta è questa:

sull'API> = 23 dispositivi, se installi un'app (l'app non è un'app di sistema), dovresti controllare l'autorizzazione di archiviazione in "Impostazioni - applicazioni", c'è un elenco di autorizzazioni per ogni app, dovresti controllarlo! provare


3

Nel mio caso stavo usando una libreria di selezione file che ha restituito il percorso alla memoria esterna ma da cui è partito /root/. E anche con l' autorizzazione WRITE_EXTERNAL_STORAGE concessa in fase di esecuzione ho ancora ricevuto l'errore EACCES (Autorizzazione negata) .
Quindi utilizzare Environment.getExternalStorageDirectory()per ottenere il percorso corretto per l'archiviazione esterna.

Esempio:
Impossibile scrivere: /root/storage/emulated/0/newfile.txt
Può scrivere: /storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

Uscita 1:

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

Uscita 2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488

Stavo avendo lo stesso identico problema. La rimozione della rootparte dal percorso ha risolto il mio problema.
xabush,


3

Per chiunque venga qui dai risultati di ricerca e scelga come target Android 10: Android 10 (API 29) modifica alcune autorizzazioni relative all'archiviazione.

Ho risolto il problema quando ho sostituito le mie precedenti istanze di Environment.getExternalStorageDirectory()(che è obsoleta con API 29) concontext.getExternalFilesDir(null) .

Nota che context.getExternalFilesDir(type)può restituire null se il percorso di archiviazione non è disponibile, quindi assicurati di controllarlo ogni volta che controlli se disponi di autorizzazioni esterne.

Leggi di più qui .


2

Sto creando una cartella sotto / data / nel mio init.rc (facendo confusione con l'aosp su Nexus 7) e ho avuto esattamente questo problema.

Si è scoperto che dare l'autorizzazione alla cartella rw (666) non era sufficiente e doveva essere rwx (777), quindi tutto ha funzionato!


2

L'applicazione post 6.0 delle autorizzazioni di archiviazione può essere ignorata se si dispone di un dispositivo rooted tramite questi comandi adb:

root@msm8996:/ # getenforce
getenforce
Enforcing
root@msm8996:/ # setenforce 0
setenforce 0
root@msm8996:/ # getenforce
getenforce
Permissive

1

Aggiungi autorizzazione in manifest.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3
Non c'è permessoandroid.permission.READ_INTERNAL_STORAGE
Ryan R

0

Ho avuto lo stesso problema (API> = 23).

La soluzione https://stackoverflow.com/a/13569364/1729501 ha funzionato per me, ma non era pratico scollegare l'app per il debug.

la mia soluzione era installare il driver di dispositivo adb corretto su Windows. Il driver USB di Google non ha funzionato per il mio dispositivo.

PASSAGGIO 1: scarica i driver adb per la marca del tuo dispositivo.

PASSAGGIO 2: vai a Gestione dispositivi -> altri dispositivi -> cerca le voci con la parola "adb" -> seleziona Aggiorna driver -> indica la posizione nel passaggio 1


0

dopo aver aggiunto l'autorizzazione risolto il mio problema

<uses-permission android:name="android.permission.INTERNET"/>

0

Aggiungi dipendenze di livello

implementation 'com.karumi:dexter:4.2.0'

Aggiungi sotto il codice nella tua attività principale.

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                checkMermission();
            }
        }, 4000);
    }

    private void checkMermission(){
        Dexter.withActivity(this)
                .withPermissions(
                        android.Manifest.permission.READ_EXTERNAL_STORAGE,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        android.Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
                if (report.isAnyPermissionPermanentlyDenied()){
                    checkMermission();
                } else if (report.areAllPermissionsGranted()){
                    // copy some things
                } else {
                    checkMermission();
                }

            }
            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                token.continuePermissionRequest();
            }
        }).check();
    }

0

Nel mio caso l'errore appariva sulla linea

      target.createNewFile();

poiché non sono riuscito a creare un nuovo file sulla scheda SD, quindi ho dovuto usare l'approccio DocumentFile.

      documentFile.createFile(mime, target.getName());

Per la domanda precedente il problema può essere risolto con questo approccio,

    fos=context.getContentResolver().openOutputStream(documentFile.getUri());

Vedi anche questa discussione, Come usare la nuova API di accesso alla scheda SD presentata per Android 5.0 (Lollipop)?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.