java.io.FileNotFoundException (В доступе отказано) При попытке записи на SD-карту Android - PullRequest
17 голосов
/ 28 января 2011

Я пытаюсь выбрать файл изображения из фотогалереи и записать на SDCard.Ниже приведен код, который приводит к исключению.Кажется, это исключение возникает при попытке создать 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;

}

Ответы [ 7 ]

24 голосов
/ 13 октября 2011

Вот так должен выглядеть ваш файл манифеста

<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" />

9 голосов
/ 05 марта 2013

У меня была эта проблема, и ответы здесь не устранили ее, потому что я сделал довольно глупую ошибку.

Убедитесь, что вы дали вашему эмулятору Android SD-карту ... Я оставил размер SD-карты пустым и, конечно, он ничего не мог найти. Кроме того, я указал каталог внутри указанной SD-карты, который еще не был создан, поэтому обязательно рассмотрите этот случай.

(Вы можете изменить настройки SD-карты AVD, перейдя в Android Virtual Device Manager, отредактировав свой эмулятор и введя некоторое значение для размера SD-карты)

7 голосов
/ 13 октября 2011

Вы также должны убедиться, что подсистема внешнего хранилища находится в правильном состоянии;используйте Environment.getExternalStorageState() и ищите Environment.MEDIA_MOUNTED, который является единственным безопасным состоянием.

Также неплохо сузить обработку исключений до IOException вокруг этих разделов, чтобы не перевыпускать после ввода-вывода-специфичные проблемы, например, отключение носителя.

Если вам нужны события, существуют широковещательные намерения (Intent.ACTION_MEDIA_xxx) с той же информацией, которую вы можете зарегистрировать с помощью IntentListener.

Также обратите внимание, чтовнешнее хранилище может быть отключено при использовании USB для отладки!

Существует также длительный период запуска устройства, когда внешнее хранилище недоступно.Если вы выполняете какие-либо действия в службах при запуске, это проблема.

В общем случае ваше приложение должно знать о состоянии внешнего хранилища при обращении к нему и обрабатывать случаи, когда оно недоступно или становится недоступным при доступеэто.

3 голосов
/ 21 сентября 2012

Если у вас установлены правильные разрешения в манифесте, убедитесь, что ваше устройство не находится в режиме «Дисковод» при подключении к ПК. Измените его на режим «Только зарядка», и он должен работать.

2 голосов
/ 23 января 2017

Обратите внимание, что в дополнение к ответу Saurabh, начиная с API 23, вы должны запрашивать разрешения во время выполнения.

См. Здесь: https://developer.android.com/training/permissions/requesting.html

И ответ Джастина Фидлера здесь: https://stackoverflow.com/a/33288986/328059

Кроме того, у меня было несколько случаев, когда после изменения разрешения и повторного запуска приложения с помощью Instant Run разрешения не обновлялись.Поэтому после изменения манифеста рекомендуется удалить приложение с целевого устройства и перестроить.

0 голосов
/ 20 октября 2016

Попробуйте использовать openFileOutput("filename") для возврата FileOutputStream вместо того, чтобы указывать местоположение самостоятельно.

Проверьте документ здесь

0 голосов
/ 28 января 2011

Вы можете попробовать:

String myPath=Environment.getExternalStorageDirectory()+"/Image"+ imageGroup + "_" + imageNumber + ".png";

File myFile = new File();      
input = new FileInputStream(myFile);
...