Java.io.FileNotFoundException(Permission denied) При попытке записать на SD-карту Android
Я пытаюсь выбрать файл изображения из фотогалереи и записать на SD-карту. Ниже приведен код, который приводит к исключению. Кажется, это исключение возникает при попытке создания FileOutputStream. У меня есть следующая строка, добавленная в файл манифеста, вложенный внутри элемента приложения. Я не могу найти решение проблемы:
<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;
}
Ответы
Ответ 1
Вот как ваш файл манифеста должен выглядеть как
<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" />
Ответ 2
У меня была эта проблема, и ответы здесь не исправить, потому что я сделал довольно глупую ошибку.
Удостоверьтесь, что вы дали вашему эмулятору Android SD-карту... Я оставил размер SD-карты пустым, и поэтому, конечно, он ничего не нашел. Кроме того, я указывал директорию внутри указанной SD-карты, которая еще не была создана, поэтому обязательно рассмотрите этот случай.
(Вы можете изменить настройки карты AVD SD, перейдя в Диспетчер виртуальных устройств Android, отредактировав свой эмулятор по выбору и введя какое-то значение для размера SD-карты)
Ответ 3
Вы также должны убедиться, что подсистема внешнего хранилища находится в правильном состоянии; используйте Environment.getExternalStorageState()
и ищите Environment.MEDIA_MOUNTED
, который является единственным безопасным состоянием.
Также неплохо было бы сузить обработку исключений до IOException
вокруг этих разделов, чтобы вы не перегрузились от проблем, связанных с IO, например. отключен.
Если вам нужны события, есть трансляции (Intent.ACTION_MEDIA_xxx
) с той же информацией, которую вы можете зарегистрировать с помощью IntentListener
.
Также обратите внимание, что при использовании USB для отладки внешнее хранилище может отключено!
Во время запуска устройства также существует расширенный период, когда внешнее хранилище недоступно. Если вы делаете вещи в сервисах при запуске, это проблема.
В общем, ваше приложение должно знать о состоянии внешнего хранилища при обращении к нему и обрабатывать случаи, когда оно недоступно, или становится недоступным при доступе к нему.
Ответ 4
Если у вас есть правильные разрешения, установленные в манифесте, убедитесь, что ваше устройство не находится в режиме "Диск" при подключении к ПК. Измените его на режим "Только зарядка", и он должен работать.
Ответ 5
Обратите внимание, что помимо ответа Saurabh, поскольку API 23 вам нужно запрашивать разрешения во время выполнения.
Смотрите здесь:
https://developer.android.com/training/permissions/requesting.html
И Джастин Фидлер ответит здесь: fooobar.com/questions/119859/...
Кроме того, у меня было несколько случаев, когда после изменения разрешения и повторного запуска приложения с помощью Instant Run разрешения не обновлялись. Итак, как наилучшая практика, после изменения манифеста я удалю приложение с целевого устройства и перестрою.
Ответ 6
Вы можете попробовать:
String myPath=Environment.getExternalStorageDirectory()+"/Image"+ imageGroup + "_" + imageNumber + ".png";
File myFile = new File();
input = new FileInputStream(myFile);
Ответ 7
Попробуйте использовать openFileOutput("filename")
, чтобы вернуть FileOutputStream вместо указания местоположения самостоятельно.
Проверьте документ
здесь