java.io.filenotfoundexception open failed eacces (permission denied) on device
Asked Answered
A

11

25

The following code which consists of downloading a file from a server and save it in the storage works fine when the device has an internal storage.
But when I tried it with a device with no internal storage, only with external storage I get the following exception.

java.io.filenotfoundexception open failed eacces (permission denied)

public void downloadFile(String dlUrl, String dlName) {
    int count;

    HttpURLConnection con = null;
    InputStream is = null;
    FileOutputStream fos = null;

    try {
        URL url = new URL( dlUrl );
        con = (HttpURLConnection) url.openConnection();
        con.setDoInput(true);
        con.connect();

        is = url.openStream();
        String dir = Environment.getExternalStorageDirectory() + Util.DL_DIRECTORY;
        File file = new File( dir );
        if( !file.exists() ){
            file.mkdir();
        }

        Util.LOG_W(TAG, "Downloading: " + dlName + " ...");

        fos = new FileOutputStream(file + "/" +  dlName);
        byte data[] = new byte[1024];

        while( (count = is.read(data)) != -1 ){
            fos.write(data, 0, count);
        }

        Util.LOG_D(TAG, dlName + " Download Complete!");


    } catch (Exception e) {
        Util.LOG_E(TAG, "DOWNLOAD ERROR = " + e.toString() );
        bServiceDownloading = false;
    }
    finally{
        try {
            if( is != null)
                is.close();
            if( fos != null)
                fos.close();
            if( con != null)
                con.disconnect();
        } catch (Exception e) {
            Util.LOG_E(TAG, "CLOSE ERROR = " + e.toString() );
        }
    }
}

And in manifest file I has the following:

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

Any suggestions what maybe the cause? By the way Environment.getExternalStorageDirectory() returns /mnt/sdcard/ and file.mkdir() return false.

Ay answered 9/7, 2013 at 5:38 Comment(10)
try with File file = new File( dir + "/" + dlName );Horseradish
the outcome is the same unfortunately. Btw the file.mkdir() returns false, thats the problem I think. @PankajKumarAy
If you are debugging on Emulator make sure your created sd card support.. or if real device make sure that sd-card is present (device is not Attached with USB)Horseradish
Debugging in real device. SD-Card is present. How to check if device is not attached with USB? Does this include USB mouse?Ay
No no. If Device is attached with computer via wire.. this state makes sd-card to be not accessible. SO remove wire and then checkHorseradish
It was attached to my PC for debugging. Disconnecting from the PC does not seems to fix the problem. since file.mkdir() returns the false, I think somehow the app can not access the SD CardAy
Choice is yours... you can check after disconnect the device from computer.Horseradish
@PankajKumar, I did but it did not solve the problem.Ay
Did you eventually manage to solve it?Saccharase
@Saccharase I did not solve it in the ideal way. But I have posted an answer on how I have dealt with the problem. Hope it will help you.Ay
A
17

This problem seems to be caused by several factors.

Check#1
First add this permission in your manifest file and check if it is working:

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

</application>

  .....

Check#2:

If you are running on an emulator, check the properties to see if it has an SD card.

Check#3:

Disable file transfer from device to computer. If Enabled, the app wont be able to access the SD card.

Check#4:
If still not working, try the following:

 String dir = Environment.getExternalStorageDirectory().getAbsolutePath()

For me the following worked:
The problem is that getExternalStorageDirectory returns /mnt/sdcard whereas I need the actual path of external storage which is /mnt/sdcard-ext and there is no API in android that can get me the absolute path of removable sdcard.
My solution was to hard code the directory as follows:

String dir = "/mnt/sdcard-ext" ;

Since the application is intended to work only on one device, the above did the job.
If you encounter the same problem, use an file explorer application to find out the name of the external directory and hard code it.

Ay answered 7/11, 2013 at 1:28 Comment(3)
This is a device specific path (as you mentioned). For ex: I see here as String dir = "/mnt/sdcard".Saccharase
What solution would you suggest if you want to access a file in the external storage (or not) for ALL android phones?Muriah
What should I do for Check#2 from your answer?Margravine
T
37

This attribute is "false" by default on apps targeting Android 10 or higher.

<application android:requestLegacyExternalStorage="true" ... >
    ...
</application>
Tapetum answered 8/11, 2019 at 6:1 Comment(0)
A
17

This problem seems to be caused by several factors.

Check#1
First add this permission in your manifest file and check if it is working:

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

</application>

  .....

Check#2:

If you are running on an emulator, check the properties to see if it has an SD card.

Check#3:

Disable file transfer from device to computer. If Enabled, the app wont be able to access the SD card.

Check#4:
If still not working, try the following:

 String dir = Environment.getExternalStorageDirectory().getAbsolutePath()

For me the following worked:
The problem is that getExternalStorageDirectory returns /mnt/sdcard whereas I need the actual path of external storage which is /mnt/sdcard-ext and there is no API in android that can get me the absolute path of removable sdcard.
My solution was to hard code the directory as follows:

String dir = "/mnt/sdcard-ext" ;

Since the application is intended to work only on one device, the above did the job.
If you encounter the same problem, use an file explorer application to find out the name of the external directory and hard code it.

Ay answered 7/11, 2013 at 1:28 Comment(3)
This is a device specific path (as you mentioned). For ex: I see here as String dir = "/mnt/sdcard".Saccharase
What solution would you suggest if you want to access a file in the external storage (or not) for ALL android phones?Muriah
What should I do for Check#2 from your answer?Margravine
L
10

Use READ_EXTERNAL_STORAGE permission to read data from the device.

Lydon answered 9/7, 2013 at 5:40 Comment(2)
Thanks for your suggestion but unfortunately it doesnt solve the issue.Ay
"Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted this permission." developer.android.com/reference/android/…Garfield
T
6

Did you try it on emulator? Check the properties if it has an SD card. I had the same problem, and it was because the emulator did not have an SD card. Check if yours has or not.

Trocar answered 28/8, 2013 at 11:52 Comment(1)
Yes, I am trying it on Emulator. Where to check for the properties you're referring to?Margravine
K
4

I had the same problem, and i solved it by disabling file transfer from device to computer. Because if u enable file transfer, sd card is not accessible to debugging application.

Karissakarita answered 19/9, 2013 at 17:6 Comment(1)
OMG It solved my problem but 3 hrs gone in debuggingAnschluss
D
3
try
Environment.getExternalStorageDirectory().getAbsolutePath()

and don't forget to add

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Deach answered 23/5, 2014 at 2:43 Comment(0)
T
1

Try using mkdirs instead of mkdir. If you are creating a directory path and parent doesn't exist then you should use mkdirs.

Troop answered 10/1, 2016 at 8:49 Comment(0)
D
1

I suspect you are running Android 6.0 Marshmallow (API 23) or later. If this is the case, you must implement runtime permissions before you try to read/write external storage. https://developer.android.com/training/permissions/requesting.html

Developing answered 23/8, 2017 at 10:20 Comment(0)
S
1

i have done very silly mistake. I have already put in AndroidManifest.xml

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

and also add permission in java file,as get permission pragmatically. But there is mistake of Manifest.permission.READ_EXTERNAL_STORAGE. Please use Manifest.permission.WRITE_EXTERNAL_STORAGE.

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
Stace answered 3/10, 2018 at 12:19 Comment(1)
its integer value.Please refer this link #44310357Stace
K
0

I had the same problem. I used the write and read permission in the manifest correctly , yet it didn't work! The solution was very silly: unplug your phone from the PC before running the application. It seems when your phone is connected as "Mass storage" to the PC, the application cannot access the external storage.

Kinch answered 15/4, 2016 at 20:37 Comment(0)
A
0

First in your manifest file declare permissions :

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

now in header of application tag of manifest file :

android:requestLegacyExternalStorage="true"

now defines provider for your app in between tag of manifest file. as :

 <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_path" />
    </provider>

now create a folder xml in res folder like this : refer to this picture

now create a xml file provider_path.xml and copy below code in it :

<?xml version="1.0" encoding="utf-8"?>
<path>
<external-path
    name="external_files"
    path="." />

now in your activity :

String filename = null ;
URL url = null;
try {
                        url = new URL("http://websitename.com/sample.pdf");
                        filename = url.getPath();
                        filename = filename.substring(filename.lastIndexOf('/')+1);

                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
  File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/"+filename);
                    if(file.exists()){
                        Uri uri = FileProvider.getUriForFile(context, "com.example.www"+".provider",file);
                        Intent i = new Intent(Intent.ACTION_VIEW);
                        i.setDataAndType(uri, "application/pdf");
                        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        context.startActivity(i);
                    }
                    else {
                        //download file here
                        new AlertDialog.Builder(context)
                                .setTitle("Information")
                                .setMessage("Do you want to download this file ?")
                                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }
                                })
                                .setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url+""));
                                        request.setTitle(filename);
                                        request.setMimeType("application/pdf");
                                        request.allowScanningByMediaScanner();
                                        request.setAllowedOverMetered(true);
                                        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                                        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
                                        DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
                                        downloadManager.enqueue(request);
                                    }
                                }).show();

                    }
Alula answered 26/12, 2021 at 19:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.