Dateizugriff externalStorage auf third Party App mit API30

  • Antworten:19
swa00
  • Forum-Beiträge: 3.704

11.05.2021, 07:01:47 via Website

Moin Zusammen,

ich schreibe derzeit ein bestehendes Package um , welches aus dem dataPath einer thirdParty-App Dateien ausliest. Unter API 30 habe ich keine Zugriffe mehr.
(Auch der hausinterne Dateimanager kommt nur noch bis /android/data (darin alles leer)

Allerdings : Mit einer USB Verbindung (PC) oder DeviceExplorer in AS habe ich Zugriff

File file = new File(.... bla bla> /android/data/THIRDPARTY_APP/files/"");
File[] files = > file.listFiles(); < -- Liefert null zurück - nicht einmal ein Exception

.....

< uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" / >
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" / >
< uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" / >

....
Alternative für API29

< application
android:requestLegacyExternalStorage="true"

Wo bin ich zu Blöde oder muss ich das Teil tatsächlich rooten ?

Danke

— geändert am 11.05.2021, 12:27:54

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

Kommentieren
Andy
  • Forum-Beiträge: 401

11.05.2021, 15:57:58 via Website

Nabend, ich weiß nur, dass die Entwickler alle ein wenig rumtricksen, um drauf zugreifen zu können. Unter API 30 geht das mit dem Zugriff z.B. auf Android/data/ ja bekanntermaßen nicht mehr (ist seit einigen Monaten Thema im Netz).
https://www.xda-developers.com/android-11-features-developers-new-apis/

Trotz der neuen Berechtigung "Zugriff auf alle Dateien" hat man ja noch nicht mal Zugriff auf den Download-Ordner.

Aber bei allen relevanten Apps klappt es eigentlich auch mit API 30 wieder, bei den guten Dateimanagern, FolderSync, Syncthing Fork usw. Die haben alle einen Weg gefunden, um auf alle Ordner zugreifen zu können.

Deshalb vermute ich, man findet im Netz diverses dazu, kann aber selbst nicht sagen, wo.

— geändert am 11.05.2021, 19:47:05

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

11.05.2021, 19:24:19 via Website

Hallo hier mal ein einfaches Beisiel mit den ich es immer bis API 29 geschafft habe auf die volle SD Karte intern oder echte externe zuzugreifen.
Unter API 30 kann ich nur noch einen Verzeichnis aus wählen und auf das dann zugreifen.
Natürlich muss das vom User am Anfang ausgewählt und bestätigt werden.
Hoffe das hilft weiter.

    package com.jw.sdcard_saf_api23_extern;

import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.documentfile.provider.DocumentFile;

import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    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() {

        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();
        }
    }




    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();
        }
    }
}
Hilfreich?
swa00
Kommentieren
swa00
  • Forum-Beiträge: 3.704

14.05.2021, 16:30:10 via Website

Hallo Jokel,

vielen lieben Dank für deine Mühe.

Das funktioniert soweit ganz gut, allerdings lässt sich kein rekursives Einlesen eines
Verzeichnisbaumes realisieren.

Ich habe mir auch verschiedene Filemanager GitHub Projekt angeschaut,
die hören aber auch schon an dem Punkt auf und können es auch nicht (nur bis API29)
Der Source von denen ist teilweise eben mal 3 Tage alt.

Ich denke , ich werde jetzt LineageOS nehmen , dann habe ich Ruhe :-)

— geändert am 14.05.2021, 16:33:28

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

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

14.05.2021, 16:45:28 via Website

Hmm, es können aber Apps auch mit API 30.

Ist das nirgends dokumentiert? (Oder darf es nicht?). Dann am besten mal konkret jemanden anschreiben, denke ich.

— geändert am 19.07.2021, 22:18:08

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

14.05.2021, 16:55:37 via Website

Andi , nenne mir bitte einen Filemanager, der unter API 30
auf den Android/data Ordner (und darunter) die Files einer anderen App anzeigt.

Selbst der Hauseigene Filemanager von Samsung macht das nicht mehr.

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

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

14.05.2021, 17:24:05 via Website

Hallo
Der Ordner android/data/packet Name oder der /data/data/.... war aber schon immer ohne Root Tabu.

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

14.05.2021, 17:46:24 via Website

@swaa00

Spontan aus dem Kopf: FolderSync Pro

Hat auch einen Dateimanager eingebaut. Und synct natürlich.

— geändert am 14.05.2021, 17:47:10

Hilfreich?
Kommentieren
Gelöschter Account
  • Forum-Beiträge: 21.034

19.07.2021, 21:18:25 via Website

Andy

@swaa00

Spontan aus dem Kopf: FolderSync Pro

Nicht ab API 30!

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

19.07.2021, 21:26:30 via Website

Geht. FolderSync (Pro) ist auf Ziel-API 30 und kann in Ordner innerhalb Android/data und darunter lesen und schreiben.

Du hast es sicher ausprobiert, bevor du deinen Beitrag geschrieben hast?

— geändert am 19.07.2021, 21:27:09

Hilfreich?
Kommentieren
Gelöschter Account
  • Forum-Beiträge: 21.034

19.07.2021, 21:39:40 via Website

Ja, ich habe es ausprobiert. Einmal unter LineageOS 18.1 (also Android 11) und einmal unter AndroidOne, ebenfalls mit Android 11. Beide haben FolderSync Pro 3.0.48

Anbei der Screenshot von LineageOS 18.1:

User uploaded photo

Auf dem AndroidOne-Gerät erscheint die gleiche Meldung.

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

19.07.2021, 21:44:05 via Website

Funktioniert auf unseren Geräten (alle Android 11), siehe hier:

imageimage

— geändert am 19.07.2021, 21:46:08

Hilfreich?
Kommentieren
Gelöschter Account
  • Forum-Beiträge: 21.034

19.07.2021, 21:45:51 via Website

Sind Eure Geräte gerootet? Meine sind es nicht.

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

19.07.2021, 21:46:52 via Website

Nein, keins gerootet.

— geändert am 19.07.2021, 21:47:03

Hilfreich?
Kommentieren
Sebastian
  • Forum-Beiträge: 371

20.07.2021, 13:40:12 via Website

Mit Rootrechten hat das nichts zu tun, da FolderSync Pro keine Rootrechte einfordert. Es müssen die richtigen Berechtigungen erteilt werden, siehe Screenshot.
image

Es muss der Zugriff auf /storage/emulated/0/Android gewährt werden.

(getestet mit LineageOS 18.1 und FolderSync Pro 3.0.48)

Hilfreich?
Kommentieren
Gelöschter Account
  • Forum-Beiträge: 21.034

20.07.2021, 13:55:34 via Website

In den Einstellungen von FolderSync kann man einstellen, dass Root-Rechte angefordert werden.

Ich habe es nochmal ausprobiert. Auf das Verzeichnis Android/data und Android/obb kann ich mit FolderSync weder auf dem internen Speicher noch auf der SD-Karte zugreifen. Tippe ich auf "Beheben" erscheint der gleiche Fehler wie in meinem Screenshot. Auf die üblichen Verzeichnisse kann ich sehr wohl zugreifen. Auch auf Android/media kann ich zugreifen.

Es liegt also nicht an nicht gewährten Berechtigungen.

Kommando zurück: Man kann den Zugriff tatsächlich freigeben. Der Weg dorthin erfolgt aber nicht in den Berechtigungen wie bei älteren Android-Versionen.

— geändert am 20.07.2021, 13:59:37

Hilfreich?
Kommentieren
Sebastian
  • Forum-Beiträge: 371

20.07.2021, 13:58:09 via Website

Bei mir und @Andy funktioniert es ja auch.

Hilfreich?
Kommentieren
Sebastian
  • Forum-Beiträge: 371

20.07.2021, 14:30:20 via Website

App öffnen > rechts unten auf die drei Striche (Über) > Berechtigungen

Hilfreich?
Kommentieren
Andy
  • Forum-Beiträge: 401

20.07.2021, 18:23:54 via Website

Aries

Kommando zurück: Man kann den Zugriff tatsächlich freigeben. Der Weg dorthin erfolgt aber nicht in den Berechtigungen wie bei älteren Android-Versionen.

Genau das meinte ich zu Beginn mit dem "rumtricksen" bei API 30 - solange es noch geht... Das Ist ja das Thema hier.

Es funktioniert übrigens nur bei Android/data im internen Speicher, auf SD funktioniert es nicht.

Hilfreich?
Kommentieren
Sebastian
  • Forum-Beiträge: 371

20.07.2021, 18:39:53 via Website

Die SD kann zur Not am PC oder aber auch via USB mit einem Kartenlesegerät komplett gelesen werden.

Hilfreich?
Kommentieren