Jump to content

Viktor Akselrod

Administrators
  • Posts

    458
  • Joined

  • Last visited

  • Days Won

    87

Blog Entries posted by Viktor Akselrod

  1. Viktor Akselrod
    Ранее в блоге мы уже рассматривали использование аутентификацию с помощью Facebook Login в рамках iOS приложения. В данной статье мы рассмотрим использование сервиса Facebook Login для Android приложений, поддержка которого появится в версии FGX Native 1.16.1.0.
    Настройка серверной части была подробно расписана в статье для iOS. Если вы ранее уже настраивали серверную часть для iOS приложения, то можете пропустить этот шаг. 
    Перейдем непосредственно к настройке приложения.
     
    1. Добавить библиотеку-зависимость Facebook SDK в настройках проекта с помощью диалога Project -> FGX Android Libraries -> Добавить библиотеку-зависимость.
    com.facebook.android:facebook-login:16.2.0
    (на момент написания статьи (03/09/2023) актуальная версия SDK 16.2.0)
    2. Создаем текстовый файл в папке проекта с именем strings.xml, в который добавляем константы, взятые из настроек приложения на сервере.
    <resources> <string name="app_name">APP-NAME</string> <string name="facebook_app_id">APP-ID</string> <string name="fb_login_protocol_scheme">fb1234</string> <string name="facebook_client_token">CLIENT-TOKEN</string> </resources> где APP-ID - App ID из шага 8a
    CLIENT-TOKEN - Client token из шага 8b
    APP-NAME - имя приложения
    3. Добавляем файл strings.xml в деплой приложения (Project -> Deployment) для обеих платформ Android32/64. Remote path должен быть res\values\.

    4. Вносим изменения в шаблон манифеста AndroidManifest.template.xml сразу после плейсхолдера <%fgx-activities%> и до основной activity
    ... <%fgx-activities%> <!--begin insertion--> <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/> <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/> <activity android:name="com.facebook.FacebookActivity" android:configChanges= "keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" /> <activity android:name="com.facebook.CustomTabActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="@string/fb_login_protocol_scheme" /> </intent-filter> </activity> <!--end insertion--> <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity" ....  
    Внимание! Из-за ошибки в Facebook Login SDK пока недоступно получение дополнительных данных таких как email, имя и т.д. На данный момент в случае успешной аутентификации сервис возвращает только основной токен.
    Мы следим за исправлением этой ошибки и сообщим вам, как только это произойдет.
     
    Спасибо за внимание.
  2. Viktor Akselrod
    В этой статье мы разберем настройку и использование сервиса VK Login с помощью TfgVKLoginAuthenticationClient.
     

    Настройка серверной части
    Переходим по ссылке и попадаем в список приложений. Нажимаем на кнопку Create 
    Заполняем название, выбираем тип Standalone app и нажимаем кнопку Connect app
    После подтверждения по телефонному звонку попадаем на страницу вновь созданного приложения и переходим в раздел Settings В настройках запоминаем значение параметра App ID (он далее понадобится нам при настройке Delphi приложения) На этой же странице указываем идентификатор нашего приложения в поле App Bundle ID for iOS (также понадобится далее при настройке Delphi приложения) App status изменяем на Application on and visible to all
    Сохраняем настройки с помощью кнопки Save.
     
    Настройка клиентской части
    Переходим в настройки iOS профиля приложения и назначаем CFBundleIdentifier из шага 5 настройки серверной части

    Открываем в текстовом редакторе файл info.plist.TemplateiOS.xml из директории проекта и сразу после плейсхолдера <%StoryboardInfoPListKey%> добавляем следующий текст
    <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>vkAPP-ID</string> <key>CFBundleURLSchemes</key> <array> <string>vkAPP-ID</string> </array> </dict> </array> <key>LSApplicationQueriesSchemes</key> <array> <string>vk</string> <string>vk-share</string> <string>vkauthorize</string> </array> <key>VKAppID</key> <string>APP-ID</string> где APP-ID - App ID из шага 4
    Внимание! Если вы в приложении используете одновременно аутентификацию Facebook Login, то необходимо скомбинировать вышеуказанные ключи с имеющимися ключами от Facebook Login.
    Итоговый файл можно посмотреть в прикрепленном демо проекте Authentication - Clients.zip
    Спасибо за внимание.
  3. Viktor Akselrod
    В этой статье мы разберем настройку и использование сервиса Google Sign-In с помощью TfgGoogleSignInAuthenticationClient.

     
    Настройка серверной части
    Переходим по ссылке и попадаем н а страницу документации с пошаговым мастером настройки, запускаемым по кнопке Configure a project
    Запускаем мастер и указываем имя проекта (внутреннее именование, невидимое для конечного пользователя)
    Указываем имя продукта для OAuth клиента, которое увидит конечный пользователь в диалоге аутентификации
    Далее в выпадающем списке выбираем тип клиента Android, указываем имя пакета (далее понадобится нам при настройке Delphi приложения) и отпечаток сертификата (получение рассмотрено ниже)
    Завершаем настройку (при надобности сохраните конфигурационные данные клиента)
     
    Получение SHA-1 отпечатка сертификата
    При сборке Android приложение подписывается сертификатом разработчика. От типа сборки, режима конфигурации и версии Delphi будет зависеть местоположение файла сертификата от которого мы будет получать отпечаток. Ниже будет рассмотреть вариант получения отпечатка для Debug сборки в режиме конфигурации Development для Delphi 11.
    Открываем командуню строку Windows и выполяем следующую команду 
    keytool -list -v -alias androiddebugkey -keystore "C:\Users\%USERNAME%\AppData\Roaming\Embarcadero\BDS\22.0\debug.keystore" где %USERNAME% - имя залогиненого пользователя Windows
    22.0 - версия Delphi 11 (для Delphi 10.4 этот параметр будет равен 21.0).
    Если вы используете собственный сертификат разработчика и режим конфигурации Application Store, подставьте путь к вашему .keystore файлу.

    Настройка клиентской части
    Переходим в настройки Android профиля приложения и назначаем package из шага 4 настройки серверной части

    Открываем в текстовом редакторе файл AndroidManifest.template.xml из директории проекта и сразу после закрывающего тега </activity> добавляем следующий текст
    <!-- Google Play Services version, which are used in this application. This value is checked by Play Services in runtime --> <meta-data android:name="com.google.android.gms.version" android:value="12451000" /> <activity android:name="com.google.android.gms.auth.api.signin.internal.SignInHubActivity" android:excludeFromRecents="true" android:exported="false" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <!-- Service handling Google Sign-In user revocation. For apps that do not integrate with Google Sign-In, this service will never be started. --> <service android:name="com.google.android.gms.auth.api.signin.RevocationBoundService" android:exported="true" android:permission="com.google.android.gms.auth.api.signin.permission.REVOCATION_NOTIFICATION" /> Внимание! Если в настройках вашего проекта вклюены опции AdMob Service, Maps Service или Receive push notifications указывать первую строку с версией Google Play Services необязательно, т.к. она добавится автоматически. 
    Итоговый файл можно посмотреть в прикрепленном демо проекте Authentication - Clients.zip
    Спасибо за внимание.
     
  4. Viktor Akselrod
    В этой статье мы разберем настройку и использование сервиса Facebook Login с помощью TfgFacebookLoginAuthenticationClient.

    Настройка серверной части
    Переходим по ссылке и попадаем в список приложений Для создания нового приложения нажимаем кнопку Create App
    Выбираем наиболее подходящий под вашу задачу тип приложения
    Заполняем название приложения и контактную информацию
    После завершения создания нового приложения мы попадаем на страницу настроек приложения. Заходим в настройки сервиса Facebook Login
    Выбираем платформу iOS
    Далее идёт пошаговая настройка. Большая часть шагов не представляет для нас интереса. 
    В шаге 2 необходимо указать Bundle ID (он далее понадобится нам при настройке Delphi приложения)
    В шаге 3 нужно включить опцию Enable Single Sign On
    Скопируем несколько значений из серверных настроек, которые понадобятся нам для настройки Delphi приложения наравне с Bundle ID из предыдущего шага:
    a) App ID, который можно взять в тулбаре настроек, либо со страницы Settings-Basic
    b) Client token, который находится на странице Settings-Advanced-Security
    Настройка клиентской части
    Переходим в настройки iOS профиля приложения и назначаем CFBundleIdentifier из шага 7 настройки серверной части

    Открываем в текстовом редакторе файл info.plist.TemplateiOS.xml из директории проекта и сразу после плейсхолдера <%StoryboardInfoPListKey%> добавляем следующий текст
    <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>fbAPP-ID</string> </array> </dict> </array> <key>FacebookAppID</key> <string>APP-ID</string> <key>FacebookClientToken</key> <string>CLIENT-TOKEN</string> <key>FacebookDisplayName</key> <string>APP-NAME</string> <key>LSApplicationQueriesSchemes</key> <array> <string>fbapi</string> <string>fb-messenger-share-api</string> </array> где APP-ID - App ID из шага 8a
    CLIENT-TOKEN - Client token из шага 8b
    APP-NAME - имя приложения

    Итоговый файл можно посмотреть в прикрепленном демо проекте Authentication - Clients.zip
     
    Спасибо за внимание.
     
  5. Viktor Akselrod
    Этой статьей мы начинаем серию статей по клиентам аутентификации, которые впервые появились в версии 1.13.4.0. Мы планируем постепенно добавлять новые сервисы аутентификации. На момент написания данной статьи поддерживаются три клиента для платформы iOS: TfgAppleIdAuthenticationClient, TfgFacebookLoginAuthenticationClient и TfgVKLoginAuthenticationClient.

     
    Что такое аутентификация?
    Согласно википедии «аутентификация» — это процедура проверки подлинности. Те другими словами это доказательство того, что перед вами именно тот пользователь, кем он представился. В обычной жизни можно провести аналогию со сличением личности по паспорту.
    Что является результатом аутентификации?
    Основным результатом аутентификации является идентификатор аккаунта (TfgAccountId), а так же ряд дополнительных полей наличие и состав которых зависит от сервиса аутентификации и желания пользователя их предоставить. Как правило, сервисы возвращают имя пользователя, email.
    Сервис аутентификации в библиотеке FGX Native
    Каждый сервис аутентификации реализует интерфейс IFGXAuthenticationService, который включает в себя метод по входу, выходу и проверке состояния авторизации по указанному индентификатору аккаунта.
    За регистрацию, хранение и поиск сервисов аутентификации отвечает класс TfgAuthenticationServiceManager.
    Для упрощения работы с сервисами добавлены клиенты аутентификации — компоненты, которые можно привычным способом бросить на форму в дизайнере и настроить с помощью инспектора объектов.
    Клиент для аутентификации с помощью Apple ID - TfgAppleIdAuthenticationClient (iOS)
    Общие сведения по использованию фреймворка.
    Абсолютно все сервисы аутентификации требуют предварительной настройки на стороне сервера и на стороне клиента (приложения).
    Важно: необходимо иметь платный аккаунт разработчика.
    Настройка серверной части.
    Переходим по ссылке и попадаем в список идентификаторов приложений. Нажимаем кнопку добавления нового идентификатора приложения.
    Выбираем опцию App IDs
    Тип идентификатора App
    Добавляем описание, указываем уникальный Band ID (он далее понадобится нам при настройке приложения) и отмечаем галку напротив опции Sign In with Apple
    Подтверждаем изменения и сохраняем новый идентификатор.
    Настройка клиентской части.
    Для успешной сборки приложения необходимо в SDK добавить фреймворк AuthenticationServices .
    Для этого необходимо открыть настройки SDK Tools-Options-Deployment-SDK Manager, в списке SDK выбрать iOS и нажать кнопку добавления нового элемента.

    Добавляем фреймворк со следующими параметрами:
    Path: $(SDKROOT)/System/Library/Frameworks Name: AuthenticationServices Type: Framework
    Нажимаем кнопку Update Local File Cache для обновления SDK.
    Переходим в настройки iOS профиля приложения и назначаем CFBundleIdentifier из шага 5 настройки серверной части.

    Демо пример использования клиентов аутентификации
    В версии 1.14.0.0 в поставку библиотеки будет включен пример по использованию клиентов аутентификации, который будет расширяться по мере добавления новых сервисов.
    Данный пример вы можете загрузить уже сейчас не дожидаясь следующего релиза Authentication - Clients.zip.
     
    Спасибо за внимание.
  6. Viktor Akselrod
    Здравствуйте.
    В этой статье мы поговорим о новинке, которая появится в релизе 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. 
    Спасибо за внимание и удачной отладки!
     
     
     
  7. Viktor Akselrod
    Здравствуйте.
    Еще одним нововведением в релизе 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); Поворот осуществляется по часовой стрелке.
     
    Благодарим за внимание и приятного коддинга 🙂.
  8. Viktor Akselrod
    Вступление
    Мы стараемся прислушиваться к потребностям наших клиентов. На этот раз мы добавили чрезвычайно важную возможность для всех пользователей карт — а именно возможность использования собственных изображений (тайлов) карт.
    runtime.mp4 Когда и кому это может понадобиться?
    На первый взгляд стандартные поставщики карт имеют полноценный, законченный функционал и не требуют вмешательства со стороны программиста. Но, как это зачастую бывает в реальной жизни, есть нюансы. Что, если вам нужно единообразие карт на обоих платформах iOS и Android (напоминаем, кто каждая ОС имеет своего поставщика карт/тайлов)? Если вам нужен оффлайн доступ к картам? Если вы разрабатываете игру и вам нужно нарисовать необычный ландшафт? Так же вам может понадобиться выбор локального поставщика карт, который имеет лучшую детализацию для конкретной местности, в которой планируется использовать приложение. И это далеко неполный список, когда собственный провайдер тайлов может быть полезен.
    Что такое тайлы? Модель тайлов
    Тайлы — это подготовленные заранее изображения части карты из которых, как в пазле, строится полная карта. Каждый тайл имеет три основных характеристики: координата по оси X, координата  по оси Y, а так же зум, к которому принадлежит данный тайл. 
    Чтобы понять, что означают эти характеристики в контексте карты, нужно разобраться с моделью тайлов. 
    Как было сказано ранее, карта строится из прямоугольных кусков и, в первую очередь, загружаются только те тайлы, которые видимы на текущем экране, а не вся карта целиком. Данный подход позволяет как оптимизировать расходы трафика (т. к. чаще всего речь идет об онлайн поставщиках карт), так и ускорить загрузку видимой части карты в целом.
    Карта имеет координатную сетку и зум. От уровня зума зависит разрешение координатной сетки. Чем выше зум, тем больше координатная сетка и тем выше детализация карты.
    По этой ссылке можно наглядно увидеть зависимость разрешения карты от зума. 
    Где взять тайлы?
    Когда мы разобрались с вопросом зачем, надо понять кто и на каких условиях предоставляет тайлы. 
    В первую очередь существует несколько крупных сервисов, которые специализируются на предоставлении тайлов. Как правило, поставщики имеют несколько планов — бесплатный с некоторыми ограничениями и платный доступ, когда количество запросов от вашего приложения превышает некий заранее оговоренный лимит. Краткий обзор основных поставщиков географических карт можно посмотреть по ссылке. Так же есть бесспорный лидер среди бесплатных поставщиков географических карт —  OpenStreetMap. 
    И, конечно же, вы сами можете сделать свою собственную реализацию поставщика тайлов, если вам не подходит ни один из готовых вариантов.
    Используем провайдеры тайлов в FGX Native
    Библиотека FGX Native предусматривает несколько вариантов добавления альтернативных провайдеров тайлов в ваш проект.
    Готовые провайдеры тайлов
    На момент публикации статьи в поставке библиотеки есть только один готовый компонент-провайдер  TfgOSMMapTileProvider, который, как не сложно догадаться из названия, предоставляет доступ к тайлам сервиса OpenStreetMap. Не исключено, что со временем список готовых провайдеров будет пополняться новыми сервисами.
    Использование: бросить на форму компонент TfgOSMMapTileProvider, в инспекторе объектов связать свойство TfgMap.TileProvider и компонент TfgOSMMapTileProvider.
    Универсальные пользовательские провайдеры тайлов
    Универсальные провайдеры дают большую гибкость по сравнению с готовыми провайдерами за счет того, что разработчик сам отвечает за предоставление тайлов. В библиотеке такие провайдеры  представлены компонентом TfgMapTileProvider. 
    Использование: 
    1) Прежде всего необходимо задать свойство TfgEventMapTileProvider.TileSize, которое отвечает за размер отдаваемых провайдером тайлов в пикселях.
    Внимание: Смена размера тайла после задействования провайдера приведет к сбросу кэша тайлов карты и повторной загрузке карты.
    2) Задать событие  TfgEventMapTileProvider.OnGetTile, в котором должен возвращаться графический тайл в виде интерфейса IFGXMapTile.
    Внимание: Событие  OnGetTile вызывается асинхронно из вторичных (не UI потоков). Реализация события должна быть потокобезопасной.

    Размер тайла всегда должен содержать актуальное, согласованное с реальным размером тайла значение. Если вам по какой-то причине нужно перенастроить провайдер — сначала отлинкуйте его от карты, настройте и потом прилинкуйте заново.
    Типичный пример реализации события: 
    function TFormMain.fgMapTileProvider1GetTile(Sender: TObject; const X, Y, Z: Integer; const AScale: Single): IFGXMapTile; begin Result := TfgMapTileSource.CreateFromUrl(Format('https://stamen-tiles.a.ssl.fastly.net/watercolor/%d/%d/%d.png', [Z, X, Y])); end; В примере выше используется класс-хэлпер TfgDefaultMapTile , который реализует требуемый для результата события интерфейс IFGXMapTile.
    Класс TfgDefaultMapTile содержит несколько конструкторов, каждый из которых отвечает за загрузку данных тайла тем или иным способом:
    constructor CreateFromBitmap(const ABitmap: TfgBitmap); constructor CreateFromFileName(const AFileName: string); constructor CreateFromStream(const AStream: TStream); constructor CreateFromUrl(const AUrl: string); Собственная реализация провайдеров тайлов
    Если же ни один из двух вышеперечисленных способов вам не подходит и нужен максимальный контроль над процессом — вам поможет собственная реализация провайдера тайлов и самих тайлов.
    Реализация провайдеров строится на базе двух интерфейсов IFGXMapTileProvider и IFGXMapTile.
    IFGXMapTile
    За представление тайла в библиотеке FGX Native отвечает интерфейс  IFGXMapTile. Он имеет два свойства: сырые данные, содержащие изображение тайла в любом поддерживаемом графическом формате (обычно png) и размер данных в байтах.
    IFGXMapTile = interface ['{77F3C69D-6C83-4CAB-8A8C-6ED483B28275}'] function GetData: Pointer; function GetSize: Integer; property Data: Pointer read GetData; property Size: Integer read GetSize; end; IFGXMapTileProvider
    Провайдер тайлов реализуется с помощью интерфейса IFGXMapTileProvider.
    GetTileSize - возвращает общий для всех тайлов размер тайла в пикселях.
    GetTile - возвращает тайл для указанных координат. Метод должен быть потокобезопасным.
    AddObserver, RemoveObserver — подписка на уведомления/отписка от уведомлений. Реализация должна уведомлять всех заинтересованных наблюдателей об изменении размера тайла и разрушении провайдера. 
    IFGXMapTileProvider = interface ['{AE2174DA-7362-4566-A307-6164E31635F1}'] function GetTileSize: TSize; function GetTile(const X, Y, Z: Integer; const AScale: Single): IFGXMapTile; procedure AddObserver(const AObserver: IFGXMapTileProviderObserver); procedure RemoveObserver(const AObserver: IFGXMapTileProviderObserver); end; Использование: 
    1) Реализовать интерфейс IFGXMapTileProvider.
    2) По желанию реализовать интерфейс IFGXMapTile.
    Данный тип провайдера идеально подойдет для реализации собственного кэша тайлов, оффлайн доступа к картам и тд, те там где нужна исключительная гибкость и полный контроль над процессом.
    На этом знакомство с механизмом провайдеров тайлов подходит к концу. 
    Спасибо за внимание.
  9. Viktor Akselrod
    Здравствуйте.
    В этой статье мы поговорим об отладке приложений на 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.
     
    Логирование - мощный инструмент, который может пригодиться в самых трудных и запутанных ситуациях при поиске ошибок. 
    Спасибо за внимание и удачной отладки!
     
×
×
  • Create New...