Dateien sichern in Android 10 - 11

  • Antworten:11
Hermann Robl
  • Forum-Beiträge: 10

19.04.2020, 15:10:11 via Website

Hallo alle zusammen,

ich hätte mal eine Frage zum Speichern von z.B. Textdateien.

Ab Android 10 existiert ja der Ordner "Documents" nicht mehr. Welche Möglichkeiten habe ich, meine Textdateien der App
zu Speichern damit der Benutzer diese am PC sichern kann (Datensicherung). Der Documente Ordner war ja zugänglich am PC.

Jetzt habe ich in meiner neuen App die Dateien im internen App - Speicher (getFilesDir) gespeichert.
Beim manuellen Sichern über Google Drive (Google Datensicherung) ist mir dann aufgefallen, dass diese absolut unzuverlässig ist!
Mal werden die Daten richtig gesichert, dann manchmal werden obwohl die aktuellsten Daten gesichert wurden, ältere wiederhergestellt.
Mehrmals hatte ich auch schon nach Wiederherstellung der Sicherung alle Daten (.txt Dateien) verloren.
Das ist für die Käufer einer App aber nicht zumutbar. Man kann bei Neuinstallation der App oder Umstieg auf ein neues Gerät nicht
sicher sein das die aktuellen Dateien wiederhergestellt werden.

Ich überlege jetzt, meine App - Daten im Ordner "Downloads" zu Speichern. Aber wie ist es dann ab Android 11 Scoped Storage...
App ist ab Android 6 .

Viele Grüße erstmal

Hermann

Antworten
Gelöschter Account
  • Forum-Beiträge: 21.034

19.04.2020, 15:27:46 via Website

Hermann Robl

Ab Android 10 existiert ja der Ordner "Documents" nicht mehr.

Das Verzeichnis gab es in Android nie. Wenn es vorhanden ist, liegt das an der jeweiligen ROM, einer App oder der Nutzer hat ihn angelegt.

Welche Möglichkeiten habe ich, meine Textdateien der App

Prüfe doch, ob es das Verzeichnis gibt und wenn nicht, lass es anlegen.

Antworten
Jokel
  • Forum-Beiträge: 1.527

19.04.2020, 15:38:47 via Website

Hallo
wie war den der genaue Path zu dem Ordner?

Antworten
Hermann Robl
  • Forum-Beiträge: 10

19.04.2020, 15:55:16 via Website

Natürlich. Kannst in jeden Buch nachlesen...

Example: getting the Documents folder would look like: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)

Antworten
Jokel
  • Forum-Beiträge: 1.527

19.04.2020, 16:06:56 via Website

Ja wenn du ihn so mit den richtigen Premission erstellts wird er da sein .
Er ist dann auf der internen SdKarte.

Antworten
Stefan Z.
  • Forum-Beiträge: 3.806

19.04.2020, 18:22:59 via App

Natürlich gibt es den Ordner Documents seitens Android.

Xiaomi Mi 9T, Android 10, Stock ohne Root.

Antworten
Jokel
  • Forum-Beiträge: 1.527

19.04.2020, 21:15:00 via Website

Hallo auf einem Standard jungfräulichen Android ist der Ortner nicht vorhanden.
Wenn doch wurde er von dir oder einer App erstellt.

Die Methode die du nennst ist ab Android Api 29 deprecated .
Environment.getExternalStoragePublicDirectory(....

Auch der volle zugriff auf die interne oder externe SD karte ist nicht mehr mit den üblichen File Methoden möglich.
Auch das vorher erstellen des Ordners mit mkDir() ist da so nicht mehr möglich.
Ohne SAF geht es nicht mehr vollzugriff auf die Sdkarte zu haben.
https://developer.android.com/guide/topics/providers/document-provider

Hier mal etwas Beispiele Code zum testen wo du zugriff hast. Lasse unter den verschrienen APIs laufen und du wirst im log sehen was geht.
Ich gehe mal davon aus das du die Permissoin WRITE_EXTERNAL_STORAGE hast denn die braucht du unter API 23 ja auch.

void test(){

    File f= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
    if( f.exists()!= true){
        boolean bb = f.mkdir();
    }

    String extPath= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
    File file0 = new File(extPath,"new0.txt");
    try {
        Log.i("test", "Datei 0 :"+ extPath );
        boolean b = file0.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file0  :"+ extPath +"  " + e);
        e.printStackTrace();
    }

    // path ohne Permission
    extPath = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
    File file1 = new File(extPath, "neu1.txt");
    try {
        Log.i("test", "Datei 1 :"+ extPath );
        boolean b = file1.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file1  :"+ extPath +"  " + e);
        e.printStackTrace();
    }

    // interne sd Karte

    File[] fs = getExternalFilesDirs(null);
    extPath = fs[0].getAbsolutePath();

    File file2 = new File(extPath, "neu2.txt");
    try {
        Log.i("test", "Datei 2 :"+ extPath );
        boolean b = file2.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file2  :"+extPath +"  " + e);
        e.printStackTrace();
    }

    extPath = fs[0].getAbsolutePath().substring(0, fs[0].getAbsolutePath().indexOf("/A"));
    File file3 = new File(extPath, "neu3.txt");
    try {
        Log.i("test", "Datei 3 :"+ extPath );
        boolean b = file3.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file3  :" +extPath +"  "+ e);
        e.printStackTrace();
    }

    //externe sd Karte

    extPath = fs[1].getAbsolutePath();

    File file4 = new File(extPath, "neu4.txt");
    try {
        Log.i("test", "Datei 4 :"+ extPath );
        boolean b = file4.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file4  :" +extPath +"  "+ e);
        e.printStackTrace();
    }

    extPath = fs[1].getAbsolutePath().substring(0, fs[1].getAbsolutePath().indexOf("/A"));
    File file5= new File(extPath, "neu5.txt");
    try {
        Log.i("test", "Datei 5 :"+ extPath );
        boolean b = file5.createNewFile();
    } catch (IOException e) {
        Log.i("test", "Fehler bei file5 :"+extPath +"  "+ e);
        e.printStackTrace();
    }

}

— geändert am 19.04.2020, 21:58:04

Antworten
Hermann Robl
  • Forum-Beiträge: 10

19.04.2020, 21:46:28 via Website

Vielen lieben Dank für die Tipps.
Werde ich morgen mal testen.
Melde mich dann nochmal...

Antworten
Hermann Robl
  • Forum-Beiträge: 10

20.04.2020, 13:15:50 via Website

Hallo Jokel,

verwende ich "getExternalFilesDir" oder "getFilesDir", werden laut Doku meine Dateien beim
deinstallieren der App gelöscht. Ganau das will ich aber nicht. Ich möchte das die mit der
App erstellten Dateien nach Deinstallation der App erhalten bleiben.
Der Anwender soll zugriff auf die Dateien haben, diese z.B. über PC sichern können.

Mit "Files Dir" bin ich wiederum von der Google Datensicherung abhängig, welche ja nicht so richtig
funktioniert.

Meine App läuft bisher noch mit Permission u. "Environment.getExternalStoragePublicDirectory(...."
unter Android 10. Bei 11 wahrscheinlich nicht mehr?

Antworten
Jokel
  • Forum-Beiträge: 1.527

20.04.2020, 16:06:47 via Website

Hallo also ich habe nicht geschaft unter Android 10 vollen Zugriff auf die interne sd karte zubekommen. Mit den klassischen Methoden.

Nur mit SFA nachdem ich mir die Berechtigung die Uri vom User geholt habe.

Antworten
Jokel
  • Forum-Beiträge: 1.527

20.04.2020, 20:16:06 via Website

Hallo der Zugriff mit
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
boolean bb = file.mkdirs();

Geht nur bis API 28. Eine Möglichkeit ist die targetSdkVersion auf 28 zu setzen im bulid.gradle.
Damit ist es zwar keine Richtige API 29 APP geht auch unter API 30 Android R.

Auf die exchte sd Karte kommst du schon seit Android 5.1 nur noch mit SAF.

Ansonsten versuche hier mal meinen code.

public class MainActivity extends AppCompatActivity {

// speichert die Uri zum externen Speicher
DocumentFile treeUrlDir;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(
            this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
                this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 12345);
    } else {
        getSAF_Preissoin();
    }
}

void getSAF_Preissoin() {
    SharedPreferences TreePref = getSharedPreferences("SAF_Permission", 0);
    String st = TreePref.getString("TreeURL", "");
    if (!st.equals("")) {
        treeUrlDir = DocumentFile.fromTreeUri(this, Uri.parse(st));
        permissionOK();
    } else {
        startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), 42);
    }
}

void permissionOK() {
    test();
    // hier Ccode wenn Permissoin OK
    String text;
    DocumentFile dir1 = treeUrlDir.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();
    }
}

void test()  {
    // geht nur mit  targetSdkVersion 28 mit 29 nicht mehr
    File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
    boolean bb = file.mkdirs();
    File  file2 = new File(file,"test.txt");
    try {
        file2.createNewFile();
    } 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();
}

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 12345) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Log.i("resultcode", "dateierstellen  " + requestCode);
            getSAF_Preissoin();
        } else {
            Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == 42) && (resultCode == RESULT_OK) && (data != null)) {
        treeUrlDir = DocumentFile.fromTreeUri(this, data.getData());
        SharedPreferences TreePref = getSharedPreferences("SAF_Permission", 0);
        SharedPreferences.Editor TreeEd = TreePref.edit();
        TreeEd.putString("TreeURL", treeUrlDir.getUri().toString());
        TreeEd.commit();
        permissionOK();
    }
}

}

Antworten
Hermann Robl
  • Forum-Beiträge: 10

23.04.2020, 17:48:51 via Website

Danke Dir nochmals Jokel,

ich mache es jetzt mit "extPath = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();"

Wollte hauptsächlich nur das der Benutzer die Daten auch auf dem PC speichern kann u. sich nicht nur auf die Google - Sicherung verlassen muss. Das geht hiermit.

Mit getFilesDir (Hatte ich vorher), hat mann ja über den PC keinen Zugriff auf die internen App - Dateien.

Nochmals Danke

Hermann

Antworten