问题描述
我曾经在西雅图的德尔福创建了一个项目,现在我想搬到德尔福里约.我使用 findfirst/findnext 读取了外部 SD 卡上的目录结构
I have a project that I once created in Delphi Seattle and I would now like to move to Delphi Rio.I read the directory structure on an external SD-Card using findfirst/findnext
i := findfirst(datadir + '*', faanyfile, ts);
datadir 变量包含一个有效目录.在西雅图,代码运行良好(返回值 i=0)并且第一个目录条目在变量 ts 中返回.现在,在 Rio 上编译相同的代码,我得到一个返回错误值 i=13(访问被拒绝).
datadir variable contains a valid directory. On Seattle, the code works fine (return value i=0) and the first directory entry is returned in variable ts.Now, compiling the same code on Rio, I get a return error value i=13 (access denied).
在我的项目中设置了 READ_EXTERNAL_STORAGE 权限.
The permission READ_EXTERNAL_STORAGE is set in my project.
如果我将清单文件中的 targetSdkVersion(在 Rio 中自动设置为 26)硬编码为 19(即 minSdkVersion),则即使在 Rio 中,代码也会再次起作用.那么很明显,一些处理 sd 卡访问的方法已经从 sdk 级别 19 更改为 26?
If I hardcode the targetSdkVersion in the manifest file (which is automatically set to 26 in Rio) down to 19 (which is the minSdkVersion) the code works again, even in Rio.So obviously some way to handle sd-card access has changed from sdk-level 19 to 26?
有什么提示吗?
推荐答案
Android OS 引入 运行时权限 从 API 23 开始的模型.
Android OS introduced Runtime Permissions model since API 23.
这意味着除了在 Manifest 中指定权限之外,您还需要在运行时请求用户授予您所谓的危险权限的权限.用户可以在被询问时选择授予您权限,但也可以随时撤销该权限.
That means in addition to specifying permission in Manifest, you also need to ask user for granting you permission for so called dangerous permissions at runtime. User has a choice to give you permission when asked, but it can also revoke that permission at any time.
每当您的应用程序处理需要运行时权限的代码时,它必须验证用户是否授予了您该权限,并准备好处理用户未授予您权限的情况.
Whenever your application deals with code that needs runtime permission it must verify that user granted you that permission and be prepared to deal with situation where user didn't gave you the permission.
READ_EXTERNAL_STORAGE
就是其中之一.
可以在权限概述
要将您的应用程序上传到 Google Play 商店,您的应用程序需要支持最低 API 26(目前),并且 Delphi Rio 默认针对新的 API 级别.它还引入了对在运行时询问权限的支持.
以下是请求 READ_EXTERNAL_STORAGE
权限并从共享下载文件夹读取文件的基本示例.
uses
System.Permissions,
Androidapi.Helpers,
Androidapi.JNI.App,
Androidapi.JNI.OS,
...
procedure TMainForm.AddFiles;
var
LFiles: TArray<string>;
LFile: string;
begin
LFiles := TDirectory.GetFiles(TPath.GetSharedDownloadsPath);
for LFile in LFiles do
begin
Memo1.Lines.Add(LFile);
end;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE)],
procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
begin
if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
begin
Memo1.Lines.Add('GRANTED');
AddFiles;
end
else
begin
Memo1.Lines.Add('NOT GRANTED');
end;
end)
end;
这篇关于Delphi Rio 无法读取设置了 READ_EXTERNAL_STORAGE 权限的外部存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!