Запись внешнего хранилища не работает до тех пор, пока я не перезапущу приложение на Android M

У меня возникла проблема с новой системой разрешений. Я изменил свой код, чтобы запросить разрешение для WRITE_EXTERNAL_STORAGE. Но мое приложение не может писать (или читать) SD-карту, пока я не перезапущу приложение (конечно, я разрешил его в диалоговом окне). После этого он работает нормально.

Это не новое приложение, я уже объявил WRITE_EXTERNAL_STORAGE в манифесте, а на более ранних системах он отлично работает.

Я использую методы checkSelfPermission и requestPermissions, и когда я делаю запрос на чтение или запись на SD-карту, у меня есть исключение, в котором у меня нет разрешения.

Кто-нибудь знает, что я пропустил? Или я столкнулся с ошибкой?

Версия SDK является последней (обновлена ​​несколько часов назад), и я тестирую ее на эмуляторе.

Ответы

Ответ 1

Вам нужно Callback, если пользователь разрешает разрешение WRITE_EXTERNAL_STORAGE от RuntimePermission dialog.

Сначала вам нужно реализовать OnRequestPermissionsResultCallback Listener класса ActivityCompat в Activity и переопределить метод void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults), чтобы проверить, разрешает или запрещает ли пользователь разрешение

Вы можете сделать следующее:

int REQUEST_STORAGE = 1;

private void checkExternalStoragePermissions() {
    if (hasStoragePermissionGranted()) {
        //You can do what whatever you want to do as permission is granted
    } else {
        requestExternalStoragePermission();
    }
}

public boolean hasStoragePermissionGranted(){
        return  ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}

public void requestExternalStoragePermission() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        ActivityCompat.requestPermissions(MainActivity.this, {Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_STORAGE);
    }
}

Здесь onRequestPermissionsResult() будет вызываться метод, когда пользователь разрешает или запрещает разрешение на разрешение из окна Runtime.

Вы также можете справиться с ситуацией, когда пользователь установил флажок, никогда не отображая диалоговое окно Runtime Permission.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {

        if (requestCode == REQUEST_STORAGE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               //User allow from permission dialog
               //You can do what whatever you want to do as permission is granted
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivtity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
               //User has deny from permission dialog
               Snackbar.make(mainLayout, getResources().getString("Please enable storage permission"),Snackbar.LENGTH_INDEFINITE)
                      .setAction("OK", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                ActivityCompat.requestPermissions(MainActivity.this, {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE);
                            }
                       })
                       .show();
            } else {
                // User has deny permission and checked never show permission dialog so you can redirect to Application settings page
                Snackbar.make(mainLayout, getResources().getString("Please enable permission from settings"),Snackbar.LENGTH_INDEFINITE)
                     .setAction("OK", new View.OnClickListener() {
                           @Override
                           public void onClick(View view) {
                                Intent intent = new Intent();                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", MainActivity.this.getPackageName(), null);
                                intent.setData(uri);
                                startActivity(intent);
                            }
                       })
                       .show();
            }
        }
}

Здесь я использовал Snackbar, чтобы показать релевантное сообщение пользователю о Разрешении, а mainLayout - id от Activity Main Layout.

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