写入德尔福 10.3 Rio 中的外部 SD 卡



我编写了一个照片应用程序,可以将图像从外部源流式传输到平板电脑上的应用程序(三星Galaxy TAB S(。 我决定使用平板电脑中的外部SD卡作为存储,因为内部存储经常空间不足。另外,我需要删除它才能备份所有图像。

"读取"JPG 一切正常,但是当涉及到将 JPG 从流"写入"到 SD 卡时,权限被拒绝。

我已经设置了WRITE_EXTERNAL_STORAGE权限,但这在Android SDK 25.2.5中不起作用,因为Android改变了外部访问权限的工作方式。

fWriteStorage:=JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
PermissionsService.RequestPermissions([fReadStorage, fWriteStorage], DisplayRationale);

我想做的是调用Android系统文件夹选择器对话框,以允许应用程序写入SD卡。 如下所述:Android 5.0 及更高版本上的 SD 卡。

有谁知道如何在德尔福 10.3 Rio 中调用 SD 卡的权限选择器? 与包括Android版TotalCommander在内的所有应用程序类似,需要对外部SD卡进行写入访问。

我现在再次尝试,使用以下代码,但仍然没有运气。 我需要为图像库创建新文件夹,但无法创建该文件夹。

fWriteStorage := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
if PermissionsService.IsPermissionGranted(fWriteStorage) then
begin
applog('IsPermissionGranted: TRUE');
if ForceDirectories(System.IOUtils.TPath.Combine(GLOBAL_SDCARD, 'FoxyTab/Storage')) then
AppLog('GLOBAL_SDCARD Created')
else
AppLog('Can not create SD CARD folder ' + System.IOUtils.TPath.Combine(GLOBAL_SDCARD, 'FoxyTab/Storage'));
PermissionsService.RequestPermissions([fWriteStorage],
procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
begin
if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
begin
AppLog('Access Granted');
if ForceDirectories(System.IOUtils.TPath.Combine(GLOBAL_SDCARD, 'FoxyTab/Storage')) then
AppLog('GLOBAL_SDCARD Created')
else
AppLog('Can not create SD CARD folder ' + System.IOUtils.TPath.Combine(GLOBAL_SDCARD, 'FoxyTab/Storage'));
end
else
begin
AppLog('Access Denied');
end;
end);

我总是得到"访问权限授予",但无法创建文件夹。

SD卡不是平板电脑的内部,而是"可移动"的microSD卡,因为我需要在图库已满时将其删除以备份到另一台设备(PC/MAC(。卡的路径是/storage/2266-7298/。 与使用标准目录返回的内容不同。

> 无需调用系统对话框即可获取访问权限。

使用PermissionsService.RequestPermissions()时,您需要实际等待 Android 回复为授予或拒绝状态,然后才能尝试执行您请求权限的操作。

在您显示的代码中,您没有将回调函数传递给RequestPermissions()以获取该回复。因此,在您向SD卡写入文件之前,您不知道用户是否实际授予了对SD卡的访问权限。

你需要更多这样的东西:

fWriteStorage := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
...
if PermissionsService.IsPermissionGranted(fWriteStorage) then
begin
// access previously granted, write files...
end
else
begin
PermissionsService.RequestPermissions([fWriteStorage],
procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
begin
if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
begin
// access granted, write files...
end
else
begin
// access denied, can't write files...
end;
end,
DisplayRationale);
end;
end;

请注意,如果使用 Android 的Context.getExternalFilesDir()函数(由 Delphi 的System.IOUtils.TPath.GetSharedDocumentsPath()方法包装(,则在写入属于应用包的文件夹时WRITE_EXTERNAL_STORAGE实际上不需要写入 SD 卡的权限:

Build.VERSION_CODES.KITKAT开始,读取或写入返回的路径不需要任何权限;调用应用始终可以访问该路径。这仅适用于为调用应用程序的包名称生成的路径。要访问属于其他包的路径,需要Manifest.permission.WRITE_EXTERNAL_STORAGE和/或Manifest.permission.READ_EXTERNAL_STORAGE

像这样的应用程序 总指挥官 访问其他应用程序的文件,这就是为什么它需要(READ|WRITE)_EXTERNAL_STORAGE. 如果你的应用只是读取/写入自己的文件供自己使用,则可能不会。

最新更新