Permission denied on writing to external storage despite permission

后端 未结 6 1364
攒了一身酷
攒了一身酷 2020-12-01 15:07

I have an Android 7.0 test device and my APK targets = \"targetSdkVersion 22\", with:



        
相关标签:
6条回答
  • 2020-12-01 15:19

    If you target SDK 29 and you still get a "permission denied" error after successfully requesting the WRITE_EXTERNAL_STORAGE permission you should add

    android:requestLegacyExternalStorage="true"

    to the application definition in AndroidManifest.xml.

    <manifest ... >
      <!-- This attribute is "false" by default on apps targeting
           Android 10 or higher. -->
        <application android:requestLegacyExternalStorage="true" ... >
          ...
        </application>
    </manifest>
    

    see https://developer.android.com/training/data-storage/compatibility

    0 讨论(0)
  • 2020-12-01 15:27

    If you're running your app on API level 23 or greater you have to request permission at runtime.

    Request permission:

    String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
    requestPermissions(permissions, WRITE_REQUEST_CODE);
    

    Then handle the result:

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
           case WRITE_REQUEST_CODE:
             if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
               //Granted.
    
    
             }
           else{
               //Denied.
             }
            break;
        }
    }
    

    For more information visit Requesting Permissions at Run Time - Android Doc

    0 讨论(0)
  • 2020-12-01 15:38

    UPDATE: See Volker Voecking's answer for a better solution


    EDIT: This is simply a workaround for those who don't have time to look for a solution. *

    If you get permission denied error even when the permissions are granted and you already implemented permission checks,

    make sure you're not targetting api level 29:

    Change targetSdkVersion and compilesdkversion from 29 to 28 or any other lower level.

    0 讨论(0)
  • 2020-12-01 15:38

    Related to the answer "make sure you're not targetting api level 29...", I found this.

    https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory

    。。。。。。。。。。

    "getExternalStoragePublicDirectory"

    This method was deprecated in API level 29.

    To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

    。。。。。。。。。。

    so, in that case you have to replace "getExternalStoragePublicDirectory" with those other methods.

    0 讨论(0)
  • 2020-12-01 15:40

    Here is what I did in a similar situation:

    Step 1: Add permission to manifest file

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

    Step 2: Create a permission checking function

    void checkForPermissions()
    {
        // Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
    
            // Permission is not granted
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                // Show an explanation 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.
                // This part I didn't implement,because for my case it isn't needed
                Log.i(TAG,"Unexpected flow");
            } else {
                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE);
    
                // MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        } else {
            // Permission is already granted, call the function that does what you need
    
            onFileWritePermissionGranted();
        }
    }
    

    Step 3: Implement onRequestPermissionsResult

     @Override
        public void onRequestPermissionsResult(int requestCode,
                                               String[] permissions, int[] grantResults) {
            switch (requestCode) {
                case MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
                    // If request is cancelled, the result arrays are empty.
                    if (grantResults.length > 0
                            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        // permission was granted, yay! 
                        // call the function that does what you need
                        onFileWritePermissionGranted();
                    } else {
                        Log.e(TAG, "Write permissions has to be granted tp ATMS, otherwise it cannot operate properly.\n Exiting the program...\n");
                    }
                    return;
                }
    
                // other 'case' lines to check for other
                // permissions this app might request.
            }
        }
    

    Step 4: Use the permission :)

    void onFileWritePermissionGranted()
    {
       // Write to some file
    }
    
    0 讨论(0)
  • 2020-12-01 15:41

    Android N introduces a new model of permissions which only asks for permissions when the app really needs it rather than during installation like it previously did.

    Use the following code to ask for permissions

    Note - Also add the required permissions in the Manifest file

    If you aren't asking permissions from Main Activity pass the reference to the context/activity

    The following example shows example for asking permissions to Write to external storage, multiple permisisons can be requiested at the same time (Not recommended by google).

    public class MainActivity extends AppCompatActivity {
    /**
     * Variables for requiesting permissions, API 25+
     */
    private int requestCode;
    private int grantResults[];
    
    
    /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {if(ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED ){
            //if you dont have required permissions ask for it (only required for API 23+)
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
    
    
            onRequestPermissionsResult(requestCode,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},grantResults);
        }
    
        @Override // android recommended class to handle permissions
        public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
            switch (requestCode) {
                case 1: {
    
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    Log.d("permission","granted");
                } else {
    
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.uujm
                    Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
    
                    //app cannot function without this permission for now so close it...
                    onDestroy();
                }
                return;
            }
    
            // other 'case' line to check fosr other
            // permissions this app might request
        }
    }
    
    0 讨论(0)
提交回复
热议问题