Delphi Rio не может прочитать внешнее хранилище с установленными разрешениями READ_EXTERNAL_STORAGE
У меня есть проект, который я когда-то создал в Delphi Seattle, и теперь я хотел бы переехать в Delphi Rio. Я прочитал структуру каталогов на внешней SD-карте, используя findfirst / findnext
i := findfirst(datadir + '*', faanyfile, ts);
Переменная datadir содержит допустимый каталог. В Сиэтле код работает нормально (возвращаемое значение i=0), и первая запись каталога возвращается в переменной ts. Теперь, компилируя тот же код на Rio, я получаю значение ошибки возврата i=13 (доступ запрещен).
Разрешение READ_EXTERNAL_STORAGE установлено в моем проекте.
Если я жестко закодирую targetSdkVersion в файле манифеста (который автоматически устанавливается на 26 в Rio) до 19 (который является minSdkVersion), код снова работает, даже в Rio. Таким образом, очевидно, что какой-то способ обработки доступа к SD-карте изменился с уровня SDK 19 на 26?
Любые намеки на кого-то?
1 ответ
Android OS представила модель прав доступа Runtime начиная с API 23.
Это означает, что в дополнение к указанию разрешения в Manifest вам также необходимо запросить у пользователя разрешение на так называемые опасные разрешения во время выполнения. Пользователь может дать вам разрешение на запрос, но он также может отозвать это разрешение в любое время.
Всякий раз, когда ваше приложение имеет дело с кодом, для которого требуется разрешение во время выполнения, оно должно убедиться, что пользователь предоставил вам это разрешение, и быть готовым справиться с ситуацией, когда пользователь не предоставил вам разрешение.
READ_EXTERNAL_STORAGE
это один из них.
Обзор различных разрешений (включая их классификацию) можно найти в обзоре разрешений.
Чтобы загрузить свое приложение в Google Play Store, ваше приложение должно поддерживать минимальный 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;