如何更正 NativeScript 应用程序中“下载”文件夹中的读取文件?

Posted

技术标签:

【中文标题】如何更正 NativeScript 应用程序中“下载”文件夹中的读取文件?【英文标题】:How to correct read file from "Downloads" folder in NativeScript app? 【发布时间】:2020-07-12 15:56:44 【问题描述】:

我在 NativeScript 上编写了一个 android 应用程序。

我在App_Resources/Android/AndroidManifest.xml中定义了所需的权限:

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

我知道访问存储是不够的,所以我已经在运行时请求了权限,并在系统设置中检查了它。

通过浏览器将一些图像下载到“下载”文件夹后,我想在我的应用程序中阅读它。最初我通过nativescript-mediafilepicker 获得了一个文件路径,但要知道我使用以下sn-p:

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)

【问题讨论】:

您应该使用 API 以编程方式构建路径,android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();,现在您可以将此路径传递给文件系统。 我尝试过,但没有成功。我更新了我的问题。 根据错误,您似乎没有获得运行时权限。您可以尝试在 Playground 上重现该问题并分享链接吗? 【参考方案1】:

所以,解决办法是:

    在 AndroidManifest.xml 中添加
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    在 AndroidManifest.xml 中添加
<application android:requestLegacyExternalStorage="true" ...>

    通过字符串路径获取文件:
const file = fs.File.fromPath('/storage/emulated/0/Download/7zoVG9uML7AyjwHl.png');
file.readSync(e => console.log('ERROR ' + e));

【讨论】:

在读取文件时遇到问题,requestLegacyExternalStorage 标志修复了这些问题。在 Android 10 中似乎是必需的。 requestLegacyExternalStorage 运行良好。谢谢!【参考方案2】:

我认为要访问下载目录,您还需要向清单添加写入权限,即android.permission.WRITE_EXTERNAL_STORAGE

然后您可以使用编程方式构建文件的路径

new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()+"/7zoVG9uML7AyjwHl.png");

【讨论】:

我尝试过,但没有成功。我更新了我的问题。【参考方案3】:
    在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:requestLegacyExternalStorage="true" ...>
    使用 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
            ;
    对于 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"

【讨论】:

【参考方案4】:

早上好,

我的系统详情:

插件:@nativescript-community/ui-document-picker Ubuntu 20.04.3 LTS NativeScript CLI 8.1.4 NVM 0.35.3 节点 v16.13.0 NPM 8.1.0 Android 11 API 级别 30 "@nativescript/core": "~8.1.1", “@nativescript-community/ui-document-picker”:“^1.1.7”, "@nativescript/android": "8.1.1",

当打开文件选择器并从下载文件夹中选择一个 PDF 文件时,file.readSync 说错误:

Error: java.io.FileNotFoundException: /storage/emulated/0/Download/Test.pdf: open failed: EACCES (Permission denied)

当调用 file.read 时出现错误:

Error: ReadTask returns no result.

这只会在 targetSdkVersion 设置为 30 而不是 29 时发生,但现在要在 Google App Store 中发布和应用程序需要 targetSdkVersion 30。

谢谢

【讨论】:

以上是关于如何更正 NativeScript 应用程序中“下载”文件夹中的读取文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用本机代码的情况下要求用户在 NativeScript 上启用蓝牙

如何在 Nativescript-Vue 中使用 nativescript-drawingpad?

设备上的 Nativescript iOS 应用程序分析

NativeScript - 如何将图像保存/添加到手机的默认图库应用程序中

如何在 NativeScript 中更改应用程序名称

如何在 NativeScript 应用程序中导航多个页面?