Разрешения во время выполнения: нет разрешения сразу после предоставления

Я пытаюсь получить разрешение на хранение в Marshmallow. Кажется, все работает отлично, и я могу дать или отказать в разрешении.

private static final int REQUEST_STORAGE = 1;

// request storage permission
private void requestStoragePermission() {
    String[] permissions = new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE };
    if (!hasStoragePermission()) {
        Log.e(TAG, "No storage permission at the moment. Requesting...");
        ActivityCompat.requestPermissions(this, permissions, REQUEST_STORAGE);
    } else
        Log.e(TAG, "We already have storage permission. Yay!");
}

// check is storage permission granted
private boolean hasStoragePermission() {
    String storagePermission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
    int hasPermission = ContextCompat.checkSelfPermission(this, storagePermission);
    return (hasPermission == PackageManager.PERMISSION_GRANTED);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_STORAGE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "Storage permission granted");
            } else {
                Log.e(TAG, "Storage permission denied");
                Toast.makeText(getApplicationContext(), getString(R.string.no_storage_permission), Toast.LENGTH_SHORT).show();
            }
            break;
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

Однако проблема здесь. Когда я использую эту функцию в первый раз, hasStoragePermission() всегда имеет значение false, даже после предоставления разрешения. Когда разрешение не было предоставлено раньше, мне приходится дважды использовать контекстное меню, чтобы иметь возможность делать то, что я хочу. Это неприемлемо.

// some code...
// even more code...

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case ID_CONTEXT_MENU_SAVE_IMAGE:
            // in order to save anything we need storage permission
            requestStoragePermission();
            Log.e("SomeActivity", "storagePermissionGranted: " + hasStoragePermission());
            if (!hasStoragePermission())
                return false;
            saveImageToDisk(mPendingImageUrlToSave);
            break;
    }
    return super.onContextItemSelected(item);
}

Есть ли известная ошибка в Android Marshmallow, которая может ее вызвать? Код кажется в порядке, потому что на самом деле я могу предоставить/отказать в разрешении на хранение. Хотя я хочу получить его немедленно.


person koras    schedule 15.01.2016    source источник
comment
Единственное решение моей проблемы - просто поставить if (mPendingImageUrlToSave != null) { saveImageToDisk(mPendingImageUrlToSave); mPendingImageUrlToSave = null; } на onRequestPermissionsResult -> разрешение предоставлено. Это тривиально, и это, вероятно, предпочтительный способ. Но раздражает, что разрешения не выдаются сразу...   -  person koras    schedule 16.01.2016
comment
А также добавить то же самое к else из requestStoragePermission()   -  person koras    schedule 16.01.2016


Ответы (1)


Запрос разрешений и возвращаемый результат являются асинхронными. После того, как ваш onRequestPermissionsResult() будет выполнен, вашему приложению либо будет предоставлено, либо отказано в разрешении. В некоторых случаях это приведет к перезапуску всего вашего приложения (определенные разрешения). К вашему сведению, внешнее хранилище должно быть одним из них, но прямо сейчас у M есть проблема, из-за которой приложение не всегда перезапускается при предоставление этого разрешения.

person Larry Schiefer    schedule 16.01.2016
comment
Модель разрешений Шредингера :D Теперь мне все ясно. Не перезапущен, а воссоздан (действия), если быть точным. На данный момент он не воссоздан, и мне это нравится. Никаких проблем. - person koras; 16.01.2016
comment
На самом деле это и то, и другое: если ваша активность воссоздается, значит, процесс был перезапущен. Это связано с тем, что за кулисами существуют разрешения (например, внешнее хранилище), которые требуют добавления идентификатора пользователя вашего приложения в определенные группы и контексты политик SE. Когда они изменяются, например добавляются в группу, ни один запущенный процесс не получает это изменение — только новые процессы, принадлежащие этому идентификатору пользователя. Рады, что вы смогли преодолеть те проблемы, которые у вас были. - person Larry Schiefer; 16.01.2016