Вопрос, заданный пользователем, касается перемещения файла в Android-приложении, написанном на Delphi 12 FMX для Android. Суть проблемы заключается в необходимости копирования файла из одной директории в другую с использованием запроса на разрешения для чтения и записи на внешнее хранилище. Однако, несмотря на настройки в Uses Permissions и наличие соответствующих разрешений в AndroidManifest.xml, при попытке выполнения кода возникает ошибка, связанная с недостатком разрешений.
Контекст и решение проблемы
Пользователь уже нашел решение проблемы: изменение пути, из которого копируется файл, с TPath.GetSharedDocumentsPath на TPath.GetPublicPath. Это позволило выполнить операцию копирования без необходимости в запросе дополнительных разрешений. Однако, стоит отметить, что такое решение может быть не универсальным для всех случаев использования.
Альтернативное решение
Для обеспечения универсальности и соблюдения политики безопасности Android, особенно важной начиная с версии 6.0 (Marshmallow), рекомендуется использовать следующий подход:
Запрос разрешений: Убедитесь, что ваше приложение корректно запрашивает необходимые разрешения. В коде пользователя уже реализован запрос на READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE, что является правильным подходом.
Обработка результатов запроса: Проверьте, что код корректно обрабатывает результаты запроса разрешений. В случае отказа пользователя предоставить разрешения, приложение должно корректно реагировать на это.
Соблюдение ограничений Android 10 и выше: С Android 10 (Q) изменена политика доступа к файлам, в частности, для /storage/emulated/0/Documents/. Теперь для доступа к этим файлам необходимо использовать API Scoped Storage. Пример кода с использованием Scoped Storage на Object Pascal:
uses
Androidapi.JNIBridge;
procedure TfrmMain.CopyDB(direction2download: Boolean);
var
f1, f2: String;
documentPath: JString;
begin
{$IFDEF ANDROID}
PermissionsService.RequestPermissions([permRead, permWrite],
procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
begin
if Length(AGrantResults) = 2 and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then
begin
if TPlatform.OSVersion >= TOSVersion.Q then
begin
// Получаем путь к общему документу с использованием Scoped Storage
documentPath := TJDocumentsDir.GetExternalDocumentsDir(JString.Create('calorie_consumption.db'));
if direction2download then
TFile.Copy(documentPath, TPath.Combine(TPath.GetDocumentsPath, 'calorie_consumption.db'), True)
else
TFile.Copy(TPath.Combine(TPath.GetDocumentsPath, 'calorie_consumption.db'), documentPath, True);
end
else
// Для версий Android ниже 10 используем старый подход
begin
f1 := TPath.Combine(TPath.GetDocumentsPath, 'calorie_consumption.db');
f2 := TPath.Combine(TPath.GetSharedDocumentsPath, 'calorie_consumption.db');
if direction2download then
TFile.Copy(f2, f1, True)
else
TFile.Copy(f1, f2, True);
end;
end
else
TDialogService.ShowMessage('Permission not granted!');
end);
{$ENDIF}
end;
Тестирование: Проверьте приложение на разных версиях Android, чтобы убедиться, что все функции по перемещению файлов работают корректно.
Заключение
При работе с Android-приложениями на Delphi важно учитывать изменения в политике безопасности, особенно начиная с Android 10. Рекомендуется использовать Scoped Storage для работы с файлами, чтобы обеспечить совместимость и безопасность приложения.
Контекст описывает проблему копирования файлов в Android-приложении на Delphi 12 FMX, связанную с недостатком разрешений, и предлагает решения, включая использование Scoped Storage для обеспечения совместимости и безопасности при работе с файлами.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.