Jump to content

Viktor Akselrod

Administrators
  • Posts

    271
  • Joined

  • Last visited

  • Days Won

    48

Everything posted by Viktor Akselrod

  1. Здравствуйте. Демо пример уже доступен, но только в закрытой клиентской зоне форума.
  2. Здравствуйте. Исправлено в следующем релизе. Спасибо, что сообщили.
  3. Здравствуйте. В этой статье мы поговорим о новинке, которая появится в релизе 1.11.6.0, а именно о встроенном средстве просмотра логов устройств работающих под управлением операционной системы Android. Общие данные о том, что такое логи, их ценность при отладке и тд вы можете прочитать в статье касающейся логирования в контексте iOS Общие сведения. Для просмотра логов под Android используется утилита командной строки logcat. Вы можете использовать ее как напрямую, управляя через параметры командной строки, так и воспользоваться Android Studio в которой есть одноименное окно logcat. Второй вариант предпочтительней, т. к. имеет графический интерфейс, но, естественно, он требует установки самой Android Studio. Итак, новая утилита FGX Android Log Viewer (далее логвьювер) призвана упростить просмотр логов за счет удобной интеграции в IDE, графического интерфейса и гибкой системы фильтрации. Внешний вид. Запустить логвьювер можно из меню Project -> FGX Android Log Viewer. Левую горизонтальную часть окна занимает тулбар с основными органами управления, такими как: запуск/остановка захвата логов, очистка списка, экспорт и тд. Верхний тулбар содержит выбор активного устройства, выбор приложения, для которого будут собираться логи (либо для всех приложений) и быстрый фильтр. Основную часть окна занимает список логов, представленный в виде таблицы. Внизу располагается статус бар, отображающий количество элементов списка, в тч отфильтрованных, а так же, текущий статус захвата логов. Опциональное окно детальной информации о событии. Логвьювер поддерживает докинг форм, следовательно может быть как плавающим окном, так и быть закреплен в любом удобном для вас месте в IDE. Отправка сообщений в лог. Для начала работы выберите устройство в верхнем тулбаре (в нашем случае это Redmi Note 7) и нажмите кнопку старта захвата логов. Список будет постепенно наполняться записями. Для просмотра детальной информации о записи можно два раза кликнуть по самой записи в списке, либо выделить запись и нажать соответствующую кнопку в левом тулбаре. Теперь создадим тестовое приложение, запустим его и отправим несколько записей в лог. Для этого воспользуемся кодом из предыдущей статьи: uses System.SysUtils, FGX.Application, FGX.Dialogs, FGX.Log; procedure TFormMain.fgButton1Tap(Sender: TObject); begin TfgLog.Debug('Hello from TfgLog.Debug'); end; procedure TFormMain.fgButton2Tap(Sender: TObject); begin TfgLog.Info('Hello from TfgLog.Info'); end; Наши сообщения отправлены и встаёт вопрос, как их найти среди огромного списка других сообщений. Есть два варианта решения задачи: Изначально собирать сообщения только от нашего приложения, выбрав его перед захватом лога в верхнем тулбаре (в этом случае количество попадаемых в лог сообщений значительно сократится, но так можно пропустить важные сообщения, в т.ч. падения, от самой Android и/или её компонентов) Воспользоваться фильтрацией, которая представлена в логвьювере в двух вариантах: быстром и расширенном. Воспользуемся вариантом 2. Варианты фильтрации списка событий. Окно быстрой фильтрации находится в правой части верхнего тулбара (вариант по-умолчанию): Фильтрация осуществляется по всем столбцам списка без учёта регистра. Можно указывать несколько значений, разделённых пробелом. В итоговую выборку попадут события, которые соответствуют хотя бы одной подчасти фильтра (OR). Для включения расширенного фильтра воспользуйтесь кнопкой на левом тулбаре. После включения верхний тулбар приобретёт следующий вид: Каждое окно ввода "привязано" к одноименному столбцу списка. В итоговую выборку попадут события, которые соответствуют всем заполненным окнам фильтра (AND). Просмотр событий. Итак, чтобы найти отправленные ранее сообщения, для начала укажем в окне быстрого фильтра слово "FGX" - этим тегом помечаются все сообщения, отправленные с помощью TfgLog. Как видно на скриншоте, в списке остались только относящиеся к FGX записи, среди которых не составит труда увидеть и искомые записи. Альтернативный вариант - поиск по Process Id (PID), который можно узнать из окна IDE Events (в нашем случае 25505) В результате значений будет уже больше, т.к. в итоговую выборку попадают все сообщения, относящиеся к процессу, а не только сообщения, отправленные непосредственно FGX. Но, даже так, найти наши записи не составляет особого труда. Либо вы можете отфильтровать список непосредственно по части отправленной записи: Состав и количество фильтров огранивается только вашей фантазией. Надеемся, что вам понравится опыт работы с новым средством просмотра логов FGX Android Log Viewer. Спасибо за внимание и удачной отладки!
  4. Download: setup_1.11.5.0_release.eng.exe.zip Release date: 18 August 2021 Improvements 🙌 TfgLabel Now when user taps on link in HTML in TfgLabel text (TextType=HTML), the link is opened by operation system (Android). FGX-125 Clicks on hyperlinks have stopped being processed (Android). Bug Fixes 🐛 FGX-117 TfgSvgPath incorrect display of some images (Android). FGX-118 Long titles and subtitles are not trimmed in TfgNavigationBar (iOS). FGX-119 The TfgEdit/TfgMemo.OnChanged event can be invoked when form is being closed (iOS). FGX-120 The TfgCollectionView.Padding doesn't work (iOS). FGX-121 Realign doesn't work in TfgCollectionView.OnBindItem (iOS). FGX-122 The text is not visible in TfgButton on iOS 12.5.4 (iOS). FGX-123 Duplicated Android API classes (Android). FGX-124 Bug in usage Font.Style (iOS). FGX-126 Hyperlinks are not rendered in TfgLabel (Android). The Italic style may not applied sometimes (iOS). The shadow parameters were not applied to the text on the TfgButton (iOS). Fixed the use of clipping text by characters in TfgLabel when there is no hyphenation (iOS).
  5. Скачать: setup_1.11.5.0_release.rus.exe.zip Дата релиза: 18 августа 2021 Улучшения 🙌 TfgLabel Теперь при нажатии на ссылку в HTML в TfgLabel (TextType=HTML) ссылка открывается системой в приложении по умолчанию (Android). FGX-125 Перестали обрабатываться нажатия на гиперссылки (Android). Исправление ошибок 🐛 FGX-117 TfgSvgPath некорректное отображение некоторых изображений (Android). FGX-118 Длинные заголовки в TfgNavigationBar не обрезаются (iOS). FGX-119 Событие TfgEdit/TfgMemo.OnChanged может вызываться при закрытии формы (iOS). FGX-120 Не работает TfgCollectionView.Padding (iOS). FGX-121 Не работает Realign при обращении к элементам TfgCollectionView (iOS). FGX-122 Не отображается текст в TfgButton на iOS 12.5.4 (iOS). FGX-123 Дублирование классов в Android API (Android). FGX-124 Ошибка в отображении Font.Style (iOS). FGX-126 Не отображается текст гиперссылок (Android). Иногда стиль отображения шрифта Italic мог не применяться (iOS). Параметры тени не применялись к тексту на кнопке TfgButton (iOS). Исправлено использования отсечения текста по символам в TfgLabel при отсутствии переноса (iOS).
  6. Здравствуйте. В этой статье мы поговорим об отладке приложений на iOS с помощью логирования (часть материала будет актуальна и для Android). Общие сведения. Логирование позволяет получать информацию о работе вашего приложении даже когда оно запущено без отладчика, при фатальных падениях приложения и тд. Особенно тема логирования актуальна для мобильных платформ, т.к. здесь, к сожалению, Delphi отладчик не может похвастаться такой же стабильностью и качеством, как отладчик для платформы Win32. Пошаговая отладка выливается в мучительное ожидание переходов, показываемые отладчиком значения могут не соответствовать действительности, либо вообще отсутствовать и тд. Важно! Логирование не заменяет полностью отладчик, а является вспомогательным инструментом. Условно механизм логирования можно разделить на источник логов и на утилиты для сборки и просмотра логов. Источники логов. Источником логов может быть как библиотека FGX Native, операционная система, так и само приложение (сообщения отправленные непосредственно разработчиком). На первые два варианта разработчик особо не может повлиять, поэтому более подробно остановимся на третьем варианте. Отправка сообщения в лог осуществляется с помощью кроссплатформенного класса TfgLog. Все методы TfgLog являются классовыми, а сам класс существует в единственном экземпляре - это означает, что для его использования нет необходимости создавать экземпляр класса. Основным методом класса является метод Log позволяющий отправить строку с указанным уровнем лога. /// <summary>Выводит в системный лог сообщение <c>AMessage</c> типа <c>ALogType</c>.</summary> class procedure Log(const ALevel: TfgLogLevel; const AMessage: string); Уровни лога определяют степень важности того или иного события. /// <summary>Уровень логирования.</summary> TfgLogLevel = (Trace, Debug, Info, Warning, Error, Fatal); Вы можете определить минимальный уровень лога с помощью свойства MinimumLevel, чтобы уменьшить количество выводимых в лог сообщений /// <summary> /// Указывает минимальный уровень лога, начиная с которого сообщение будет выводиться в системный лог. /// Порядок следования уровней: Debug, Info, Warning, Error, Fatal. Debug - самый низкий. /// </summary> /// <remarks> /// Для <c>DEBUG</c> конфигурации выводятся все типы сообщений по умолчанию. Для <c>RELEASE</c> сообщений выше /// <c>Info</c>. Если вы хотите видеть в релизной сборке вашего приложения и отладочные сообщения, то задайте /// значение <c>TfgLogLevel.Debug</c> в это свойство. Данная настройка распространяется только на этот класс. На /// логирование через сервис <c>IFGXLoggerService</c> она не действует. /// </remarks> class property MinimumLevel: TfgLogLevel read FMinimumLogLevel write FMinimumLogLevel; Для удобства у класса TfgLog есть набор одноименных методов, соответствующих каждому уровню лога. Например: /// <summary> /// Выводит в системный лог низкоуровневое отладочное сообщение <c>AMessage</c> для выполнения трассировки. /// </summary> class procedure Trace(const AMessage: string); overload; /// <summary>Выводит в системный лог отладочное сообщение <c>AMessage</c>.</summary> class procedure Debug(const AMessage: string); overload; В дополнение, у каждого такого метода существует перегруженная версия, принимающая во втором аргументе список параметров для отправки форматированной строки: /// <summary> /// Выводит в системный лог низкоуровневое отладочное сообщение <c>AMessage</c> с поддержкой форматирования <c>System.Format</c>. /// </summary> class procedure Trace(const AFormat: string; const Args: array of const); overload; /// <summary> /// Выводит в системный лог отладочное сообщение <c>AMessage</c> с поддержкой форматирования <c>System.Format</c>. /// </summary> class procedure Debug(const AFormat: string; const Args: array of const); overload; Сборка и просмотр логов. Для просмотра логов с iOS используется утилита, работающая на компьютере под управлением macOS под названием Console. Для просмотра логов с Android используется утилита работающая на компьютере под управлением Windows под названием logcat. Частично логирование в контексте Android было затронуто ранее в Уроке 1 «Настройка окружения, Hello World приложение и логирование». В данной статье мы сосредоточимся на утилите Console. Важно! Подразумевается, что вы имеете настроенную связку: компьютер под управлением macOS к которому подключено устройство с iOS. Исходные данные: на устройстве с iOS установлено приложение под названием TestLogging, которое имеет только две кнопки, при нажатии на которые отправляются сообщения в системный лог. Код выглядит следующим образом: uses System.SysUtils, FGX.Application, FGX.Dialogs, FGX.Log; procedure TFormMain.fgButton1Tap(Sender: TObject); begin TfgLog.Debug('Hello from TfgLog.Debug'); end; procedure TFormMain.fgButton2Tap(Sender: TObject); begin TfgLog.Info('Hello from TfgLog.Info'); end; Теперь перейдем непосредственно к утилите сбора и просмотра логов. Запустите утилиту Console которая находится в Launchpad -> Other. Главное окно состоит из меню навигации в левой части (1), тулбара с органами управления вверху (2) и списка логов, который занимают остальную клиентскую область окна (3). Теперь выбираем в меню навигации слева устройство из списка Devices с которого мы хотим получать логи. В нашем случае это устройство с именем IPhone. Теперь запускаем сбор логов с помощью кнопки тулбара Start или кликнув по ссылке Start streaming находящейся в центре списка логов. После старта список логов будет быстро наполняться сообщениями. Список логов представляет собой таблицу с настраиваемыми колонками. Вы можете настроить видимость колонок по своему усмотрению с помощью контекстного меню, вызываемого по клику на заголовки таблицы. Самая полезная для нас информация находится в колонке Message - это непосредственно текстовое сообщение лога. Более удобно текстовое сообщение просматривать в окне детальной информации, которое можно открыть двойным кликом по строке списка логов, либо с помощью кнопки тулбара Info. Теперь запустим наше тестовое приложение и последовательно нажмем обе кнопки. Лог содежит тысячи записей, среди которых практически невозможно найти интересующие нас строки. Для решения этой задачи существуют фильтры, которые располагаются в правой части тулбара. Механизм фильтрация довольно гибкий и позволяет комбинировать несколько фильтров по разным колонкам с учетом выбранного способа сравнения (частичное или полное совпадение включая вариант с отрицанием). Важно! Фильтрация осуществляется без учета регистра. Есть несколько способов, как можно отобразить только те строки, которые относятся к нашему приложению. Самый простой вариант - отфильтровать по имени процесса. Вводим фразу TestLogging в окно Search и нажимаем клавишу Enter на клавиатуре. По-умолчанию создастся фильтр с типом Any и способом сравнения Containts. Теперь изменим тип фильтра с Any на Process, a Containts на Equal, что означает, что в списке логов останутся только те строки, текст которых в колоноке равен TestLogging. На скриншоте видно, как строки переданные самой библиотекой FGX Native, так и те, которые были отправлены после нажатия на кнопки (отмечены стрелками). Теперь вы можете изучать собранную информацию просматривая сообщения. При необходимости вы можете сохранить выделенные строки в буфер обмена, либо передать их в другое приложение к помощью кнопки тулбара Share. Логирование - мощный инструмент, который может пригодиться в самых трудных и запутанных ситуациях при поиске ошибок. Спасибо за внимание и удачной отладки!
  7. A demo example will be posted right after the next release, because it uses some of the new functionality not available in the current release.
  8. Стала доступна запись вэбинара Демо-пример будет выложен сразу после очередного релиза, т.к. в нем используется часть нового функционала недоступного в текущем релизе.
  9. Пример мобильного приложения из вебинара так же будет доступен на форуме несколько позже.
  10. Hello. We are sorry. We have some technical problems. We try to solve them as quickly as possible. Thank you.
  11. Здравствуйте. Еще одним нововведением в релизе 1.11.2.0, помимо TfgPopup, является работа с пикселями ("сырыми данными") TfgBitmap. Доступ к пикселям открывает практически неограниченные возможности для обработки и анализа изображений. Так же в новом релизе будет добавлена возможность поворота изображения. Воможность работы с пикселями TfgBitmap. Общие сведения. Обращение к сырым данным возможно только между парными вызовами TfgBitmap.MapData и TfgBitmap.UnmapData, которые могут быть знакомы пользователям FMX. Однако, важным отличием от FMX, является отсутствие уровня доступа (только чтение/только запись/чтение и запись). Это сделано с целью ускорения доступа, т. к. работа осуществляется непосредственно с данными нативного изображения без создания промежуточного буфера. В результате вызова TfgBitmap.MapData вы получаете интерфейс IFGXBitmapData (более подробно рассмотрен ниже), который предоставляет доступ к пикселям изображения. Важно! Актуальность объекта IFGXBitmapData гарантирована только между вызовами TfgBitmap.MapData и TfgBitmap.UnmapData, т.к. используется "натуральный" интерфейс без подсчета ссылок. Важно! Во время доступа к сырым данным операции по изменению TfgBitmap запрещены (например загрузка из различных источников, изменение размера, масштаба, поворота и тд). Типичный пример работы с сырыми данными изображения: var LBitmapData: IFGXBitmapData; begin if LBitmap.MapData(LBitmapData) then try // Работа с пикселями изображения. finally LBitmap.UnmapData; end; end; Важно! Всегда проверяйте результат выполнения TfgBitmap.MapData во избежание непредвиденных последствий. Повторный вызов TfgBitmap.MapData для уже спроецированных данных вернет ложь. Интерфейс IFGXBitmapData. Интерфейс IFGXBitmapData предоставляет информацию об изображении (Info, Width, Height), а так же позволяет манипулировать пикселями изображения (RawData, Scanlines, Pixels, Colors). Информация о битмапе TfgBitmapInfo: BitsPerPixel — количество бит на один пиксель изображения. К примеру, для одного из самых распространенных вариантов ARGB, этот параметр будет равен 32-ум битам. BytesPerRow — количество байт на одну строку изображения. Обычно это Width * BitsPerPixel, но, в случае применения выравнивания для ускорения доступа к данным, значение может быть иным. PixelFormat — формат пикселя изображения. В отличии от фиксированного формата ARGB присущего стандартному типу TAlphaColor, нативные изображения могут иметь различный состав и порядок следования цветовых компонентов. Возможные комбинации этих параметров отражает тип TfgBitmapPixelFormat. TfgBitmapPixelFormat = (Unknown, Alpha, Gray, ARGB, RGBA, RGB, RGB24); IsAlphaPremultiplied — флаг, показывающий являются ли компоненты пикселя предварительно помноженными на компоненту прозрачности. Интерфейс IFGXBitmapData содержит несколько вариантов доступа к самим данным, которые отличаются по степени абстракции: RawData — самый низкий уровень. Возвращает указатель на начало данных. Размер данных можно узнать из свойства RawDataSize. Scanlines — указатель на переданную в аргументе строку. Размер данных строки в байтах можно получить из Info.BytesPerRow, количество пикселей в строке — Width. Pixels — указатель на пиксель. В аргументах передаются координаты пикселя. Размер пикселя в битах можно получить из Info.BitsPerPixel. Colors — цвет пикселя в стандартном формате TAlphaColor. В аргументах передаются координаты пикселя. Как правило, для достижения максимальной скорости при последовательном сканировании пикселей изображения, вместо индексного доступа (Pixels, Colors) используют инкрементный перебор начиная с некой точки отсчёта (начало изображения RawData, начало определенной строки Scanlines[Y], определенный пиксель Pixelsх[X, Y]) . В этом случае вы получаете указатель, вместо привычного TAlphaColor. Для преобразования данных по указателю в тип TAlphaColor вам могут пригодиться готовые варианты для конвератции, которые находятся в хэлпере TAlphaColorHelper из модуля FGX.Types.Color. Для формирования TAlphaColor из сырых данных используйте перегруженный конструктор: constructor Create(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean); overload; Для обратной операции подойдет метод: /// <summary>Записывает текущий цвет по адресу <c>APixel</c> с учетом опций <c>APixelFormat</c> и <c>AIsAlphaPremultiplied</c>.</summary> procedure ToPixel(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean); Реальный пример работы с сырыми данными. Ниже приведен кусок кода из нового демонстрационного примера "Графика" -> "TfgBitmap - работа с "сырыми" данными" в котором изображение преобразуется из цветного в оттенки серого. uses FGX.Types.Color, FGX.Canvas.Types, FGX.Canvas.Types, FGX.Assets, FGX.Assets.BitmapSet; procedure TFormMain.fgButton1Tap(Sender: TObject); var LBitmapSet: TfgAssetBitmapSet; LBitmap: TfgBitmap; LBitmapData: IFGXBitmapData; I, J: Integer; begin if not TfgAssetsManager.Current.Find<TfgAssetBitmapSet>('Image', LBitmapSet) then Exit; LBitmap := LBitmapSet.GetBitmap; if LBitmap.MapData(TfgBitmapDataAccessMode.ReadWrite, LBitmapData) then try for J := 0 to LBitmap.Height - 1 do for I := 0 to LBitmap.Width - 1 do LBitmapData.Colors[I, J] := LBitmapData.Colors[I, J].ToGrayscale; finally LBitmap.UnmapData; end; fgPaintBox1.Invalidate; end; Повороты изображения. Благодаря добавлению работы с сырыми данными появилась возможность с легкостью вращать изображения. Поворот осуществляется с помощью метода TfgBitmap.Rotate: /// <summary>Поворачивает изображение на указанный угол.</summary> procedure Rotate(const AAngle: TfgRotation); В качестве аргумента передается одно из предустановленных значений угла поворота. TfgRotation = (Rotation0 = 0, Rotation90 = 90, Rotation180 = 180, Rotation270 = 270); Поворот осуществляется по часовой стрелке. Благодарим за внимание и приятного коддинга 🙂.
  12. Здравствуйте. Ошибка подтверждена. Ваша сообщение переведено в баг трекер.
  13. Здравствуйте. Проблема в iOS мосте (RTL) на Rio. В настоящий момент мы ищем решение.
  14. Yes. iOS profile will be created anyway. These checkboxes are not responsible for creating an iOS profile. If you are not interested in the iOS profile, just leave the default checkboxes.
  15. Hello @MoreWood We have fixed the translation in the next release. Correct translation: You must select at least one type of devices for the iOS platform. Thank you.
  16. Здравствуйте. Продублировал ваш запрос на багтрекер. Спасибо.
  17. Здравствуйте. Проверим информацию. Спасибо за отчет.
  18. All right. Still need a fix from our side. Thank you
  19. Спасибо за ответ. Проверим на вашем окружении.
  20. Hello. TfgAnimationHelper.HideForm(Self, [TfgAnimationOption.ReleaseOnFinish]) - this call does not close immediately form. first plays the animation, then enqueues the deletion and only then deletes the form. during this time fgBarcodeScanDetected may fire several more times. so it is important to prevent for double form destruction.
×
×
  • Create New...