it-swarm.com.de

Oreo (WRITE EXTERNAL STORAGE) Erlaubnis

Laut "developer.Android.com"

If the app targets Android 8.0 (API level 26), the system grants only 
READ_EXTERNAL_STORAGE at that time; however, if the app later requests 
WRITE_EXTERNAL_STORAGE, the system immediately grants that privilege 
without prompting the user.

Jetzt habe ich den READ_EXTERNAL_STORAGE und fordere den DownloadManager auf, eine Datei im öffentlichen Download-Ordner herunterzuladen

downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mAttachmentItem.getFilename());

Leider bekam ich 

E/UncaughtException: Java.lang.IllegalStateException: Unable to create directory: /storage/emulated/0/data/user/0/com.abc.cba/files
                                                                           at Android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.Java:699)

Ich habe beide Berechtigungen im Manifest erklärt

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

Die Leseberechtigung ist bereits erteilt, und in Runtime fordere ich die Schreibberechtigung an. Das System fordert keine Meldungen oder Dialoge auf. Es wird immer "Nicht erteilt" in "onRequestPermissionsResult" angezeigt

public static boolean isPermissionsToAccessStorageAreGranted(Context context, Activity activity) {
    ArrayList<String> permissions = new ArrayList<>();

    if (!PermissionUtil.checkPermissions(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    if (!permissions.isEmpty()) {
        String[] permissionsList = permissions.toArray(new String[permissions.size()]);
        PermissionUtil.requestPermissions(activity, permissionsList,
                PermissionUtil.REQUESTCODE_ACCESS_STORAGE);
        return false;
    } else {
        return true;
    }
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode==REQUESTCODE_ACCESS_STORAGE && grantResults[0]== PackageManager.PERMISSION_GRANTED){
 /* downloadFile(); */       
    }
}

Ich versuche, diese beiden Berechtigungen über ADB zu erteilen. Es wird ein Fehler angezeigt:

adb Shell pm grant com.abc.cba 
Android.permission.WRITE_EXTERNAL_STORAGE
Operation not allowed: Java.lang.SecurityException: Package com.abc.cbs 
has not requested permission Android.permission.WRITE_EXTERNAL_STORAGE

adb Shell pm grant com.abc.cba 
Android.permission.READ_EXTERNAL_STORAGE
Operation not allowed: Java.lang.SecurityException: Can't change 
Android.permission.READ_EXTERNAL_STORAGE. It is required by the 
application
13
SoulaimenK

Eigentlich war es ein äußeres Problem. Eine der App Libs, die ich verwende, beantworte die WRITE_EXTERNAL_PERMISSION mit Android: maxSdkVersion. Wenn Sie also mein Manifest zusammenführen, wird die Berechtigung für die gesamte Anwendung entfernt.

Die Lösung ist, hinzuzufügen:

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/> 
14
SoulaimenK

Sie haben Recht, dem Manifest die Berechtigungen hinzuzufügen:

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

Für Lollipop-Versionen und höher müssen Sie die Berechtigungen zur Laufzeit auch anfordern. Um dieses Problem zu lösen, habe ich eine neue Methode requestAppPermission erstellt, die ich beim Erstellen der Hauptaktivität aufrufe. Diese Methode wird nur für Lollipop und höher ausgeführt und kehrt früher zurück, ansonsten:

private void requestAppPermissions() {
    if (Android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        return;
    }

    if (hasReadPermissions() && hasWritePermissions()) {
        return;
    }

    ActivityCompat.requestPermissions(this,
            new String[] {
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code
}

private boolean hasReadPermissions() {
    return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}

private boolean hasWritePermissions() {
    return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}

Ich rufe diese Methode in onCreate der Aktivität auf:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Other things
    requestAppPermissions();
}

Beim ersten Laden fordert der Benutzer dazu auf, Berechtigungen zu akzeptieren.

Bevor Sie Code ausführen, der gelesen und in den Speicher geschrieben werden muss, können Sie diese Berechtigungen prüfen, indem Sie die Werte speichern oder diese Prüfungen erneut mit den oben definierten Methoden hasReadPermissions() und hasWritePermissions() ausführen.

7
Tina

Für Oreo 

sie müssen explizit eine READ_EXTERNAL_STORAGE-Anforderung (per Code) ausführen, auch wenn Sie bereits die WRITE_EXTERNAL_STORAGE-Berechtigung angefordert haben und umgekehrt, und umgekehrt. 

vorher wird READ_EXTERNAL_STORAGE automatisch gewährt, wenn WRITE_EXTERNAL_STORAGE gewährt wird.

also, was Sie tun müssen, ist zu 

1) Fragen Sie in Ihren Codes nach der Berechtigung WRITE.

2) Wenn der Benutzer die Berechtigung WRITE erteilt, fragen Sie erneut nach der Berechtigung READ. Diese wird automatisch erteilt (Sie erhalten eine Ausnahme, wenn Sie nicht nach einem _ read _ fragen. explizit)

Die Änderungen für Oreo sind für mich nicht sehr sinnvoll (keine Ahnung, warum wir nach einer automatisch erteilten Erlaubnis fragen müssen), aber das ist es.

https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html#rmp

3
Angel Koh

Wenn Sie Berechtigung verweigert Fehler erhalten, auch wenn die Berechtigungen erteilt wurden und Sie bereits Berechtigungsprüfungen implementiert haben,

stellen Sie sicher, dass Sie nicht auf API-Level 29 abzielen:

Ändern Sie targetSdkVersion und compilesdkversion von 29 bis 28 oder eine andere niedrigere Stufe.


Hoffentlich erspart dies jemandem etwas geistige Gesundheit und ihre Haare. Ich habe einige von mir verloren, als ich gegen diesen Unsinn gekämpft habe.

2
John Doe

Sie müssen Berechtigungen zur Laufzeit auf Marshmallow oder höher ..__ erteilen. 

private static final int REQUEST_WRITE_STORAGE = 112;

if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            boolean hasPermission = (ContextCompat.checkSelfPermission(getBaseContext(),
                    Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
            if (!hasPermission) {
                ActivityCompat.requestPermissions(SplashScreen.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.INTERNET
                        },
                        REQUEST_WRITE_STORAGE);
            }else{ startMainActivity(); }
        }

Ich hoffe es hilft.

Nur ein Hinweis: Auf Android P musste ich ein Dialogfeld zum Beenden anzeigen, in dem der Benutzer aufgefordert wurde, die App neu zu starten, da die oben geschriebene App nach dem Neustart keine externen Speicher lesen konnte. Im Ernst, die Jungs von Google machen Android jedes Mal besser. 6, 8, und jetzt so viele Probleme mit 9, ein weiteres solches blödes Update und ich werde zu iOS gehen :)

0
Tertium