Ich habe ein sehr seltsames Problem mit dem Speicherzugriff auf einigen Geräten. Die App funktioniert auf meinen Testgeräten (Nexus 4 & 7, Samsung GS5). Alle meine Geräte mit Android 4.4.2. Aber ich habe viele E-Mails von Benutzern erhalten, die besagten, dass die App nicht in den Speicher schreiben kann (weder in den internen Speicher noch in die SD-Karte). Aus der Protokolldatei, die vom Benutzerfeedback erhalten wurde, geht hervor, dass das Problem der folgende Code ist:
try {
if (fStream == null) {
fStream = new FileOutputStream(filename, true);
}
fStream.write(data, 0, bytes);
return;
} catch (IOException ex) {
ex.printStackTrace();
}
Es wird eine Ausnahme in der Zeile fStream = new FileOutputStream (Dateiname, true) ausgelöst. beim Erstellen von FileOutputStream.
Das Stapelprotokoll lautet:
W/System.err( 8147): Caused by: java.io.FileNotFoundException: /storage/emulated/0/my_folder/test_file_name.png: open failed: EACCES (Permission denied)
w/System.err( 8147): at libcore.io.IoBridge.open(IoBridge.java:409)
W/System.err( 8147): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err( 8147): at java.io.FileOutputStream.<init>(FileOutputStream.java:128)
W/System.err( 8147): at myapp.save(SourceFile:515)
W/System.err( 8147): ... 8 more
W/System.err( 8147): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
W/System.err( 8147): at libcore.io.Posix.open(Native Method)
W/System.err( 8147): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err( 8147): at libcore.io.IoBridge.open(IoBridge.java:393)
W/System.err( 8147): ... 11 more
In der AndroidManifest.xml habe ich folgende Berechtigungen deklariert:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Ich habe bestätigt, dass die Benutzer die private App der richtigen App auf der SD-Karte verwenden. Und was noch seltsamer ist, dass es nicht auch in den internen Speicher schreibt. Wie kann dies passieren, wenn ich sowohl Lese- als auch Schreibberechtigungen habe? Die Benutzer geben an, dass sie ihre Geräte zu diesem Zeitpunkt nicht an den PC anschließen.
Aktualisieren
Es stellt sich heraus, dass ich FileOutputStream zu häufig zum Öffnen und Schließen aufrufe, wodurch irgendwann die FileNotFoundException ausgelöst wird. Klingt eher nach einem Threading-Problem.
quelle
Antworten:
Ich bin vor einiger Zeit auf ein ähnliches Problem gestoßen.
Ihr Problem kann in zwei verschiedenen Bereichen liegen. Entweder erstellen Sie die Datei, in die Sie schreiben möchten, oder Ihre Schreibmethode ist möglicherweise fehlerhaft, da sie vom Telefon abhängig ist.
Wenn Sie die Datei an einen bestimmten Speicherort auf der SD-Karte schreiben, verwenden Sie Umgebungsvariablen. Sie sollten immer auf einen gültigen Ort verweisen. Hier ist ein Beispiel zum Schreiben in den Download-Ordner:
java.io.File xmlFile = new java.io.File(Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Filename.xml");
Wenn Sie die Datei in den internen Speicher der Anwendung schreiben. Versuchen Sie dieses Beispiel:
java.io.File xmlFile = new java.io.File((getActivity() .getApplicationContext().getFileStreamPath("FileName.xml") .getPath()));
Persönlich verlasse ich mich auf externe Bibliotheken, um das Streaming in eine Datei zu verwalten. Dieser hat mich noch nicht im Stich gelassen.
org.apache.commons.io.FileUtils.copyInputStreamToFile(is, file);
Ich habe bei einem fehlgeschlagenen Schreibbefehl zu oft Daten verloren, daher verlasse ich mich bei meinem schweren E / A-Heben auf bekannte und getestete Bibliotheken.
Wenn die Dateien groß sind, können Sie auch die Ausführung der E / A im Hintergrund untersuchen oder Rückrufe verwenden.
Wenn Sie bereits Umgebungsvariablen verwenden, kann dies ein Berechtigungsproblem sein. Schauen Sie sich die Antwort von Justin Fiedler unten an.
quelle
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" />
quelle
Apps, die standardmäßig auf Android Q - API 29 abzielen, erhalten eine gefilterte Ansicht in den externen Speicher. Eine schnelle Lösung dafür ist das Hinzufügen dieses Codes in der AndroidManifest.xml:
<manifest ... > <!-- This attribute is "false" by default on apps targeting Android Q. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Lesen Sie hier mehr darüber: https://developer.android.com/training/data-storage/compatibility
quelle
In meinem Fall hatte ich den falschen Fall in
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
android.permission
muss klein geschrieben sein, und irgendwie war die gesamte Zeichenfolge in unserer Quelle in Großbuchstaben geschrieben.quelle
Ich stand auch vor dem gleichen Problem. Nach viel harter Arbeit fand ich heraus, was in meinem Fall falsch war. Mein Gerät wurde über ein USB-Kabel mit dem Computer verbunden. Es gibt Typen für USB-Verbindungen wie Massenspeicher, Mediengerät (MTP), Kamera (PTP) usw. Mein Verbindungstyp war - "Massenspeicher", und dies verursachte die Probleme. Als ich den Verbindungstyp änderte, wurde das Problem behoben.
Denken Sie beim Zugriff auf das Dateisystem auf einem Android-Gerät immer daran: -
NICHT ALS MASSENSPEICHER an den Computer / PC anschließen.
quelle
In meinem Fall handelte es sich um ein Berechtigungsproblem. Der Haken ist, dass ich auf einem Gerät mit Android 4.0.4 ohne Fehler oder Ausnahmen Zugriff auf die Datei habe. Und auf Geräten mit Android 5.1 ist es mit der ACCESS-Ausnahme fehlgeschlagen (Öffnen fehlgeschlagen: EACCES (Berechtigung verweigert)). Behandelte es mit dem Hinzufügen der folgenden Berechtigung zum Manifestieren der Datei:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Ich denke also, dass es der Unterschied zwischen der Berechtigungsverwaltung in Betriebssystemversionen ist, der zu Fehlern führt.
quelle
Geben oder überprüfen Sie zuerst Berechtigungen wie
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Wenn diese beiden Berechtigungen in Ordnung sind, überprüfen Sie, ob Ihre Ausgabestreams im richtigen Format vorliegen.
Beispiel:
FileOutputStream fos=new FileOutputStream(Environment.getExternalStorageDirectory()+"/rahul1.jpg");
quelle
Ich bin auf dasselbe Problem gestoßen und habe festgestellt, dass ich die Berechtigungen zur Laufzeit anfordern muss, auch wenn ich sie im Manifest deklariert habe. Genau wie die Antwort von Justin Fiedler.
Die offizielle Dokumentation dazu finden Sie hier: https://developer.android.com/training/permissions/requesting.html
Meine Implementierung unterscheidet sich geringfügig von der Antwort von Justin Fiedler, dass sie auch die onRequestPermissionsResult-Methode des v4-Fragments implementiert, um die Antwort auf die Berechtigungsanforderung zu verarbeiten.
public static final int REQUEST_EXTERNAL_PERMISSION_CODE = 666; @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) public static final String[] PERMISSIONS_EXTERNAL_STORAGE = { READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE }; public boolean checkExternalStoragePermission(Activity activity) { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) { return true; } int readStoragePermissionState = ContextCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE); int writeStoragePermissionState = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE); boolean externalStoragePermissionGranted = readStoragePermissionState == PackageManager.PERMISSION_GRANTED && writeStoragePermissionState == PackageManager.PERMISSION_GRANTED; if (!externalStoragePermissionGranted) { requestPermissions(PERMISSIONS_EXTERNAL_STORAGE, REQUEST_EXTERNAL_PERMISSION_CODE); } return externalStoragePermissionGranted; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == REQUEST_EXTERNAL_PERMISSION_CODE) { if (checkExternalStoragePermission(getActivity())) { // Continue with your action after permission request succeed } } } }
quelle
In meinem Fall habe ich die Option
android:isolatedProcess="true"
für einservice
in der verwendetAndroidManifest.xml
.Sobald ich es entfernt habe, ist der Fehler verschwunden ...
quelle
Auch ich fand Lösung für meinen Weg.
Vor dem Start der App habe ich dem Datei-Explorer root gewährt und die Berechtigung zum Schreiben / Lesen beim Beenden der App nicht deaktiviert.
Meine App kann keinen externen Speicher verwenden, während ich das Gerät zum Zurücksetzen aller Berechtigungen restratiert habe.
quelle
Ich habe das gleiche Problem, aber manchmal wird das schwierigste Problem einfach beantwortet.
Ich überprüfe die Manifest-Berechtigungen erneut und dort WAS_NOT schreiben Sie die Berechtigungsschande von mir !!!
quelle
@Uriel Frankel ist richtig, dass sich der Android 10-Speicherzugriff geändert hat. Der richtige Weg ist jedoch, nicht das Legacy-Speicherflag zu verwenden, sondern den Speicher Ihrer App wie folgt anzufordern:
val screenShotDirPath = getApplication<Application>().getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.path
getExternalFilesDir ist das, was Sie brauchen.
quelle
Wenn die Clients Android 6.0 verwenden, hat Android 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
quelle
In meinem Fall war das Problem, dass die statische WIFI-Konfiguration einen Konflikt mit einem anderen Gerät hatte, das dieselbe IP-Adresse verwendet.
quelle
Fügen Sie diese Lese- und Schreibberechtigung hinzu, um dieses Problem zu beheben
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Fügen Sie diese folgende Zeile im Anwendungs-Tag hinzu
android:requestLegacyExternalStorage="true"
quelle
Dieser Fehler wurde von einer anderen App ausgelöst, für die ich die Datei meiner App freigebe (mit
Intent.FLAG_GRANT_READ_URI_PERMISSION
)Es stellt sich heraus, dass die Datei wie hier gezeigt
Uri
über dieFileProvider
Klasse bereitgestellt werden muss .quelle
In meinem Fall habe ich vergessen, / vor dem Dateinamen hinzuzufügen, nachdem ich hinzugefügt habe, habe ich ihn entfernt
bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(Environment.getExternalStorageDirectory()+"/arjunreddy.png"));
quelle