it-swarm.com.de

Android M auf SD-Karte schreiben - Berechtigung verweigert

Ich versuche, eine Datei aus meiner Anwendung auf die SD-Karte zu kopieren, aber ich bekomme die Fehlermeldung eacces (Erlaubnis verweigert). Das Betriebssystem ist Android M und ich habe Laufzeit-Speicherberechtigungen zugelassen (in App-Info eingecheckt). Ich habe auch die Verwendungsberechtigung in AndroidManifest.xml festgelegt

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

Funktioniert nicht, wenn ich auf SD-Karte kopiere

Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/1032-2568/SomeFolder/
Error: Java.io.FileNotFoundException: /storage/1032-2568/SomeFolder/SomeFile.txt: open failed: EACCES (Permission denied)

Funktioniert, wenn ich in den internen Speicher kopiere

Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/emulated/0/SomeFolder/

Code zum Kopieren der Datei von der Quelle zum Ziel

/*
 * Below are the parameters I have tried
 *
 * inputPath - data/user/0/com.example.myapp/cache or data/user/0/com.example.myapp/cache/
 * inputFile - /SomeFile.txt or SomeFile.txt
 * outputPath - /storage/1032-2568/SomeFolder/ or /storage/1032-2568/SomeFolder
 */
public static void copyFile(String inputPath, String inputFile, String outputPath) {

    InputStream in = null;
    OutputStream out = null;
    try {

        //create output directory if it doesn't exist
        File dir = new File (outputPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        in = new FileInputStream(inputPath + inputFile);
        out = new FileOutputStream(outputPath + inputFile);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();


        // write the output file (You have now copied the file)
        out.flush();
        out.close();
    }
    catch (FileNotFoundException fnfe1) {
        /* I get the error here */
        Log.e("tag", fnfe1.getMessage());
    }
    catch (Exception e) {
        Log.e("tag", e.getMessage());
    }
}

ES Datei-Explorer

Ich habe gesehen, dass der ES File Explorer auf Redmi-Geräten auch nichts auf die SD-Karte schreiben kann. Hier ist ein Video mit Lösung . Befolgen Sie die Schritte für ES Explorer auf meinem Gerät. Kann das programmgesteuert gemacht werden?

17
Sahil Khanna

Wie von @CommonsWare vorgeschlagen, müssen wir hier das neue von Android bereitgestellte Storage Access Framework verwenden und die Erlaubnis des Benutzers zum Schreiben einer SD-Kartendatei einholen, da Sie bereits gesagt haben, dass diese Datei bereits im File Manager Application ES File Explorer geschrieben ist.

Hier ist der Code, damit der Benutzer die "SD-Karte" wählen kann:

startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), requestCode);

das sieht dann ungefähr so ​​aus:

 enter image description here

Holen Sie sich den Dokumentpfad in pickedDirund übergeben Sie ihn weiter in Ihrem copyFile-Block Verwenden Sie diesen Pfad zum Schreiben der Datei:

public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (resultCode != RESULT_OK)
        return;
    else {
        Uri treeUri = resultData.getData();
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
        grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        copyFile(sdCard.toString(), "/File.txt", path + "/new", pickedDir);
    }
}


public void copyFile(String inputPath, String inputFile, String outputPath, DocumentFile pickedDir) {

    InputStream in = null;
    OutputStream out = null;
    try {

        //create output directory if it doesn't exist
        File dir = new File(outputPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        in = new FileInputStream(inputPath + inputFile);
        //out = new FileOutputStream(outputPath + inputFile);

        DocumentFile file = pickedDir.createFile("//MIME type", outputPath);
        out = getContentResolver().openOutputStream(file.getUri());

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();


        // write the output file (You have now copied the file)
        out.flush();
        out.close();
    } catch (FileNotFoundException fnfe1) {
    /* I get the error here */
        Log.e("tag", fnfe1.getMessage());
    } catch (Exception e) {
        Log.e("tag", e.getMessage());
    }
}
16
shadygoneinsane

Sie müssen die Berechtigungsanforderungslaufzeit in Android 6.0 (API Level 23) und höher hinzufügen. Hier sind die offiziellen -Dokumente

Dies ist der Code für WRITE_EXTERNAL_STORAGE

if (checkSelfPermission(Android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
    Log.d(TAG,"Permission is granted");

    return true;
}

Bitten Sie um Erlaubnis, sonst so

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
8
Junaid Hafeez

Ich habe auch dieses Problem, aber ich löste durch Verwendung der Anforderung die Erlaubnis zur Laufzeit und erteilte nach Erlaubnis die Erlaubnis. Nach der Erlaubnis in App-Info des Android-Geräts. Nachdem Sie die Erlaubnis in Manifest festgelegt haben => gehen Sie zur Einstellung Ihres Geräts => gehen Sie zu App-Info => Gehen Sie zu Erlaubnis => und geben Sie die Erlaubnis ab. Ich erinnere mich nur daran, dass ich gerade nach den API-Level 22 von Marshmallow rede.

1
Peter

Nach Android 4.3 auf einigen Geräten können Sie keinen direkten Schreibzugriff auf FileSystem on SDcard erhalten. 

Sie sollten Storage Access Framework dafür verwenden. 

1

Ich kann sehen, dass Sie den gesamten Inhalt einer Datei kopieren und versuchen, diesen in eine andere Datei zu schreiben. Ich könnte einen besseren Weg vorschlagen, dies zu tun:

Angenommen, Sie haben bereits das Vorhandensein von Dateien geprüft 

StringWriter temp=new StringWriter();
        try{
            FileInputStream fis=new FileInputStream(inputFile+inputPath);
            int i;
            while((i=fis.read())!=-1)
            {
                temp.write((char)i);
            }
            fis.close();
            FileOutputStream fos = new FileOutputStream(outputPath, false);  // true or false based on opening mode as appending or writing
            fos.write(temp.toString(rs1).getBytes());
            fos.close();
        }
        catch (Exception e){}

Dieser Code hat für meine App funktioniert ... Lassen Sie mich wissen, ob dies für Sie funktioniert oder nicht ..

1
bharath

Es sieht so aus, als ob die Laufzeitberechtigung korrekt implementiert wurde, aber die Probleme scheinen vom Gerät zu stammen Wenn Sie Redmi verwenden, müssen Sie manuell die Erlaubnis für eine bestimmte App in den Redmi-Sicherheitseinstellungen zulassen Dieses link wird angezeigt So aktivieren Sie die Erlaubnis in der Redmi-Sicherheit

1

Sie können Dateien und Ordner nicht mit einer Drittanbieter-App auf einem externen Speicher kopieren oder löschen. wie [Datei-Explorer].

Die Datenrichtlinie wurde nach KitKat Version aktualisiert. 

Wenn nur auf System-Apps zulassen. Sie können also einen Original-Datei-Explorer verwenden (von ROM kommen).

WENN Sie die App eines Drittanbieters benötigen, dannROOTIhr Gerät. (Root-Berechtigung ist erforderlich)

0
Jigar Patel

Ab Api 23 und höher müssen Sie explizit nach Berechtigungen fragen. Wie Sie bereits erwähnt haben, beantragen Sie eine Laufzeitberechtigung. Ich werde vorschlagen, dass Sie dies tun:

In deinem Fragment oder in deiner Aktivität 

 if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED)

        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                PERMISSION_CODE);
    else
        copyFile(params...);

Dann überschreiben Sie diese Methode in der Aktivität/Fragment

     @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            switch (requestCode) {
                case PERMISSION_CODE:
                    copyFile(params...);
                    break;
            }
        }

// if user checks "don't show again" and presses deny on the permission dialog 
// then it will not show up again, in that case you need to show some message to the user 
// to go in the settings and enable permissions manually

         else if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                ToastManager.showLongToast(getActivity(), "Go to app settings and turn on permissions to enjoy complete features");
            }