Как исправить чтение файла из папки загрузок в приложении NativeScript?

Я пишу приложение для Android на NativeScript.

Я определил необходимые разрешения в App_Resources/Android/AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

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

После загрузки изображения браузером в папку «Загрузки» я хочу прочитать его в своем приложении. Первоначально я получил путь к файлу от nativescript-mediafilepicker, но, насколько мне известно, я использую следующий фрагмент:

console.log(fs.File.exists('/storage/emulated/0/Download/7zoVG9uML7AyjwHl.png'));
const file = fs.File.fromPath('/storage/emulated/0/Download/7zoVG9uML7AyjwHl.png');
file.readSync(e => console.log('ERROR ' + e));

которые печатают в консоли:

JS: true
JS: ERROR Error: java.io.FileNotFoundException: /storage/emulated/0/Download/7zoVG9uML7AyjwHl.png: open failed: EACCES (Permission denied)

Что я делаю не так?

ОБНОВЛЕНИЕ Я добавил WRITE_EXTERNAL_STORAGE разрешение, но оно не действует:

permissions.requestPermissions(p).then(async () => {
  const publicDirectory = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
  const fullPath = `${publicDirectory}/7zoVG9uML7AyjwHl.png`;
  const file = fs.File.fromPath(fullPath);
  file.readSync(e => console.log('ERROR ' + e));
});
JS: ERROR Error: java.io.FileNotFoundException: /storage/emulated/0/Download/7zoVG9uML7AyjwHl.png: open failed: EACCES (Permission denied)

person Sergey Krivochenko    schedule 01.04.2020    source источник
comment
Вы должны программно построить путь с использованием API, android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();, теперь вы можете передать этот путь в файловую систему.   -  person Manoj    schedule 01.04.2020
comment
Я пытался это сделать, но безуспешно. Я обновил свой вопрос.   -  person Sergey Krivochenko    schedule 01.04.2020
comment
Судя по ошибке, похоже, что вы не получили разрешения на выполнение. Можете попробовать воспроизвести проблему на Playground и поделиться ссылкой?   -  person Manoj    schedule 01.04.2020


Ответы (3)


Итак, решение:

  1. Добавить в AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  1. Добавить в AndroidManifest.xml
<application android:requestLegacyExternalStorage="true" ...>

  1. Получить файл по строковому пути:
const file = fs.File.fromPath('/storage/emulated/0/Download/7zoVG9uML7AyjwHl.png');
file.readSync(e => console.log('ERROR ' + e));
person Sergey Krivochenko    schedule 01.04.2020
comment
возникли проблемы с чтением файлов, и флаг requestLegacyExternalStorage устранил проблемы. кажется необходимым в Android 10. - person kandan; 02.07.2020
comment
requestLegacyExternalStorage работал очень хорошо. Спасибо! - person Karan Raiyani; 25.01.2021

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

затем вы можете программно построить путь к вашему файлу, используя

new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()+"/7zoVG9uML7AyjwHl.png");
person quealegriamasalegre    schedule 01.04.2020
comment
Я пытался это сделать, но безуспешно. Я обновил свой вопрос. - person Sergey Krivochenko; 01.04.2020

  1. Добавьте в AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:requestLegacyExternalStorage="true" ...>
  1. Используйте плагин nativescript-permissions: https://www.npmjs.com/package/nativescript-permissions пример:
Permissions.requestPermissions(
            [
                android.Manifest.permission.READ_EXTERNAL_STORAGE,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            ]).then(() => {
               //your code
            };
  1. Для Android 10 API 29 нельзя использовать getExternalStorageDirectory(), потому что он устарел. подробнее здесь: https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory()

Вместо:

const file = fs.File.fromPath('/storage/emulated/0/Download/7zoVG9uML7AyjwHl.png');

Использовать:

import {Utils} from '@nativescript/core';

const file = Utils.ad.getApplicationContext().getExternalFilesDir(null).getAbsolutePath() +"/7zoVG9uML7AyjwHl.png"
person AdrianMartinez    schedule 13.06.2021