Java.io.filenotfoundexception: (в доступе отказано) в oreo android

Следующий код предназначен для записи контактных данных в файл, созданный на SD-карте (внешнее хранилище):

try {
                while (phones.isAfterLast() == false) {

                    String lookupKey = phones.getString(phones
                            .getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
                    Uri uri = Uri.withAppendedPath(
                            ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);

                    AssetFileDescriptor fd;


                    fd = mContext.getContentResolver().openAssetFileDescriptor(uri, "r");
                    FileInputStream fis = fd.createInputStream();
                    byte[] buf = readBytes(fis);
                    fis.read(buf);
                    String VCard = new String(buf);
                    FileOutputStream mFileOutputStream = new FileOutputStream(
                            cpath, true);
                    mFileOutputStream.write(VCard.getBytes());
                    phones.moveToNext();
                }
            } catch (Exception e1) {
                Applog.e(TAG, e1);
                isOk = false;
            }

Где, cpath - это путь к моему файлу на SD-карте.

Здесь я получаю сообщение об ошибке:

FileOutputStream mFileOutputStream = new FileOutputStream(
                            cpath, true);

Я получаю журнал ниже: -

java.io.FileNotFoundException: /storage/9016-4EF8/AllBackupDemo/cont20181031050512.vcf (Permission denied)
        at java.io.FileOutputStream.open0(Native Method)
        at java.io.FileOutputStream.open(FileOutputStream.java:287)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:142)

Код выбора дерева документов:

private void triggerStorageAccessFramework() {
        startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), REQUEST_SAF_PERMISSION);
    }

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
//        Log.e(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data + ")");
        if (resultCode == RESULT_CANCELED) return;

        switch (requestCode) {
            case REQUEST_SAF_PERMISSION:{
                Uri treeUri = data.getData();
                if(treeUri != null){
                    session.setPrefURI(treeUri.toString());
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
                toast(getString(R.string.permission_granted_saf));
                break;
            }
        }
    }

ЗАМЕТКА:

  1. Я получаю эту ошибку только в версии Android oreo. он отлично работает в нуге.
  2. Я уже дал разрешение на выполнение, а также упомянул в файле манифеста.
  3. Я уже реализовал SAF для разрешения файла документа.

Где вы выбрали SD-карту при выборе SAF?

Ümañg ßürmån 31.10.2018 12:41

Я проверяю перед созданием файла и, если требуется, выберите использование документа бесплатно.

Sagar Maiyad 31.10.2018 13:02

Да, вы должны выбрать в дереве документа ... и поддерживать объект на протяжении всего цикла приложения.

Ümañg ßürmån 31.10.2018 13:07

@ Ümañgßürmån я обновил свой код. проверьте там, я уже выбрал с помощью дерева документов.

Sagar Maiyad 31.10.2018 13:19

не следует ли вам использовать FileProvider для Android N и выше. developer.android.com/reference/android/support/v4/content/…‌. Проверьте, не возвращает ли Uri treeUri = data.getData(); значение null.

karan 31.10.2018 13:32

Нет, это не ноль.

Sagar Maiyad 31.10.2018 13:43

@Riser Я скоро выложу решение из своего проекта.

Ümañg ßürmån 31.10.2018 13:44

@ Ümañgßürmån Спасибо.

Sagar Maiyad 31.10.2018 14:00

@Riser Взгляните на мое решение, пожалуйста.

Ümañg ßürmån 31.10.2018 21:21
0
9
2 057
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение:

Я проанализировал и сравнил свой код с вашим и обнаружил, что весь код, который вы использовали, такой же.

Строку, в которой вы получаете сообщение об ошибке, необходимо изменить. Эта ошибка возникает из-за использования FileOutputStream, что указывает на то, что вы осуществляете доступ из файловой системы, а не из DocumentTree.

Следовательно, вместо:

FileOutputStream mFileOutputStream = new FileOutputStream(
                        cpath, true);

Попробуйте что-то вроде этого:

try {
    OutputStream out = getContentResolver().openOutputStream(cpath.getUri());
    try {

        // Do whatever you wish to do.

    } finally {
        out.close();
    }

} catch (IOException e) {
    throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
}

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

Надеюсь, это поможет.

Другие вопросы по теме