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

Как получить имя файла из объекта treeUri для загрузки BGRABitmap?

Delphi , Компоненты и Классы , TTreeView

 

В Android, начиная с API level 19 (KitKat), для доступа к файлам и каталогам, расположенным вне стандартных путей приложения, часто используется Uri (Uniform Resource Identifier) с использованием ACTION_OPEN_DOCUMENT_TREE. treeUri представляет собой Uri для дерева каталогов. Задача состоит в том, чтобы получить имя файла из этого Uri, чтобы затем загрузить содержимое файла в TBGRABitmap.

Проблема:

Получение имени файла напрямую из treeUri может быть затруднительным, так как Uri содержит информацию о месте расположения ресурса, но не обязательно само имя файла.

Решение, предложенное в исходном коде:

В предоставленном коде biologic столкнулся с этой проблемой и нашел решение. К сожалению, само решение не представлено в явном виде в первом сообщении. Второе сообщение указывает на то, что решение было найдено, но код самого решения отсутствует. Однако, исходя из контекста, можно предположить, что решение связано с использованием ContentResolver и запросом метаданных файла по Uri.

Альтернативное решение и его реализация:

Предлагается следующее решение, основанное на использовании ContentResolver для получения информации о файле, связанном с treeUri.

uses
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Provider,
  Androidapi.JNI.Net,
  Androidapi.JNIBridge,
  Androidapi.Helpers,
  FMX.Helpers;

function GetFileNameFromTreeUri(context: JContext; treeUri: Jnet_Uri): string;
var
  contentResolver: JContentResolver;
  cursor: JCursor;
  displayName: string;
  columnIndex: integer;
  uriString: string;
begin
  Result := '';
  if (context = nil) or (treeUri = nil) then Exit;

  contentResolver := context.getContentResolver;
  if contentResolver = nil then Exit;

  uriString := JStringToString(treeUri.toString);

  try
    cursor := contentResolver.query(treeUri, nil, nil, nil, nil);
    if cursor <> nil then
    begin
      try
        // Получаем индекс столбца DISPLAY_NAME
        columnIndex := cursor.getColumnIndex(TJMediaStore_MediaColumns.JavaClass.DISPLAY_NAME);

        if (columnIndex > -1) and cursor.moveToFirst then
        begin
          // Получаем имя файла
          displayName := JStringToString(cursor.getString(columnIndex));
          Result := displayName;
        end;
      finally
        cursor.close;
      end;
    end;
  except
    on E: Exception do
    begin
      // Обработка ошибок, например, когда запрошенный столбец не существует
      System.SysUtils.ShowMessage('Error getting filename: ' + E.Message);
    end;
  end;
end;

Пояснения к коду:

  1. GetFileNameFromTreeUri(context: JContext; treeUri: Jnet_Uri): string: Функция принимает JContext (контекст Android) и Jnet_Uri (объект Uri) в качестве входных параметров и возвращает имя файла в виде строки.
  2. contentResolver := context.getContentResolver;: Получаем объект ContentResolver из контекста. ContentResolver позволяет взаимодействовать с контент-провайдерами, предоставляющими доступ к данным, таким как файлы, мультимедиа и контакты.
  3. cursor := contentResolver.query(treeUri, nil, nil, nil, nil);: Выполняем запрос к контент-провайдеру, используя treeUri. query возвращает JCursor, который позволяет перебирать результаты запроса. nil в качестве аргументов означает, что мы запрашиваем все столбцы, не используем фильтры и сортировку.
  4. columnIndex := cursor.getColumnIndex(TJMediaStore_MediaColumns.JavaClass.DISPLAY_NAME);: Получаем индекс столбца DISPLAY_NAME, который содержит имя файла. TJMediaStore_MediaColumns.JavaClass.DISPLAY_NAME - это константа, представляющая имя столбца.
  5. if (columnIndex > -1) and cursor.moveToFirst then: Проверяем, что столбец DISPLAY_NAME существует и что курсор успешно переместился к первой записи (если она есть).
  6. displayName := JStringToString(cursor.getString(columnIndex));: Получаем значение столбца DISPLAY_NAME (имя файла) из курсора и преобразуем его из JString в string Delphi.
  7. cursor.close;: Обязательно закрываем курсор после использования, чтобы освободить ресурсы.
  8. Обработка ошибок: Код включает блок try...except, который позволяет обрабатывать исключения, которые могут возникнуть при выполнении запроса. Это важно, поскольку контент-провайдер может быть недоступен или может не поддерживать запрошенный столбец.

Пример использования:

uses
  ...,
  Androidapi.Helpers;

procedure TAndroidModule1.AndroidModule1ActivityResult(Sender: TObject;
  requestCode: integer; resultCode: integer; intentData: JObject);
var
  treeUri: Jnet_Uri;
  fileName: string;
  bmp: TBGRABitmap;
begin
  if resultCode = RESULT_OK then
  begin
    if intentData <> nil then
    begin
      treeUri := TJIntent.Wrap(intentData).getData;
      if treeUri <> nil then
      begin
        fileName := GetFileNameFromTreeUri(SharedActivity, treeUri);
        ShowMessage('Имя файла: ' + fileName);

        // Загрузка BGRABitmap
        bmp := TBGRABitmap.Create;
        try
          bmp.LoadFromFile(JStringToString(treeUri.getPath)); // Попытка загрузки по пути из Uri
          // Если не удалось, можно попробовать другой способ загрузки, например, через Stream
          //  bmp.LoadFromStream(...);
        except
          on E: Exception do
            ShowMessage('Ошибка загрузки изображения: ' + E.Message);
        end;

        // Дальнейшая работа с bmp
        // ...

        bmp.Free;
      end;
    end;
  end;
end;

Важные замечания:

  • Разрешения: Убедитесь, что ваше приложение имеет необходимые разрешения для доступа к файлам, указанным в treeUri. В Android 11 (API level 30) и выше необходимо использовать Storage Access Framework (SAF) и получать разрешения на доступ к каталогам. Функция Self.TakePersistableUriPermission(treeUri); в исходном коде указывает на использование SAF.
  • Обработка ошибок: Всегда обрабатывайте возможные ошибки при работе с ContentResolver и файлами. Например, файл может не существовать, или у приложения может не быть прав доступа к нему.
  • Путь к файлу: treeUri.getPath может не всегда возвращать корректный путь к файлу, особенно если файл находится в облачном хранилище или другом месте, отличном от локальной файловой системы. В таких случаях может потребоваться использование ContentResolver для получения InputStream и загрузки данных из потока.
  • Загрузка BGRABitmap: bmp.LoadFromFile(JStringToString(treeUri.getPath)) - это попытка загрузить изображение напрямую из файла, используя путь, полученный из Uri. Если это не работает (например, если getPath возвращает некорректный путь), необходимо использовать ContentResolver для получения InputStream и загрузки изображения из потока.

Альтернативный способ загрузки BGRABitmap через InputStream:

uses
  ...,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Content,
  System.IOUtils;

function LoadBGRABitmapFromUri(context: JContext; uri: Jnet_Uri): TBGRABitmap;
var
  contentResolver: JContentResolver;
  inputStream: JInputStream;
  stream: TStream;
begin
  Result := nil;
  if (context = nil) or (uri = nil) then Exit;

  contentResolver := context.getContentResolver;
  if contentResolver = nil then Exit;

  try
    inputStream := contentResolver.openInputStream(uri);
    if inputStream <> nil then
    begin
      try
        stream := TJavaInputStream.Create(inputStream, false);
        Result := TBGRABitmap.Create;
        Result.LoadFromStream(stream);
      finally
        stream.Free;
        inputStream.close;
      end;
    end;
  except
    on E: Exception do
    begin
      System.SysUtils.ShowMessage('Error loading bitmap from URI: ' + E.Message);
    end;
  end;
end;

В этом варианте мы получаем InputStream из Uri с помощью contentResolver.openInputStream(uri), затем создаем TStream из InputStream и загружаем TBGRABitmap из этого потока. Это более надежный способ загрузки изображений из Uri, особенно если файл находится не в локальной файловой системе.

Заключение:

Получение имени файла из treeUri требует использования ContentResolver и запроса метаданных файла. Предложенное решение предоставляет пример кода, который позволяет получить имя файла и загрузить TBGRABitmap из Uri. Важно помнить о необходимости обработки ошибок и получения необходимых разрешений для доступа к файлам. Приведены два способа загрузки BGRABitmap: напрямую из файла (если getPath возвращает корректный путь) и через InputStream (более надежный способ). Выбор способа зависит от конкретной ситуации и типа файла.

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

Статья описывает проблему получения имени файла из объекта treeUri в Android для загрузки BGRABitmap, предлагая решения с использованием ContentResolver и InputStream.


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

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




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


:: Главная :: TTreeView ::


реклама


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

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