Daniele Vitali
Daniele Vitali

Reputation: 3858

Permission denied when creating new file on external storage

I need to copy a file from the assets to the external storage. Here is my code:

    File f = new File(Environment.getExternalStorageDirectory() + File.separator
            + "MyApp" + File.separator + "tessdata" + File.separator + "eng.traineddata");
    if (!f.exists()) {
    AssetManager assetManager = getAssets();
    try {
        f.createNewFile();
        InputStream in = assetManager.open("eng.traineddata");
        OutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory() + File.separator
            + "MyApp" + File.separator  + "tessdata" + File.separator + "eng.traineddata");
        byte[] buffer = new byte[1024];
        int read;
            while ((read = in.read(buffer)) != -1)
                    out.write(buffer, 0, read);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (IOException e) {
            Log.e("tag", "Failed to copy asset file: ", e);
        }
    }

I've also added the permission in the manifet

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

The exception occurred when is executed f.createNewFile(), saying "Permission denied".

How can I fix it please?

Upvotes: 21

Views: 52855

Answers (6)

Bill Yan
Bill Yan

Reputation: 3468

I have googled so hard for an answer. Most solutions don't work for API 29. @ishann 's answer inspired me to search for android:requestLegacyExternalStorage . It turned out that they introduced the concept of scoped storage, which means an app can only access its dedicated folder by default. For example, the folder pattern for Pictures should now be like:

/storage/emulated/0/Android/data/com.myapp.myapp/files/Pictures

Creating files or folders in the global location will fail, even both permissions are granted:

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

the following code worked for me:

File files[] = this.getApplicationContext().getExternalFilesDirs(Environment.DIRECTORY_PICTURES);

for(File f : files){
    Log.e("debug", f.getAbsolutePath());
    File newdir = new File(f.getAbsolutePath(), "/newtest/");
    boolean result = newdir.mkdirs();
    Log.e("debug", result + " ; " + newdir.exists());
    break;
}

relevant documents

https://developer.android.com/training/data-storage#scoped-storage

https://developer.android.com/reference/android/content/Context#getExternalFilesDirs(java.lang.String)

Upvotes: 1

Ishaan
Ishaan

Reputation: 3918

Recently in API level 29, they have changed the way of accessing external storage. If you are trying to access public folders(i.e. Downloads) it will throw permission denied error.

You need to specify below code in your application tag in Manifest file.

android:requestLegacyExternalStorage="true"

Or you can save files in the root directory to avoid this error.

Upvotes: 35

Dheeraj Jaiswal
Dheeraj Jaiswal

Reputation: 364

If you are using SDK-23 you need to write permission in manifest file like this

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

Upvotes: 1

M. Usman Khan
M. Usman Khan

Reputation: 4408

In my case it was due to the Permissions popup required for API 23+, even if u have added permission in the manifest.

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

Call this function when the app launches or when you need the permission.

AndroidManifest.xml

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

Detailed sample code for permissions can be found here.

Upvotes: 41

rcbevans
rcbevans

Reputation: 8872

Do f.mkdirs() before f.createNewFile(). You are probably trying to create a new file in a non-existent directory

Upvotes: 10

andrehsouza
andrehsouza

Reputation: 519

try this:

private void copy() {

File dirOri = new File(Environment.getExternalStorageDirectory() +"/somefolder/somefile");
File dirDest = new File(Environment.getExternalStorageDirectory() + "/yourfolder");

FileChannel src = null;
FileChannel dst = null;

try {
    src = new FileInputStream(dirOri).getChannel();
    dst = new FileOutputStream(dirDest).getChannel();
    dst.transferFrom(src, 0, src.size());               
    src.close();
    dst.close();
} catch (Exception e) {}
}

-- EDIT --

Add in manifest:

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

Upvotes: 2

Related Questions