Ошибка разрешения пользователя Android M - ПРОЧИТАЙТЕ и ПИШИТЕ

Я только начал с Android M, и я не могу получить доступ к внешней памяти. Я получаю следующую ошибку

Caused by: java.lang.SecurityException: Permission Denial: reading 
com.android.providers.media.MediaProvider uri 
content://media/external/images/media from pid=15355, uid=10053 requires 
android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission() 

Я добавляю пользовательское разрешение в манифест как

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

и мой файл сборки со следующими настройками:

compileSdkVersion 23
buildToolsVersion "22.0.1"

minSdkVersion 16
targetSdkVersion 23

Как читать и писать с внешнего хранилища в Android M?

5 ответов

Решение

Чтение из документации. Я должен запросить у пользователя разрешение во время выполнения. Пример кода:

Добавьте разрешение для Android манифеста, как мы делали раньше:

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

Проверьте, предоставил ли пользователь разрешение. Если да, пропустите запрос на разрешение и продолжите работу, иначе попросите разрешения у пользователя:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!Settings.System.canWrite(this)) {
        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE}, 2909);
    } else {
        // continue with your code
    }
} else {
    // continue with your code
}

Теперь, чтобы проверить, предоставил ли пользователь разрешение или отклонил его @OverrideOnRequestPermissionResult чтобы получить обратный звонок:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case 2909: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e("Permission", "Granted");
            } else {
                Log.e("Permission", "Denied");
            }
            return;
        }
    }
}

Я не смог ПРОЧИТАТЬ внешнее хранилище только запросив разрешение WRITE, поэтому мне пришлось запросить Manifest.permission.READ_EXTERNAL_STORAGE также.


Также, если вы хотите настроить таргетинг на версии ниже API 23, проверьте версию сборки во время выполнения с IF Заявление и запросить разрешения, только если VERSION равен или выше Android M,

Если вы ищете способ справиться с любой версией Android (вы компилируете для M, но некоторые устройства могут использовать другие версии), есть версия совместимости.

if (ContextCompat.checkSelfPermission(CreatePlayerActivity.this,
            Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(CreatePlayerActivity.this,
                Manifest.permission.READ_EXTERNAL_STORAGE)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(CreatePlayerActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }

Что касается выбранного ответа:

Settings.System.canWrite(this) а также WRITE_EXTERNAL_STORAGE это две разные вещи! Должно быть:

    boolean needsRead = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED;

    boolean needsWrite = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED;

    if (needsRead || needsWrite)
        requestStoragePermission()

Я боролся с WRITE_EXTERNAL_STORAGE разрешение: после того, как я просил это, диалог не показывался и немедленно возвращался DENIED,

Проблема была в одной из включенных библиотек. Он содержал такую ​​же декларацию разрешения в своем AndroidManifest.xml, но с maxSdkVersion="22", Объявление в файле манифеста приложения было переопределено библиотекой.

Чтобы переопределить разрешение из библиотеки, я использовал следующее:

  <uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    tools:node="remove"
    tools:selector="com.example.lib" />

Я надеюсь, что это может быть полезно.

Я использовал эту утилиту на GitHub. Он работает с API 22 и 23. Добавление разрешений во время выполнения не сложно, но немного отделить ваш код и переместить методы для захвата обратных вызовов. Эта библиотека предоставляет связанный API для того, чтобы делать все, что вам нужно для поддержки разрешений во время выполнения.

https://github.com/kayvannj/PermissionUtil

Другие вопросы по тегам