Ankesh kumar Jaisansaria
Ankesh kumar Jaisansaria

Reputation: 1591

Android write file on External SD Card for android 5+

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

Upvotes: 2

Views: 6524

Answers (4)

Noi Doan
Noi Doan

Reputation: 327

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

Upvotes: 5

somesh
somesh

Reputation: 2579

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.

Upvotes: 0

Matei Radu
Matei Radu

Reputation: 2078

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.

Upvotes: 0

AGil
AGil

Reputation: 63

please check the link, where present issue:

issue

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

Upvotes: 0

Related Questions