Delphi Rio无法通过设置了READ_EXTERNAL_STORAGE权限的外部存储器读取。

8

我有一个项目,之前是用Delphi Seattle创建的,现在想迁移到Delphi Rio。 我使用findfirst/findnext函数读取外部SD卡上的目录结构。

  i := findfirst(datadir + '*', faanyfile, ts);

datadir变量包含有效的目录。在Seattle上,代码运行良好(返回值i=0),并且第一个目录条目被返回到ts变量中。 现在,在Rio上编译相同的代码,我得到了返回错误值i=13(访问被拒绝)。

我的项目中设置了READ_EXTERNAL_STORAGE权限。

如果我在清单文件中硬编码targetSdkVersion(在Rio中自动设置为26)降至19(即minSdkVersion),则代码再次正常工作,即使在Rio中也是如此。 因此,从sdk级别19到26处理sd卡访问的方式显然发生了一些变化?

有任何提示吗?


如果您在西雅图创建了应用程序,并将其迁移到里约,您需要在AndroidManifest.template.xml的<%application-meta-data%>之前添加<%provider%>,并在项目选项的授权列表中检查安全文件共享选项。 - Dave Nottage
@DaveNottage Dalija在下面的回答中提供了处理API 23及更高版本(Rio所针对的版本)权限的方法。请注意,RequestPermissions接受一个权限字符串数组,以便一次性请求多个权限。 - Freddie Bell
1个回答

13

自API 23起,Android操作系统引入了运行时权限模型。

这意味着除了在清单文件中指定权限外,您还需要在运行时请求用户授予所谓的危险权限。用户有权选择在被询问时是否授权给您许可,但是用户也可以随时撤回该权限。

每当您的应用程序涉及需要运行时权限的代码时,它必须验证用户是否已经授予了该权限,并准备处理用户未授权给您该权限的情况。

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;

这个问题与权限无关,而是与访问外部URI有关。 - Dave Nottage
1
对我来说,Dalija 是正确的。她提供的解决方案对我有效。 - Andre Ruebel
2
@DaveNottage,您是否忘记了外部URI问题的实际情况?当尝试在应用程序外共享URI时,需要进行安全文件共享授权和提供程序设置。这个问题只涉及简单访问外部存储,只需要一个权限即可。 - blong
1
同意,我的错。 - Dave Nottage
我仍然无法取消我的踩。SO需要修复 :-) - Dave Nottage
1
@DaveNottage 不要为此感到难过 :) - Dalija Prasnikar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接