Подтвердить что ты не робот

Запрос и разрешение WRITE_EXTERNAL_STORAGE во время выполнения не влияет на текущий сеанс

это касается новой модели разрешений во время выполнения, введенных в Android Marshmallow при запросе разрешения Manifest.permission.WRITE_EXTERNAL_STORAGE.

Короче говоря, то, что я испытываю, заключается в том, что если я запрашиваю (и позволяет пользователю) разрешение Manifest.permission.WRITE_EXTERNAL_STORAGE, приложение не сможет читать и писать из внешнего каталога хранилища, пока я не уничтожу и не перезапущу приложение.

Это то, что я делаю/испытываю:

Мое приложение начинается с состояния, в котором:

ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED

Это значит, что у меня нет прав доступа к внешнему хранилищу.

Затем я запрашиваю разрешение Manifest.permission.WRITE_EXTERNAL_STORAGE так же, как Google объясняет

private void requestWriteExternalStoragePermission() {
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        new AlertDialog.Builder(this)
                .setTitle("Inform and request")
                .setMessage("You need to enable permissions, bla bla bla")
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
                    }
                })
                .show();
    } else {
        ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
    }
}

Как только пользователь разрешает разрешение, вызывается onRequestPermissionsResult.

@Override
public void onRequestPermissionsResult(int requestCode,  String permissions[], int[] grantResults) {
    switch (requestCode) {
        case RC_PERMISSION_WRITE_EXTERNAL_STORAGE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && PackageManager.PERMISSION_GRANTED
                // allowed 
            } else {
                // denied
            }
            break;
        }
    }
}

Выполняется блок allowed, подтверждающий, что пользователь предоставил разрешения.

Немедленно после этого, если я не уничтожу и не открою приложение снова, у меня все еще нет доступа к внешнему хранилищу. Более конкретно:

hasWriteExternalStoragePermission();                  // returns true
Environment.getExternalStorageDirectory().canRead();  // RETURNS FALSE!!
Environment.getExternalStorageDirectory().canWrite(); // RETURNS FALSE!!

Итак, кажется, что среда выполнения Android думает, что у меня есть разрешения, но файловая система не... Действительно, попытка доступа к Environment.getExternalStorageDirectory() создает исключение:

android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87) 
at java.io.FileOutputStream.<init>(FileOutputStream.java:72) 

Если теперь уничтожить приложение и снова открыть его, поведение будет таким, каким оно есть, имея возможность читать и записывать во внешней папке хранилища.

Кто-нибудь испытывает это?

Я использую один официальный эмулятор с:

  • Последний Android 6.0 (API 23) API 23, Rev 1.
  • Эмулятор под управлением Intel X86 Atom System Image, API 23, Rev 1.

Я создаю приложение с помощью

android {
    compileSdkVersion 23
    buildToolsVersion "22.0.1"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
    }
...
}

Если кто-то подтвердит это, и я не единственный, я думаю, нам нужно будет открыть ошибку, но я надеюсь, что я делаю что-то неправильно, поскольку я думаю, что такая основная функция вряд ли будет ошибкой в ​​SDK.

4b9b3361

Ответ 1

http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE:

Начиная с уровня API 19, это разрешение не требуется для чтения/записи файлов в ваших каталогах приложений, возвращаемых getExternalFilesDir (String) и getExternalCacheDir().

"Запрос на разрешение времени выполнения" начинается с уровня API 23, очевидно, выше 19, поэтому разрешение больше не требуется, если только вы не получаете доступ к данным за пределами папки, на которую указывает getExternalFilesDir(). Поэтому я считаю, что это ошибка эмулятора.

На нижних объектах ниже уровня 19, которые не поддерживают запрашивающее разрешение во время выполнения, просто калибруйте разрешение в манифесте и оно будет работать.

Ответ 2

У меня была та же проблема. Оказывается, это, кажется, большая проблема. Изменение разрешения на запись во внешнее хранилище изменяет GID для этого процесса (на стороне Linux). Чтобы изменить идентификатор, процесс необходимо перезапустить. В следующий раз, когда вы откроете приложение, будет установлен новый идентификатор groupID и будет предоставлено разрешение.

Короче говоря, я боюсь , это не ошибка в эмуляторе, а на самом деле большая проблема с Linux и Android.

Я "решил" это, запросив разрешение при первом запуске приложения и перезапустив его, когда это разрешение указано так:

PackageManager packageManager = getPackageManager();
                    Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
                    ComponentName componentName = intent.getComponent();
                    Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
                    startActivity(mainIntent);
                    System.exit(0);

Вы можете попытаться создать службу, запущенную в фоновом режиме (с другим идентификатором процесса) и предоставив ей разрешение. Таким образом вам нужно будет только перезапустить службу, а не полное приложение. С нижней стороны это может сделать больше работы для вас.

Надеюсь, что это поможет.

--- EDIT ---

Пользователь M66B (fooobar.com/info/251815/...) нашел список связанных gid. Дополнительную информацию можно найти здесь: https://android.googlesource.com/platform/frameworks/base/+/master/data/etc/platform.xml