2

I am unable to write file to external SD Card . I get error message EAcess denied. I have searched a lot on internet and found that from Android 4.4 + android's Storage Access Framwork (SAF) is required to write file.

But I am using some android applications which are able to write(Create/Delete/Rename) file on SD Cards. They are not using SAF.

So please help me as to how can I do this without using SAF framwork.

Thanks

Ankesh kumar Jaisansaria
  • 1,563
  • 4
  • 26
  • 44

4 Answers4

5

There are a lot of confusions talking about External Memory of Android. It doesn't point to Removable SD MICRO CARD actually. So, what Google thinks "external memory" means

Refer to Android API Document

Every Android-compatible device supports a shared "external storage" that you can use to save files. This can be a removable storage media (such as an SD card) or an internal (non-removable) storage. Files saved to the external storage are world-readable and can be modified by the user when they enable USB mass storage to transfer files on a computer.

The fact is Environment.getExternalStorageDirectory() and Context.getExternalFilesDirs() could return an emulated External Memory located inside the Internal storage. Thus, these functions themselves don't give an expected results. The SECONDARY_STORAGE environment variable can help to get a real path of removable memory but writing on root of this isn't allowed because of OEM implementation. In this case, we should try to get app's data folder by Context.getExternalFilesDirs() or ContextCompat.getExternalFilesDirs() on which app's data file is allowed to be read and written.

I solve my problem by using below method, please check it and hope it helps you overcome your issues.

@TargetApi(Build.VERSION_CODES.KITKAT)
private String getRemovablePath(){
    String secondaryStore = System.getenv("SECONDARY_STORAGE");     
    if (secondaryStore != null){
        secondaryStore = secondaryStore.split(":")[0];
        secondaryStore += File.separator + "Backups/";
        File file = new File(secondaryStore);
        if((file.mkdir() || file.isDirectory()) && isFileWritable(secondaryStore)){
            return secondaryStore;
        } else {
            secondaryStore = null;
        }           
    } 

    // try again by fix address
    if(secondaryStore == null){
        if (new File("/Removable/MicroSD/").exists()){              
            secondaryStore = "/Removable/MicroSD/";
        } else if( new File("/storage/extSdCard/").exists()){
            secondaryStore = "/storage/extSdCard/";
        } else if( new File("/storage/sdcard1/").exists()){
            secondaryStore = "/storage/sdcard1/";
        } else if( new File("/storage/usbcard1/").exists()){
            secondaryStore = "/storage/usbcard1/";
        } else if( new File("/storage/external_SD/").exists()){
            secondaryStore = "/storage/external_SD/";
        }   
        /** add more fix addresses you know */
        secondaryStore += "Backups/";
        File file = new File(secondaryStore);
        if((file.mkdir() || file.isDirectory()) && isFileWritable(secondaryStore)){                             
            return secondaryStore;
        } else {
            secondaryStore = null;
        }           

    }       
    /** Try data folder*/
    if(secondaryStore == null){         
        int ver = Build.VERSION.SDK_INT;
        File[] externalRoots = null;
        if(ver <= Build.VERSION_CODES.JELLY_BEAN_MR2){          
            externalRoots = ContextCompat.getExternalFilesDirs(getBaseContext(), null);
        } else {
            externalRoots = getExternalFilesDirs(null);
        }   

        if(externalRoots.length > 1){
            secondaryStore = externalRoots[1].getAbsolutePath() + File.separator;
            return secondaryStore;
        } else {
            secondaryStore = null;
        }               
    }


    return secondaryStore;          
}
Noi Doan
  • 327
  • 5
  • 10
0

Android API < 23

Your Android Manifest must declare the specific user permission:

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

You also have to declare the reading permission if you also intend to read files:

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

User permissions must be placed before the application section, like this:

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

      ...

    <application>

Source of my explanation and examples on how to save files can be found in the official documentation.

Android 6 (API 23)

Things get a bit different starting with Android API 23 because user permissions have to be asked to the user in runtime when needed. A valid answer to this was already given here.

Community
  • 1
  • 1
Matei Radu
  • 2,038
  • 3
  • 28
  • 45
  • 1
    Have seen this thing , this works only for Emulated Sd Card (Internal Storage) – Ankesh kumar Jaisansaria May 03 '16 at 17:07
  • @AnkeshkumarJaisansaria I made further research and it seems that starting with Android 4.4 the only option for third-party apps (not OEM to be more precise) to write on physical SD cards is through the SAF framework. Officially apps should access only their reserved app folder on SD cards. – Matei Radu May 03 '16 at 17:21
  • this works if your targetApiLevel=22. Permission is auto granted even on Android M devices – Felix.D Nov 22 '16 at 03:38
0

please check the link, where present issue:

issue

for access to external memory in previous android versions there is no problem. current possess improvements

Community
  • 1
  • 1
AGil
  • 53
  • 6
0

SAF is only needed if you have to write to any location on the SD Card. To write to your app-specific directory on the SD Card, you can use context.getExternalFilesDirs. One of the paths returned will be the path of the your app specific folder on the SD Card.

Again, this is manufacturer dependent as well. If the manufacturer has not set the SECONDARY_STORAGE environment variable, the paths returned by getExternalFilesDirs will not contain the SD Card path.

somesh
  • 2,509
  • 3
  • 16
  • 24