Pytanie nieudane otwarcie: EACCES (odmowa uprawnień)


Mam bardzo dziwny problem z dostępem do pamięci na niektórych urządzeniach. Aplikacja działa na moich urządzeniach testujących (Nexus 4 i 7, Samsung GS5). Wszystkie moje urządzenia z systemem Android 4.4.2. Otrzymałem jednak wiele e-maili od użytkowników, którzy twierdzili, że aplikacja nie może zapisywać danych w pamięci (ani pamięci wewnętrznej, ani karty SD). Z pliku dziennika otrzymanego od użytkownika wynika, że ​​problem jest następujący:

try {
    if (fStream == null) {
    fStream = new FileOutputStream(filename, true);
}
    fStream.write(data, 0, bytes);
    return;
} catch (IOException ex) {
    ex.printStackTrace();
}

Zgłasza wyjątek w linii fStream = new FileOutputStream (filename, true); podczas tworzenia FileOutputStream.

Dziennik stosu to:

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

W pliku AndroidManifest.xml mam następujące uprawnienia:

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

Potwierdziłem, że użytkownicy używają poprawnej aplikacji prywatnej na karcie SD. Co dziwniejsze, nie zapisuje się również w pamięci wewnętrznej. Jak to się dzieje, jeśli mam uprawnienia do odczytu i zapisu? Użytkownicy mówią, że nie podłączają swoich urządzeń do komputera w tym czasie.

Aktualizacja

Okazuje się, że zbyt często wołam do otwierania i zamykania FileOutputStream, co w pewnym momencie wyrzuca wyjątek FileNotFoundException. Brzmi bardziej jak wątek.


49
2018-05-07 20:30


pochodzenie


Okazuje się, że zbyt często wołam do otwierania i zamykania FileOutputStream, co w pewnym momencie wyrzuca wyjątek FileNotFoundException. Brzmi bardziej jak wątek. - user3613696


Odpowiedzi:


Wróciłem do podobnego problemu jakiś czas temu.

Twój problem może dotyczyć dwóch różnych obszarów. Jest to zarówno sposób, w jaki tworzysz plik, do którego piszesz, jak i twoja metoda pisania może być wadliwa, ponieważ zależy od telefonu.

Jeśli piszesz plik w określonej lokalizacji na karcie SD, spróbuj użyć zmiennych środowiskowych. Powinny zawsze wskazywać prawidłową lokalizację. Oto przykład zapisu do folderu pobranych plików:

java.io.File xmlFile = new java.io.File(Environment
    .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
     + "/Filename.xml");

Jeśli piszesz plik do pamięci wewnętrznej aplikacji. Spróbuj tego przykładu:

java.io.File xmlFile = new java.io.File((getActivity()
   .getApplicationContext().getFileStreamPath("FileName.xml")
   .getPath()));

Osobiście polegam na zewnętrznych bibliotekach do obsługi przesyłania strumieniowego do pliku. Ten jeszcze mnie nie zawiódł.

org.apache.commons.io.FileUtils.copyInputStreamToFile(is, file);

Wiele razy traciłem dane po nieudanym poleceniu zapisu, więc polegam na dobrze znanych i przetestowanych bibliotekach dla mojego ciężkiego podnoszenia IO.

Jeśli pliki są duże, możesz również sprawdzić działanie IO w tle lub użyć wywołań zwrotnych.

Jeśli już używasz zmiennych środowiskowych, może to być problem z uprawnieniami. Sprawdź odpowiedź Justina Fiedlera poniżej.


27
2018-05-07 22:09



Spróbuję z org.apache.commons.io.FileUtils i zobaczę, czy to pomaga. Zostanie opublikowana później. Nawiasem mówiąc, po kolejnych testach okazuje się, że fStream = new FileOutputStream (filename, true); nie zawsze nie udaje się otworzyć strumienia za każdym razem, wygląda na to, że działa po raz pierwszy i nie powiedzie się następnym razem. - user3613696
Okazuje się, że zbyt często wołam do otwierania i zamykania FileOutputStream, co w pewnym momencie wyrzuca wyjątek FileNotFoundException. Brzmi bardziej jak wątek. Zaznaczam twoją odpowiedź, ponieważ została zaakceptowana, ponieważ prawidłowo wskazałeś możliwy błąd. - user3613696
Dzięki. Tak, ponieważ nie mogliśmy zobaczyć całego kodu, musimy tylko zgadywać, co może być przyczyną problemu. Dzięki za zaakceptowanie! - Garret


W przypadku interfejsu API 23+ musisz zażądać uprawnień do odczytu / zapisu, nawet jeśli są już w twoim manifeście.

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

114
2017-10-22 19:20



To prawda, rozwiązał mój problem. Więcej informacji: developer.android.com/training/permissions/requesting.html - joaobarbosa
WTF !!! ??? Google próbuje złamać cały Sklep Play. - Chameleon
Dokładnie, mój problem, był podobny. Jeśli testowałem aplikację w wersji Androida niższej niż wersja 6. aplikacja działała jak urok, ale dla> = 6 coś było nie tak. Jak powiedział @easyspeak, po prostu dodaj prośbę o pozwolenie. - Shudy
jak to zrobić w testach instrumentalnych? - Ahmad Muzakki
dałem pozwolenie, ale nie mogłem zrobić pliku .zip w sdcard - Bhanu Sharma


W moim przypadku miałem niewłaściwy przypadek

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

android.permission musi być pisany małymi literami, a cały ciąg w naszym źródle był wielkimi literami.


6
2017-09-25 18:23





Zmierzyłem się również z tym samym problemem. Po wielu ciężkich pracach odkryłem, co jest nie tak w moim przypadku. Moje urządzenie zostało podłączone do komputera kablem USB. Istnieją rodzaje połączeń USB, takich jak Mass Storage, Media Device (MTP), Camera (PTP) itp. Mój typ połączenia to "Masowa pamięć masowa" i to było przyczyną problemów. Po zmianie typu połączenia problem został rozwiązany.

Zawsze pamiętaj podczas uzyskiwania dostępu do systemu plików na urządzeniu z Androidem: -

NIE PODŁĄCZAJ JAKIEGO PAMIĘCI MASOWEJ do komputera / komputera.


4
2017-10-22 10:17



Co zmieniłeś? Mam PTP i MTP jako moje jedyne opcje, ani pracy. Nawet ładowanie aplikacji na moim urządzeniu i uruchamianie jej z urządzenia bez połączenia z komputerem nie rozwiązuje go. - G_V
Lub debuguj go za pomocą Wi-Fi. - David


W moim przypadku był to problem uprawnień. Połów jest taki, że na urządzeniu z Androidem 4.0.4 dostałem dostęp do pliku bez żadnego błędu czy wyjątku. I na urządzeniu z Androidem 5.1 nie udało się z wyjątkiem ACCESS (otwarte zawieszenie: EACCES (odmowa uprawnień)). Obsługiwano go, dodając uprawnienia do pliku manifestu:

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

Sądzę więc, że to różnica między zarządzaniem uprawnieniami w wersjach systemu operacyjnego, które powoduje awarie.


2
2018-01-08 14:29





Najpierw podaj lub sprawdź uprawnienia, takie jak

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

Jeśli te dwa uprawnienia są w porządku, sprawdź, czy strumienie wyjściowe mają poprawny format.

Przykład:

FileOutputStream fos=new FileOutputStream(Environment.getExternalStorageDirectory()+"/rahul1.jpg");

2
2018-02-21 10:14





W moim przypadku skorzystałem z tej opcji android:isolatedProcess="true" dla service w AndroidManifest.xml.

Jak tylko ją usunąłem, błąd zniknął ...


1
2018-03-05 19:40





Wystąpił ten sam problem i stwierdziłem, że muszę żądać uprawnień w czasie wykonywania, nawet jeśli zadeklarowałem to w manifeście. Tak jak powiedział Justin Fiedler.

Oficjalna dokumentacja na ten temat znajduje się tutaj: https://developer.android.com/training/permissions/requesting.html

Moja implementacja różni się nieco od odpowiedzi Justina Fiedlera, że ​​implementuje on także metodę onRequestPermissionsResult fragmentu v4, aby obsłużyć odpowiedź na żądanie uprawnień.

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
            }
        }
    }
}

1
2018-04-02 01:04



Świetna ilustracja. Uratowałem mój dzień. :-) - TechBee


Mam ten sam problem, ale Czasami najtrudniejszy problem otrzymuje prostą odpowiedź.

Ponownie sprawdzam manifesty i tam uprawnienie do zapisu WAS_NOT wstyd mnie !!!


1
2018-06-19 16:43



Jezu Chryste, przydarzyło mi się to, dzięki stosom - Juanca