Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Проблемы с копированием файлов в Delphi на Android: решения и особенности работы с TDirectory.Copy

Delphi , Программа и Интерфейс , Приложение своё

 

Введение

В последнее время разработчики Delphi, работающие с мобильными приложениями для Android, сталкиваются с неожиданными проблемами при работе с файловыми операциями. В частности, как показал пример пользователя Peter C, возникают сложности с копированием файлов между директориями с использованием TDirectory.Copy. В этой статье мы разберем причины таких проблем и предложим несколько решений.

Описание проблемы

Пользователь столкнулся со следующей ситуацией:

  1. При первом запуске копирование из TPath.GetPublicPath + '/diary' в TPath.GetSharedDocumentsPath + '/backup' работает корректно (2-3 секунды)
  2. При повторном запуске операция завершается мгновенно, но файлы не копируются
  3. После ручного удаления файлов и повторного запуска копирование не работает
  4. После перезагрузки устройства копирование снова работает корректно
  5. Если приложение создает новый файл, копируется только он

Анализ проблемы

Особенности работы TDirectory.Copy в Delphi

Метод TDirectory.Copy в Delphi имеет две перегрузки:

class procedure Copy(const SourceDirName, DestDirName: string); overload;
class procedure Copy(const SourceDirName, DestDirName: string; IgnoreErrors: Boolean); overload;

По умолчанию используется первая перегрузка, которая эквивалентна вызову второй с параметром IgnoreErrors=True. Это означает, что при возникновении ошибок копирования исключения не будут генерироваться.

Проблемы с разрешениями в Android

Начиная с Android 10 (API 29), Google ввел ограниченный доступ к хранилищу (Scoped Storage), что существенно изменило правила работы с файлами:

  1. Приложения имеют доступ только к своим собственным файлам и определенным типам общих файлов
  2. Операции с файлами, созданными вне приложения, могут быть ограничены
  3. Удаление файлов вручную может привести к блокировкам

Решения проблемы

1. Использование IgnoreErrors=False

Как предложил Remy Lebeau, можно использовать перегрузку с IgnoreErrors=False для получения подробной информации об ошибках:

try
  TDirectory.Copy(MASTER_PATH, BACKUP_PATH, False);
except
  on E: EInOutError do
    ShowMessage('Ошибка копирования: ' + E.Message);
end;

2. Принудительное копирование с проверкой файлов

Альтернативное решение - реализовать собственный механизм копирования с проверкой каждого файла:

procedure ForceDirectoryCopy(const SourceDir, DestDir: string);
var
  Files: TStringDynArray;
  I: Integer;
  SourceFile, DestFile: string;
begin
  if not TDirectory.Exists(DestDir) then
    TDirectory.CreateDirectory(DestDir);

  Files := TDirectory.GetFiles(SourceDir);
  for I := 0 to High(Files) do
  begin
    SourceFile := Files[I];
    DestFile := TPath.Combine(DestDir, TPath.GetFileName(SourceFile));

    try
      // Проверяем, нужно ли копировать (по размеру или дате модификации)
      if not FileExists(DestFile) or 
         (TFile.GetLastWriteTime(SourceFile) > TFile.GetLastWriteTime(DestFile)) then
      begin
        TFile.Copy(SourceFile, DestFile, True);
      end;
    except
      on E: Exception do
        Log.d('Ошибка копирования файла ' + SourceFile + ': ' + E.Message);
    end;
  end;
end;

3. Работа с Android Storage Access Framework

Для корректной работы с файлами в Android рекомендуется использовать Storage Access Framework:

uses
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Net,
  Androidapi.JNI.JavaTypes,
  Androidapi.Helpers;

procedure RequestFileAccess;
var
  Intent: JIntent;
begin
  Intent := TJIntent.JavaClass.ACTION_OPEN_DOCUMENT_TREE;
  TAndroidHelper.Activity.startActivityForResult(Intent, REQUEST_CODE_OPEN_DIRECTORY);
end;

Рекомендации по работе с файлами в Delphi для Android

  1. Всегда обрабатывайте исключения при файловых операциях
  2. Не полагайтесь на работу с файлами вне sandbox вашего приложения
  3. Используйте правильные пути:
    TPath.GetDocumentsPath - приватное хранилище приложения
    TPath.GetSharedDocumentsPath - общие документы
    TPath.GetPublicPath - общедоступные директории
  4. Кэшируйте файловые операции для уменьшения количества обращений к хранилищу
  5. Учитывайте ограничения Scoped Storage в новых версиях Android

Пример полного решения

procedure TForm1.BackupFiles;
var
  Files: TStringDynArray;
  I: Integer;
  SourceFile, DestFile: string;
  Success, AnyError: Boolean;
begin
  if not TDirectory.Exists(MASTER_PATH) then
  begin
    ShowMessage('Исходная директория не существует');
    Exit;
  end;

  if not TDirectory.Exists(BACKUP_PATH) then
    TDirectory.CreateDirectory(BACKUP_PATH);

  Files := TDirectory.GetFiles(MASTER_PATH);
  AnyError := False;

  for I := 0 to High(Files) do
  begin
    SourceFile := Files[I];
    DestFile := TPath.Combine(BACKUP_PATH, TPath.GetFileName(SourceFile));

    try
      if not FileExists(DestFile) or 
         (TFile.GetLastWriteTime(SourceFile) > TFile.GetLastWriteTime(DestFile)) then
      begin
        TFile.Copy(SourceFile, DestFile, True);
      end;
      Success := True;
    except
      on E: Exception do
      begin
        Log.d('Ошибка копирования: ' + E.Message);
        AnyError := True;
        Success := False;
      end;
    end;

    TThread.Synchronize(nil,
      procedure
      begin
        UpdateProgress(I, High(Files), TPath.GetFileName(SourceFile), Success);
      end);
  end;

  TThread.Synchronize(nil,
    procedure
    begin
      if AnyError then
        ShowMessage('Резервное копирование завершено с ошибками')
      else
        ShowMessage('Резервное копирование успешно завершено');
    end);
end;

Заключение

Проблемы с копированием файлов в Delphi на Android связаны в первую очередь с изменениями в политике безопасности Google. Лучшим решением является:

  1. Использование специальных методов для работы с файлами
  2. Правильная обработка исключений
  3. Ограничение операций только теми файлами, которые созданы самим приложением
  4. Использование механизмов Android для запроса прав доступа при необходимости

Приведенные в статье решения помогут избежать описанных проблем и создать стабильно работающее приложение для резервного копирования файлов на Android устройствах.

Создано по материалам из источника по ссылке.

Статья рассматривает проблемы копирования файлов в Delphi на Android, связанные с ограничениями Scoped Storage, и предлагает решения, включая обработку ошибок, альтернативные методы копирования и работу с Storage Access Framework.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Приложение своё ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-08-01 20:05:20/0.0065701007843018/0