Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.io.FileNotFoundException (Permission denied) When trying to write to the Android sdcard

I am trying to select an image file from the photo gallery and write to the sdcard. Below is the code that results in an exception. It appears to throw this exception when trying to create the FileOutputStream. I have the following line added to the manifest file nested inside the application element. I can't find a solution to the problem:

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

public boolean saveSelectedImage( Uri selectedImage, int imageGroup,
        int imageNumber )
{
    boolean exception = false;
    InputStream input = null;
    OutputStream output = null;
    if( externalStorageIsWritable() )
    {
        try
        {
            ContentResolver content = ctx.getContentResolver();
            input = content.openInputStream( selectedImage );
            if(input != null) Log.v( CLASS_NAME, "Input Stream Opened successfully");
            File outFile = null;

            File root = Environment.getExternalStorageDirectory(  );
            if(root == null) Log.v(CLASS_NAME, "FAILED TO RETRIEVE DIRECTORY");
            else Log.v(CLASS_NAME, "ROOT DIRECTORY is:"+root.toString());

            output = new FileOutputStream( root+"/Image"+ imageGroup + "_" + imageNumber + ".png" );

            if(output != null) Log.e( CLASS_NAME, "Output Stream Opened successfully");
            //  output = new FileOutputStream
            // ("/sdcard/Image"+imageGroup+"_"+imageNumber+".png");

            byte[] buffer = new byte[1000];
            int bytesRead = 0;
            while ( ( bytesRead = input.read( buffer, 0, buffer.length ) ) >= 0 )
            {
                output.write( buffer, 0, buffer.length );
            }
        } catch ( Exception e )
        {

            Log.e( CLASS_NAME, "Exception occurred while moving image: ");
            e.printStackTrace();

            exception = true;
        } finally
        {
            // if(input != null)input.close();
            // if(output != null)output.close();
            // if (exception ) return false;
        }

        return true;
    } else
        return false;

}
like image 239
joefischer1 Avatar asked Jan 28 '11 01:01

joefischer1


3 Answers

This is how your manifest file should look like

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".WriteCBTextToFileActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

like image 54
Saurabh Avatar answered Oct 05 '22 16:10

Saurabh


I had this issue and the answers here didn't fix it, because I had made a pretty silly mistake.

Make sure you give your Android emulator an SD card...I had left the size of the SD card blank and so of course it couldn't find anything. On top of that, I was specifying a directory inside said SD card which had not yet been created so be sure to consider that case as well.

(You can change an AVD's SD card settings by going to the Android Virtual Device Manager, editing your emulator of choice, and entering some value for the SD card size)

like image 9
deluxxxe Avatar answered Oct 05 '22 16:10

deluxxxe


You must also make sure that the External Storage subsystem is in the correct state; use Environment.getExternalStorageState() and look for Environment.MEDIA_MOUNTED that is the only safe state.

It's also a good idea to narrow exception handling to IOException around those sections, so you don't over-recover from IO-specific issues, e.g. media unmounted.

If you need events, there are broadcast intents (Intent.ACTION_MEDIA_xxx) with the same information you can register for with IntentListener.

Also note that external storage may be disabled when you are using USB for debugging!

There is also an extended period during device startup, where External Storage is not available. If you do stuff in services on startup, this is an issue.

In general, your application must be aware of the External Storage state when accessing it, and handle cases where it is unavailable, or becomes unavailable while accessing it.

like image 7
escape-llc Avatar answered Oct 05 '22 16:10

escape-llc