Schreiben auf die echte externe SD-Carte

  • Antworten:14
Jokel
  • Forum-Beiträge: 1.530

05.02.2019, 17:09:27 via Website

Hallo Ich möchte schreibend auf die echte externe SD-Carte zugreifen.
Dabei meine ich nicht die intern emulated/0 Karte.
Auch will ich nicht nur auf die externe Kate in den Ordner Android/data/….. sondern auf das Root der Karte zugreifen und zwar schreibend.

Mit
File[] extStorageState=ContextCompat.getExternalFilesDirs(MainActivity.this, null);

Bekomme ich den Phat zu: /storage/120D-1904/Android/data/meinpacketname/files
Schreiben lesen kein Problem

Mit
File dir = Environment.getExternalStorageDirectory();

Bekomme ich: /strorage/emulated/0
Schreiben, Lesen kein Problem

Mit:
File storage_dir = new File("/storage");
File[] files = storage_dir.listFiles();
File dir = files[0];

Habe ich zwar den Phat der SD-Carte aber nur lesend und nicht schreibend.

Wobei ich meine die Permission mittels ASK Lib gesetzt zu haben.

Wie gesagt das lesen einer Datei im Root der SD-Karte geht nur schreiben nicht.

Hoffe mir kann einer helfen die richtige Permission für die sd-Karte zu setzen.

Das Schreiben auf die internne Karte auch ins Root geht.

Sage schon mal Danke.

— geändert am 05.02.2019, 17:57:03

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.02.2019, 18:42:13 via Website

Hallo Jockel,

das mit der physischen externen SD und schreibzugriff aus Apps ist inzwischen eine komplizierte Sache, die in jeder Android Version anders ist, weil Google das ständig ändern muss...

Mein letzter Stand dazu: Du kannst auf externe SD Karte nur in /Android/data/com.app.my/... schreiben, für alles andere Brauchst du Root Rechte...
Kann aber auch sein, dass das nicht stimmt, habe schon ewig nichts mehr damit gemacht.

Hier gibt es aber eine ganz gute Übersicht mit Links, damit müsstest du dich in die Thematik einlesen:
https://stackoverflow.com/a/40201333/4975457

ansonsten hilft das vlt:
https://developer.android.com/training/data-storage/files#WriteExternalStorage

Hast du zusätzlich zu ASK Lib die Permissions in der Manifest festgelegt?

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Jokel
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

05.02.2019, 19:11:32 via Website

Pascal erstmal danke für Die schnelle Antwort.

Ja ich habe die Permissions auch im Manifest.

Das es auch ohne Root Rechte gehen muss sieht man an den vielen Dateie Explorer Apps die das auch schaffen auf einen nicht gerooteten Gerät. Die fragen aber auch immer noch mal zusetzlich Rechte ab. Nur wie die das unter der Haube machen ist die große Frage.

Deine links schaue ich mir noch an. Habe ich bis jetzt noch nicht.

Ps. Leider sind die Links genau das was ich auch schon gefunden habe und auch alles getestet habe. Hat leider nicht geholfen.

— geändert am 05.02.2019, 19:25:28

Hilfreich?
Pascal P.
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.02.2019, 19:25:08 via Website

Dann kan ich dir leider nicht helfen.
Mein aktuelles Device hat keine externe SD, daher kann ich auch keine Verhaltenstests etc. machen...

Edit: Du kannst natürlich dir Apps und Beispielapps suchen die das können:
z.b. hier eine OpenSource FileExplorer App:
https://github.com/1hakr/AnExplorer
Wenn du das mit der installierten App machen kannst, dann lohnt es sich vlt. den Code anzuschauen, obwohl das bei einem größeren Projekt evtl. aufwändig werden könnte

— geändert am 05.02.2019, 19:28:17

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Jokel
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

05.02.2019, 19:30:45 via Website

Ok verstehe. Aber im Emulator ab API 25 wird auch eine internen und externen sd karte simuliert. Da habe ich das gleiche verhalten wie im Handy oder Tab.

Hoffe noch auf weiter antworten.

Hilfreich?
Kommentieren
swa00
  • Forum-Beiträge: 3.704

05.02.2019, 22:01:05 via Website

Hast du mal den Weg durch Lesen der /system/etc/vold.fstab ausprobiert ??

Damit bekommst du die absoluten Mounts und bist Kernel unabhängig .

(So setze ich es zumindest um)

 private ArrayList<String> getMountPoints() {
        ArrayList<String> mountPointList = new ArrayList<String>();
        File voldFstab = new File("/system/etc/vold.fstab");
        Scanner scanner = null;
        try {
            scanner = new Scanner(new FileInputStream(voldFstab));
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                if (line.startsWith("dev_mount") || line.startsWith("fuse_mount")) {
                    String[] lineSplits = line.split("\\s+");
                    String mountPoint = lineSplits[2];
                    if (mountPoint.contains(":")) {
                        mountPoint = mountPoint.substring(0, mountPoint.indexOf(":"));
                    }
                    mountPointList.add(mountPoint);
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (scanner != null) scanner.close();
        }
        return mountPointList;
    }

    private ArrayList<String> getProcMounts() {
        ArrayList<String> procMountList = new ArrayList<String>();
        File procMounts = new File("/proc/mounts");
        Scanner scanner = null;
        try {
            scanner = new Scanner(new FileInputStream(procMounts));
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                if (line.startsWith("/dev/block") && !line.contains("asec")) {
                    String[] lineSplits = line.split("\\s+");
                    String procMount = lineSplits[1];
                    if (!procMountList.contains(procMount)) {
                        procMountList.add(procMount);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (scanner != null) scanner.close();
        }
        return procMountList;
    }
}

— geändert am 05.02.2019, 22:01:46

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
JokelPascal P.
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

05.02.2019, 22:50:58 via Website

@saw00 nein so habe ich es noch nicht Probiert. Erstmal Danke für den Tipp werde es Mogen mal testen.
Mir scheint das es das Beispiel was Pascal auf Github gefunden hat es ähnlich macht.

Bedanke mich auf jedenfal erstmal für die Hilfe bis hierhin. Melde mich wenn ich weiter gekommen bin. Ob ich Morgen dazu komme zum testen kann ich nicht sagen. Freue mich schon mal über die Tipps.

Danke Danke Jörg.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

06.02.2019, 08:43:42 via Website

Hallo muss leider sagen das mir die Variante von saw00 wohl nicht zu viel helfen wird.
Denn die fstab Datei biegt es seit Android 4.2.2 nicht mehr in dieser form.
Vor länger Zeit hatte ich die Suche Non mal wegen einem anderen Grund gesucht.

Na dann werde ich wohl weiter suchen.

Hilfreich?
Kommentieren
swa00
  • Forum-Beiträge: 3.704

06.02.2019, 10:23:56 via Website

Ja und in den Mounts ?

Deshalb hatte ich dir beide varianten aufgezählt ,
Bei mir läuft es so bis 8.x (9 habe ich noch nicht getestet)

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

06.02.2019, 12:06:41 via Website

Hallo @saw00 erstmal Danke für die mühe.

irgendetwas scheint mit meinen Permission noch nicht zu stimmen.

Beim versuch auf eine Datei lesend zuzugreifen kommt der Fehler
java.io.FileNotFoundException: /mnt/media_rw/120D-1904/Hallo/Hallo.txt (Permission denied)

habe den Code mit den Mounts benutzt.
String 0 scheint meie SD-Karte zu sein "/mnt/media_rw/120D-1904"

ArrayList<String> mountPoint = getProcMounts();
File sdmount = new File(mountPoint.get(0),"Hallo/Hallo.txt");
try {
BufferedReader br = new BufferedReader(new FileReader(sdmount));

        String zeile1 = br.readLine();
        br.close();

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

die Datei existiert und hiermit kann ich sie auch lesen.

File storage_dir = new File("/storage");
        File[] files = storage_dir.listFiles();
        File datei = new File(files[0],"Hallo/Hallo.txt");
                           // datei -> "/storage/120D-1904/Hallo/Hallo.txt"

 try {
          BufferedReader br = new BufferedReader(new FileReader(datei));
                String zeile1 = br.readLine();
                br.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

— geändert am 06.02.2019, 12:12:42

Hilfreich?
Kommentieren
swa00
  • Forum-Beiträge: 3.704

06.02.2019, 15:57:16 via Website

Jörg ,

nicht falsch verstehen - manchmal sieht mal vor lauter Bäumen den Wald nicht mehr :

Aber an sowas Triviales, beim User die Permissions anzufragen , haste schon gemacht , oder ? :-)

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

06.02.2019, 16:07:46 via Website

Ja habe ich .
Habe das auch am Anfang gesagt. Und wenn ich die nicht hätte könnte ich mit meiner Methode auch nicht die Datei lesen.

Ich habe es mit der ask lib versucht und mit der wie es die Google steht.
Auch habe ich sie im manifest gesetzt.

hier meine beiden Varianten

 // Primission für sdkarte einholen mit ASK LIB
    Ask.on(this)
            .debug(true)
            .id(123)
            .forPermissions(Manifest.permission.ACCESS_COARSE_LOCATION
                    , Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .withRationales("Location permission need for map to work properly",
                    "In order to save file you will need to grant storage permission") //optional
            .go();



    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
             != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

        } else {
             ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);
         }
    } else {

        ArrayList<String> mountPoint = getProcMounts();
        File sdmount = new File(mountPoint.get(0),"Hallo/Hallo.txt");
        try {
            BufferedReader br = new BufferedReader(new FileReader(sdmount));
            String zeile1 = br.readLine();
            br.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

— geändert am 06.02.2019, 16:16:23

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

07.02.2019, 13:30:33 via Website

Hallo
so habe nun eine Lösung gefunden wie ich Lesend und Schreibend auf die echte SD-Carte zugreifen kann.

Ich habe es mit den StorageManaager gemacht.
Hier ein Beispiel für das lesen, schreiben geht auch.
Bedanke mich für die Hilfe von allen. :*

Danke, Danke

Jörg

private static final int REQUEST_CODE = 123;
SharedPreferences pref;
SharedPreferences.Editor ed;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    pref = PreferenceManager.getDefaultSharedPreferences(this);
    ed = pref.edit();

    StorageManager m = getSystemService(StorageManager.class);
    if (m != null) {
        List<StorageVolume> volumes = m.getStorageVolumes();
        StorageVolume volume = volumes.get(1);

        String st = pref.getString("URL",null);
        if( st == null) {
            Intent intent = volume.createAccessIntent(null);
            startActivityForResult(intent, REQUEST_CODE);
        }else{
            Uri uri = Uri.parse(st);
            DocumentFile du = DocumentFile.fromTreeUri(this,uri);

            String text;
            DocumentFile dir1 = du.findFile("Hallo");
            DocumentFile dir2 = dir1.findFile("Hallo.txt");
            try {
                text = readTextFromUri(dir2.getUri());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == REQUEST_CODE) && (resultCode == RESULT_OK) && (data != null)) {
        DocumentFile dir = DocumentFile.fromTreeUri(this, data.getData());

        ed.putString("URL",dir.getUri().toString());
        ed.commit();

        String text;
        DocumentFile dir1 = dir.createDirectory("Hallo");
        DocumentFile dir2 = dir1.createFile("txt","Hallo.txt");

        try {
            writeTextToUri(dir2.getUri());
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            text = readTextFromUri(dir2.getUri());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

private String readTextFromUri(Uri uri) throws IOException {
    InputStream inputStream = getContentResolver().openInputStream(uri);
    BufferedReader reader = new BufferedReader(new InputStreamReader( inputStream));
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        stringBuilder.append(line);
    }
    reader.close();
    return stringBuilder.toString();
}

private void writeTextToUri(Uri uri) throws IOException {
    OutputStream outPutStream = getContentResolver().openOutputStream(uri);
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outPutStream));
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    writer.write("Hallo das ist ein Text");
    writer.close();
}

— geändert am 07.02.2019, 14:48:34

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

10.02.2019, 09:58:41 via Website

Hallo @saw00
Ich habe es zwar mit den StorageManager geschafft auf die SD-Carte zuzugreifen.
Nun würde es mich aber doch noch Interessieren wie du das über den absoluten Phat der Mounts machst. Mit einen File Objekt kann ich bis API 22 auf den Phat darauf zugreifen.

Wie würdest du auf den Block

/dev/block/vold/public:253,64 /mnt/media_rw/1804-0209 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0

Phat /mnt/media_rw/1804-0209 Zugreifen?

Mit welchen Methoden machst du das?

Gib mir da doch Bitte nochmal einen Tipp.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

13.02.2019, 15:16:25 via Website

Hallo schade das es keine weitere Tips gibt. Wie ich ohne SAF auf die Karte zugreifen kann.
Den path habe ich ja nun dank saw00 top mir den mounts. Nur mit den klassischen file Methoden habe ich keinen Zugriff darauf. Obwohl ich der Meinung bin die Permissions gesetzt zu haben. Im Manifest und auch zur Laufzeit vom User.

Hilfreich?
Kommentieren