Ausnahme 'Öffnen fehlgeschlagen: EACCES (Berechtigung verweigert)' unter Android


297

ich bekomme

Öffnen fehlgeschlagen: EACCES (Permission denied)

an der Leitung OutputStream myOutput = new FileOutputStream(outFileName);

Ich habe die Wurzel überprüft und es versucht android.permission.WRITE_EXTERNAL_STORAGE.

Wie kann ich dieses Problem beheben?

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();
}

Ich hatte das gleiche Problem auf einem Android-Tablet, aber meine Situation kann einzigartig sein. Deshalb berichte ich meine Lösung hier in einem Kommentar. Der Fehler trat auf, als die App versuchte, auf das Verzeichnis / data / data / myapp / foo zuzugreifen, das über 50 XML-Dateien enthielt. Die App hat den Ordner aufgrund eines Fehlers nicht bereinigt. Nachdem einige alte Dateien gelöscht wurden, verschwand der Fehler. Keine Ahnung warum. Es könnte ein Problem des generischen Android-Geräts sein.
Hong

Antworten:


236

Ich hatte das gleiche Problem ... Das <uses-permissionwar am falschen Ort. Dies ist richtig:

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

Das uses-permissionTag muss sich außerhalb des applicationTags befinden.


2
es ist, dass die Verwendungsberechtigung außerhalb der Anwendung sein muss
user462990

3
Ich erhalte eine Warnung: " <uses-permission>Tag erscheint nach <application>Tag"
mr5

11
WARNUNG Verwenden Sie in Android 4.4.4 nicht den Parameter android:maxSdkVersion="18". Es erzeugte diese Ausnahme
guisantogui

1
Diese Berechtigung wird ab API-Ebene 19 erzwungen. Vor API-Ebene 19 wird diese Berechtigung nicht erzwungen, und alle Apps haben weiterhin Zugriff auf das Lesen aus dem externen Speicher.
Zar E Ahmer

1
Ich benutze API Level 15, ich bekomme Fehler beim Versuch, die Datei auf den OTG USB Stick zu verschieben
Ravi Mehta

330

Für API 23+ müssen Sie die Lese- / Schreibberechtigungen anfordern, auch wenn sie bereits in Ihrem Manifest enthalten sind.

// 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" />

Eine offizielle Dokumentation zum Anfordern von Berechtigungen für API 23+ finden Sie unter https://developer.android.com/training/permissions/requesting.html


13
Damit dies funktioniert, muss die Aktivität die Antwort auf die Anforderung der Aktivitätsberechtigungen verarbeiten. Weitere Informationen finden Sie unter developer.android.com/training/permissions/… .
kldavis4


1
Ist das nicht eine schlechte Sache? in Bezug auf die Benutzererfahrung.
M. Usman Khan

5
Aber wo verwende ich es? Wenn ich beispielsweise ein Bild aufnehmen möchte, muss ich verifyStoragePermissions vor startActivityForResult oder bei onActivityResult ausführen? es verwirrt mich wirklich.
Kiwi Lee

3
Danke, das löst mein Problem. Nur ein Hinweis: Wenn jemand "Manifest.permission" nicht auflösen kann, müssen Sie nur "import android.Manifest" importieren.
Oubaida AlQuraan

167

Google hat eine neue Funktion für Android Q : Gefilterte Ansicht für externen Speicher. Eine schnelle Lösung hierfür ist das Hinzufügen dieses Codes zur Datei AndroidManifest.xml:

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

Weitere Informationen finden Sie hier: https://developer.android.com/training/data-storage/compatibility


@ Billy Ich habe bemerkt, dass es nur auf Geräten mit API 29 passiert. Also habe ich nach Änderungen im Dateianbieter gesucht
Uriel Frankel

Endlich habe ich die cloudtestingscreenshotter_lib.aar, um mit dieser Zeile zu arbeiten, die dem androidTest-Manifest hinzugefügt wurde. Vielen Dank für diesen Fund.
Bko

6
Sie, Sir, haben mir viel Zeit gespart. Viele Dinge sind für einen Entwickler in Q zu einem Problem geworden. Ich denke, diese Antwort sollte als separate Frage veröffentlicht werden und verdient mehr Gegenstimmen.
Sanjeev

Ich würde gerne mehr über diesen netten kleinen schwarzen Zaubertrick lesen, aber leider gibt der Link einen 404-Fehler zurück ...
Trotzdem

Es gibt eine Warnung, dass android:requestLegacyExternalStorage="true"dies nicht zu niedrigeren Versionen führen wird. @UrielFrankel
Santanu Sur

58

Ich habe dies einmal beobachtet, als ich die Anwendung im Emulator ausführte. In den Emulatoreinstellungen müssen Sie die Größe des externen Speichers ("SD-Karte") richtig angeben. Standardmäßig ist das Feld "Externer Speicher" leer. Dies bedeutet wahrscheinlich, dass kein solches Gerät vorhanden ist und EACCES auch dann ausgelöst wird, wenn im Manifest Berechtigungen erteilt wurden.


51

Stellen Sie zusätzlich zu allen Antworten sicher, dass Sie Ihr Telefon nicht als USB-Speicher verwenden.

Ich hatte das gleiche Problem bei aktiviertem HTC Sensation im USB-Speichermodus. Ich kann die App weiterhin debuggen / ausführen, aber nicht auf einem externen Speicher speichern.


Danke Mann, obwohl ich zur Laufzeit vom Benutzer Berechtigungen angefordert hatte. Dieser Fehler ist im Emulator aufgetreten.
Sharp Edge

1
Wenn ich das Samsung Galaxy S6-Gerät anschließe, wird zuerst die Option "Zugriff auf Gerätedaten zulassen" mit "VERWEIGERN" oder "ERLAUBEN" angezeigt. Außerdem wird über die Benachrichtigungsleiste die Option "USB für 1. MTP 2. PTP 3. MIDI verwenden" angezeigt Geräte 4. Laden. Welches soll ich wählen?
Testsingh

34

In android: requestLegacyExternalStorage = "true" auf das Android - Manifest Es ist arbeitete mit Android 10 (Q) bei SDK 29+
oder nach der Migration 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 funktioniert perfekt, das war die Antwort, nach der ich gesucht habe, großartig, danke @rhaldar, du hast meinen Tag gerettet
Ayush Katuwal

29

Mein Problem war mit "TargetApi (23)", das benötigt wird, wenn Ihre minSdkVersion unter 23 liegt.

Ich habe also eine Erlaubnis mit dem folgenden Snippet angefordert

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

Lösung für Android Q :

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

Du hast meinen Tag gerettet. Die Erlaubnis wird erteilt, aber Glide kann keine Bilder lesen, bis ich dies eingestellt habe.
Leegor

Achtung: Android 11 entfernt den alten Zugriff im August 2020 vollständig. Aktualisieren Sie daher den Dateizugriff besser, um das Storage Access Framework (SAF) für Ihre Apps zu verwenden
dimib

16

Ich erlebe das gleiche. Ich habe festgestellt, dass das Problem behoben wird, wenn Sie zu Einstellungen -> Anwendungsmanager -> Ihre App -> Berechtigungen -> Speicher aktivieren gehen .


1
Ich kann diesen Abschnitt nicht finden?
Evan Sevy

13

Es stellte sich heraus, dass es ein dummer Fehler war, da ich mein Telefon immer noch mit dem Desktop-PC verbunden hatte und dies nicht bemerkte.

Also musste ich die USB-Verbindung ausschalten und alles funktionierte einwandfrei.


arbeitete auch für mich. Aber warum funktioniert es? Welchen Unterschied macht es nicht, USB an PC anzuschließen?
user13107

Gute Frage. Ich habe das nie weiter untersucht. Ich denke, es gibt eine Schreibsperre vom System, sobald Sie das Gerät anschließen (so dass es möglicherweise ein USB-Gerät auf Ihrem Computer emuliert). Vielleicht, um inkonsistente Daten zu vermeiden. Ich bin mir aber nicht sicher.
Tobias Reich


13

Ich hatte das gleiche Problem auf dem Samsung Galaxy Note 3 mit CM 12.1. Das Problem für mich war, dass ich hatte

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

und musste es verwenden, um Benutzerfotos aufzunehmen und zu speichern. Als ich versuchte, dieselben Fotos in ImageLoader zu laden, wurde der (Permission denied)Fehler angezeigt . Die Lösung bestand darin, explizit hinzuzufügen

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

da die obige Berechtigung die Schreibberechtigung nur auf API-Version 18 und damit die Leseberechtigung beschränkt.


Hat mir nicht geholfen! Einen Versuch wert! Vielen Dank.
Sakiboy

9

Zusätzlich zu allen Antworten hat Android, wenn die Clients Android 6.0 verwenden, ein neues Berechtigungsmodell für (Marshmallow) hinzugefügt .

Trick: Wenn Sie auf Version 22 oder niedriger abzielen, fordert Ihre Anwendung bei der Installation alle Berechtigungen an, genau wie auf jedem Gerät, auf dem ein Betriebssystem unter Marshmallow ausgeführt wird. Wenn Sie den Emulator ausprobieren, müssen Sie ab Android 6.0 explizit die Einstellungen-> Apps-> YOURAPP -> Berechtigungen aufrufen und die Berechtigung ändern, falls Sie welche erteilt haben.


2
Unglaublich, ich habe 2 Tage damit verbracht, das herauszufinden. Jedes Mal, wenn ich das Gefühl habe, dass die Dinge unter Android reibungslos laufen, passiert so etwas.
Jaime Ivan Cervantes

7

Seltsamerweise wurde mein Problem gelöst, nachdem ich vor meiner neuen Datei einen Schrägstrich "/" gesetzt hatte . Ich habe das geändert:

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

dazu:

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

1
Hier ist nichts Seltsames. In der ersten Zeile versuchen Sie, eine Datei im selben Verzeichnis zu erstellen, in dem sich auch Ihr externes Speicherverzeichnis befindet. dh /storage/.../somethingnewfile anstelle von /storage/.../something/newfile
Stéphane

@ Stéphane Der Fehler selbst ist seltsam, wenn man sich das breite Spektrum an Antworten ansieht.
Darush

3
Der richtige Weg, dies zu tun, ist die Verwendung des File (dir, file) cosntructor
Nick Cardoso

@NickCardoso Sie können auch File (String pathname) verwenden. Sieht so aus, als würden Sie hier nicht den Punkt verstehen. Bei der Frage geht es nicht darum, wie die File-Klasse verwendet wird. Der Antwortbereich in diesem Thread zeigt, wie irreführend dieser Fehler ist und wie viele Möglichkeiten, ihn zu beheben. In meinem Fall war der Fehler der fehlende Schrägstrich. Einige Leute haben es nützlich gefunden. Sicher können Sie Ihre eigene Methode für den Zugriff auf eine Datei verwenden. Mach weiter und poste deine Antwort. Es kann jemandes Problem lösen.
Darush

Sie verstehen den Punkt nicht. Wenn Sie den richtigen Konstruktor verwenden, ist Ihr Hack nicht erforderlich. Mein Kommentar wurde hinzugefügt, damit er zukünftigen Lesern helfen kann, die durch Ihren Fehler in die Irre geführt wurden. Es war keine persönliche Kritik und brauchte keine Antwort
Nick Cardoso

6

Ich hatte das gleiche Problem und keiner der Vorschläge half. Aber ich fand einen interessanten Grund dafür auf einem physischen Gerät, Galaxy Tab .

Wenn der USB-Speicher aktiviert ist, haben Lese- und Schreibberechtigungen für externen Speicher keine Auswirkungen. Schalten Sie einfach den USB-Speicher aus und mit den richtigen Berechtigungen ist das Problem behoben.


2
Verdammt, ich habe gerade 3 Stunden damit verbracht, herumzuarbeiten. Außerdem musste ich das Gerät neu starten und es funktionierte. Vielen Dank
Crgarridos

5

Ich würde erwarten, dass alles unten /datazum "internen Speicher" gehört. Sie sollten jedoch in der Lage sein, zu schreiben /sdcard.


5
Ich habe auch versucht <Verwendungsberechtigung android: name = "android.permission.WRITE_INTERNAL_STORAGE" />. immer noch das gleiche.
Mert

1
Die / data-Partition ist im Allgemeinen für normale Benutzer (ohne Rootberechtigung) schreibgeschützt, die versuchen, auf normale Dateien zuzugreifen. Für den internen Speicher gibt es spezielle Methoden, insbesondere wenn Sie auf Datenbanken zugreifen möchten. Die Android-Entwicklerseiten sollten Ihnen bei diesem Problem helfen.
Ofenfehler

5

Ändern Sie eine Berechtigungseigenschaft in Ihrer /system/etc/permission/platform.xml
und der Gruppe wie unten angegeben.

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

platform.xml ist sofort gesperrt und versucht dies über die ADB-Shell, benötigt jedoch das Skript, das ADB für den Mod verwenden kann.
John

Scheitern. Legen Sie mein Gerät in eine Boot-Schleife.
Tobse

5

Ich hatte den gleichen Fehler, als ich versuchte, ein Bild in den DCIM / Kamera-Ordner auf dem Galaxy S5 (Android 6.0.1) zu schreiben, und stellte fest, dass nur dieser Ordner eingeschränkt ist. Ich könnte einfach in DCIM / einen beliebigen Ordner schreiben, aber nicht in die Kamera. Dies sollte eine markenbasierte Einschränkung / Anpassung sein.


4

Wenn Ihre Anwendung zur Systemanwendung gehört, kann sie nicht auf die SD-Karte zugreifen.


4

Beachten Sie Folgendes, auch wenn Sie im Manifest alle korrekten Berechtigungen festgelegt haben: Der einzige Ort, an dem Apps von Drittanbietern auf Ihre externe Karte schreiben dürfen, sind "ihre eigenen Verzeichnisse" (dh / sdcard / Android / data /), in die geschrieben werden soll irgendwo anders: Sie erhalten eine Ausnahme: EACCES (Berechtigung verweigert)


3

Vielleicht lautet die Antwort:

Wenn Sie auf der API> = 23 Geräte die App installieren (die App ist keine System-App), sollten Sie die Speicherberechtigung unter "Einstellungen - Anwendungen" überprüfen. Es gibt eine Berechtigungsliste für jede App. Sie sollten sie aktivieren. Versuchen


3

In meinem Fall habe ich eine Dateiauswahlbibliothek verwendet, die den Pfad zum externen Speicher zurückgegeben hat, aber von dort aus gestartet wurde /root/. Und selbst mit der zur Laufzeit erteilten Berechtigung WRITE_EXTERNAL_STORAGE wurde immer noch der Fehler EACCES (Berechtigung verweigert) angezeigt .
Verwenden Sie also Environment.getExternalStorageDirectory(), um den richtigen Pfad zum externen Speicher zu erhalten.

Beispiel:
Kann nicht schreiben: /root/storage/emulated/0/newfile.txt
Kann schreiben: /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;
}

Ausgabe 1:

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

Ausgabe 2:

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

Ich hatte genau das gleiche Problem. Das Entfernen des rootTeils aus dem Pfad hat mein Problem behoben.
Xabush


3

Für alle, die aus Suchergebnissen hierher kommen und auf Android 10 abzielen: Android 10 (API 29) ändert einige Berechtigungen in Bezug auf Speicher.

Ich habe das Problem behoben, als ich meine vorherigen Instanzen von Environment.getExternalStorageDirectory()(die mit API 29 veraltet sind) durch ersetzt habe context.getExternalFilesDir(null).

Beachten Sie, dass context.getExternalFilesDir(type)null zurückgegeben werden kann, wenn der Speicherort nicht verfügbar ist. Überprüfen Sie dies daher immer dann, wenn Sie prüfen, ob Sie über externe Berechtigungen verfügen.

Lesen Sie hier mehr .


2

Ich erstelle einen Ordner unter / data / in meiner init.rc (mit dem Aosp auf Nexus 7 herumspielen) und hatte genau dieses Problem.

Es stellte sich heraus, dass es nicht ausreichte, dem Ordner rw (666) die Berechtigung zu geben, und es musste rwx (777) sein, dann funktionierte alles!


2

Die Durchsetzung von Speicherberechtigungen nach Version 6.0 kann umgangen werden, wenn Sie über ein gerootetes Gerät über die folgenden adb-Befehle verfügen:

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

1

Berechtigung im Manifest hinzufügen.

<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
Es gibt keine Erlaubnisandroid.permission.READ_INTERNAL_STORAGE
Ryan R

0

Ich hatte das gleiche Problem (API> = 23).

Die Lösung https://stackoverflow.com/a/13569364/1729501 funktionierte für mich, aber es war nicht praktisch, die App zum Debuggen zu trennen.

Meine Lösung bestand darin, den richtigen ADB-Gerätetreiber unter Windows zu installieren. Der Google USB-Treiber funktionierte für mein Gerät nicht.

SCHRITT 1: Laden Sie ADB-Treiber für Ihre Gerätemarke herunter.

SCHRITT 2: Gehen Sie zum Geräte-Manager -> Andere Geräte -> suchen Sie nach Einträgen mit dem Wort "adb" -> wählen Sie Treiber aktualisieren -> geben Sie in Schritt 1 den Speicherort an


0

Nach dem Hinzufügen der Erlaubnis löste sich mein Problem

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

0

Gradle-Abhängigkeiten hinzufügen

implementation 'com.karumi:dexter:4.2.0'

Fügen Sie den folgenden Code in Ihre Hauptaktivität ein.

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

In meinem Fall erschien der Fehler in der Zeile

      target.createNewFile();

Da ich keine neue Datei auf der SD-Karte erstellen konnte, musste ich den DocumentFile-Ansatz verwenden.

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

Für die obige Frage kann das Problem mit diesem Ansatz gelöst werden,

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

Siehe auch diesen Thread. Wie verwende ich die neue SD-Kartenzugriffs-API für Android 5.0 (Lollipop)?

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.