Подтвердить что ты не робот

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;

}
4b9b3361

Ответ 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 вместо указания местоположения самостоятельно.

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