[android] open failed: EACCES (autorizzazione negata)


Answers

Per API 23+ è necessario richiedere i permessi di lettura / scrittura anche se sono già nel tuo 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" />
Question

Sto avendo un problema molto strano con l'accesso di archiviazione su alcuni dispositivi. L'app funziona sui miei dispositivi di test (Nexus 4 e 7, Samsung GS5). Tutti i miei dispositivi con Android 4.4.2. Ma ho ricevuto molte e-mail dagli utenti che dicevano che l'app non può scrivere nella memoria (né la memoria interna né la scheda SD). Dal file di log ricevuto dal feedback degli utenti, posso vedere che il problema è il seguente codice:

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

Genera un'eccezione sulla riga fStream = new FileOutputStream (filename, true); quando si crea FileOutputStream.

Il registro dello stack è:

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 AndroidManifest.xml ho dichiarato le seguenti autorizzazioni:

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

Ho confermato che gli utenti stanno utilizzando la private app corretta sulla scheda SD. E la cosa più strana è che non riesce a scrivere anche nella memoria interna. Come può accadere se ho entrambi i permessi di lettura e scrittura? Gli utenti dicono che non stanno collegando i loro dispositivi al PC in quel momento.

Aggiornare

Si scopre che sto chiamando Apri e chiudi FileOutputStream troppo frequentemente, che a un certo punto getta FileNotFoundException. Sembra più un problema di threading.




Ho incontrato lo stesso problema e ho scoperto che devo richiedere le autorizzazioni in fase di esecuzione, anche se l'ho dichiarato nel manifest. Proprio come ha dichiarato la risposta di Justin Fiedler.

La documentazione ufficiale su questo sono qui: https://developer.android.com/training/permissions/requesting.html

La mia implementazione è leggermente diversa dalla risposta di Justin Fiedler che implementa anche il metodo onRequestPermissionsResult di v4 fragment per gestire la risposta alle richieste di autorizzazione.

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



Prima dare o controllare le autorizzazioni come

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

Se queste due autorizzazioni sono OK, controlla che i flussi di output siano nel formato corretto.

Esempio:

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



Nel mio caso il problema era la configurazione WIFI che era statica aveva un conflitto con un altro dispositivo che utilizza lo stesso indirizzo IP.




Inoltre ho trovato la soluzione per il mio modo.

Prima dell'app di lancio ho concesso root a file-explorer e non ho disabilitato l'autorizzazione per scrivere / leggere quando si esce dall'app.

La mia app non può utilizzare la memoria esterna mentre eseguivo il ripristino del dispositivo per reimpostare tutte le autorizzazioni.




Ho anche affrontato lo stesso problema. Dopo un sacco di duro lavoro, ho trovato cosa non andava nel mio caso. Il mio dispositivo è stato collegato al computer tramite cavo USB. Esistono tipi per connessioni USB come Mass Storage, Media Device (MTP), Camera (PTP) ecc. Il mio tipo di connessione era - 'Mass Storage', e questo causava i problemi. Quando ho cambiato il tipo di connessione, il problema è stato risolto.

Ricorda sempre durante l'accesso al filesystem sul dispositivo Android: -

NON COLLEGARE COME MEMORIA DI MASSA al computer / PC.




Related