Alex Rivera | Logout

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

Asked 2011-01-28T01:42:08.777
17

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(
Edit
Report

1 Answer

7

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.

answered 2011-10-13T10:48:07.730

Your Answer