23

I am having an issue with the new permission system. I modified my code to ask permission for WRITE_EXTERNAL_STORAGE. But my app cannot write to (or read from) the sd card until I restart application (of course I allowed it in the dialog). After that it's working fine.

It's not a new app, I already declared WRITE_EXTERNAL_STORAGE in the manifest, and on earlier systems it's working fine.

I'm using checkSelfPermission and requestPermissions methods and when I make a read or write request to the sd card I've got an exception that I don't have permission.

Anyone has any idea what did I miss? Or did I run into a bug?

SDK version is the latest (updated a few hours ago), and I'm testing it on the emulator.

Szörényi Ádám
  • 1,223
  • 13
  • 17
  • Just to clarify: are you stating that you added code to request permissions to read/write external storage, when prompted you approved the permission but did NOT allow it to restart the app and that is when you noticed the problem? – Larry Schiefer Aug 18 '15 at 22:18
  • Yes, I've added the code to request the permission, dialog showed up, I allowed it, but I still got exception when reading/writing until I restart the application. After that it works fine, can read and write the storage. And that happens every time I revoke the permission in settings, reallow in app, and it doesn't work until restart. I don't know what can cause this issue, is it by design or do I run into an issue with the SDK? – Szörényi Ádám Aug 18 '15 at 22:19
  • 3
    For this type of permission, it should be restating your app automatically. Those permissions result in your app being placed into special (Linux kernel understood) groups and SE Linux contexts. In order for your app's process to actually have the correct GID and SE context, it would have to be restarted after the necessary config change. This is one of those instances where the app restart is required, but the framework should have been forcefully doing that for you. – Larry Schiefer Aug 18 '15 at 22:22
  • I understand now, thanks. I saw that in the documentation, that some permissions require application restart, but didn't know this is that case. In that case, can I trigger a restart by code somehow? – Szörényi Ádám Aug 18 '15 at 22:23
  • Not easily, no. I'll experiment with this a bit in the coming week and see if there is a problem in the framework related to this. You might also check the public bug database (http://b.android.com) to see if an issue has been logged against this for the preview. – Larry Schiefer Aug 18 '15 at 22:26
  • I've already opened an issue in the m developer tracker. Thanks. Until this will be resolved, I will switch back to lollipop target, that way everything will be good for now. – Szörényi Ádám Aug 18 '15 at 22:30
  • I can confirm. It's a bug. However when the permission is granted the app never restart. It restart only if a permission is revoked and *never* an activity only services. So if you open an activity with permission granted, you revoke it and turning back to the activity, the app is not restarted from main activity, so you need to check always in onRestart() callback. – greywolf82 Aug 19 '15 at 15:46
  • @SzörényiÁdám can you please link the issue? I cant find it :/ – andrew Aug 25 '15 at 23:42
  • 1
    @andrew https://code.google.com/p/android-developer-preview/issues/detail?id=2982 I created my issue a few hours earlier than this, but this was more detailed, so I guess that's why mine were marked as a duplicate. – Szörényi Ádám Aug 26 '15 at 21:00
  • @SzörényiÁdám thank you – andrew Aug 26 '15 at 21:01
  • @Szörényi Ádám, are you were able to restart the application programmatically? – Alexey Subbota Apr 04 '16 at 12:44
  • @Alexey Subbota, it's a hobbie project and I didn't have time to fix this since Google fixed the issue. – Szörényi Ádám Apr 05 '16 at 21:43

1 Answers1

3

You need Callback when User allow WRITE_EXTERNAL_STORAGE permission from RuntimePermission dialog.

First you need to implement OnRequestPermissionsResultCallback Listener of ActivityCompat class in your Activity and override void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) Method to check whether User is allowing or denying the permission

You can do like this:

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);
    }
}

Here is onRequestPermissionsResult() method will be called when user allow or deny Permission from Runtime permission dialog.

You can also handle situation when User has checked never show Runtime Permission dialog.

@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();
            }
        }
}

Here i have used Snackbar to show relevant message to user about Permission and mainLayout is id of Activity's Main Layout.

Hope it helps you.

Rajesh Jadav
  • 12,801
  • 5
  • 53
  • 78
  • The SDK has a bug which is fixed since that (obviusly since there were a tons of update since that). I accept this answer, since this is the way to do this. – Szörényi Ádám Sep 29 '19 at 00:29