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 ex开发者_如何转开发ception 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;
}
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" />
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)
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.
If you have the correct permissions set in the manifest, make sure your device is not in "Disk Drive" mode when connect to a PC. Change it to "Charge only" mode and it should work.
Notice that in addition to Saurabh answer, since API 23 you need to request permissions at run-time.
See here: https://developer.android.com/training/permissions/requesting.html
And Justin Fiedler's answer here: https://stackoverflow.com/a/33288986/328059
Also, I've had several cases when after changing permission and re-running the app using Instant Run the permissions were not updated. So, as a best practice, after changing the manifest I uninstall the app from the target device, and rebuild.
You can try with:
String myPath=Environment.getExternalStorageDirectory()+"/Image"+ imageGroup + "_" + imageNumber + ".png";
File myFile = new File();
input = new FileInputStream(myFile);
Try to use openFileOutput("filename")
to return a FileOutputStream instead of specifying the location by yourself.
Check the doc here
精彩评论