Watch, Follow, &
Connect with Us

Vsevolod Leonov

FLY IQ4412

1. Всеволод Леонов (vsevolod.leonov@embarcadero.com, http://blogs.embarcadero.com/vsevolodleonov)

2. FLY Coral IQ4412 Quad

3. Втыкание телефона в USB сразу дало позитивные результаты:

После этого на телефоне самопроизвольно появилась следующая "заставка":

Изначально выключатель "Отладка по USB" был в положении "Выкл", естественно, я его включил. Как мы помним, для разработки обычно требуется войти в "Настройки"->"Для разработчиков"->"Отладка по USB". Здесь как-бы телефон сам попросился, чтобы для него начали разработку.

Затем проверка дивайса в "Менеджере устройств" показала некую определённость, правда слабо коррелирующую с названием телефона:

4. Небольшое тестовое приложение из Delphi сразу запустилось на Fly IQ4412 - шахматная королева 3D, нарисованная в Delphi IDE при помощи примитивов TCube, TSphere, TCone и т.д.

5. В Delphi IDE (в отличие от "Менеджера устройств") рассматриваемый аппарат выглядит правильно.

6. Впечатления - хороший лёгкий удобный смартфон. Большой качественный экран. Некоторая (только по сравнению с iPhone 5) тормознутость интерфейсов. Ну чуть не так плавно. 3D графика FM выглядит чуть менее чётко, чем на iPhone/iPad, но в целом по соотношению цена/качество устройство очень привлекательно.

Posted by Vsevolod Leonov on March 28th, 2014 under Android Devices | Comment now »


Отладка мобильных приложений Delphi/C++Builder for Android с помощью CodeSite и DataSnap

В предыдущей статье мы бодро сделали:

  • сервер DataSnap – сервер приложений – «обычное» VCL-приложение, способное воспринимать команды «извне»;
  • клиент DataSnap, который вызывает нами созданный метод «удалённо» (настольная машина с запущенным DataSnap-сервером приложений должна быть «на той же сети, что и дивайс клиентского приложения», а именно:
  • Win32-сборка тонкого клиента для отладочных целей;
  • Android-приложение «тонкий клиент».

Сегодня продолжим наши упражнения – разовьём тему отладки мобильных приложений.

CodeSite Express

Данный сервис логгирования/журналирования доступен вместе с Delphi уже давно. Можно ознакомиться с его возможностями от автора (CodeRage 6 session on CodeSite by Ray Konopka), а также по краткой, но ёмкой публикации по CodeStie by Bob Swart. Сейчас мы познакомимся с ним в разрезе отладки мобильных приложений на основе сделанной нами связки DataSnap-клиент – DataSnap-сервер.

Почему это эффективно при разработке мобильных приложений:

  • мобильные приложения в процессе разработки очень хорошо тестируются/отлаживаются в виде Win32-сборки для отработки связи с базами данных, алгоритмов, бизнес-логики и всего того, что не требует реального устройства;
  • но если приложение уже «попало в лапы пользователей» на реальных устройствах, то запуск в режиме отладки достаточно трудоёмок. Здесь желательно «пустить пользователя в свободное плавание», а затем точно отслеживать, что и как он делает и к каким результатам относительно внутренних значений переменных/объектов мобильного приложения это приводит.

Модификация DataSnap-сервера - добавление CodeSite

Откроем проектную группу, созданную в рамках предыдущих упражнений. Мы помним, что DataSnap-сервер является у нас "обычным VCL-приложением", поэтому мы сейчас добавим в него возможность по использованию CodeSite и сразу же экспонируем функциональность "наружу".

На форме разместим новый компонент "кнопка". Мнемонически обзовём её "кнопка для конопки" (надеюсь, Mr. Konopka простит меня, но уж очень рифма хорошая).

Отклик на кнопку будет простой:

uses CodeSiteLogging;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CodeSite.Send('hello in CodeSite live logger');
end;

Обращаем внимание на uses CodeSiteLogging. Запускаем приложение как "приложение" (пока не думаем о мобильном клиенте). Кликаем кнопку - видим Конопку!

Помимо нашего окна возникает окно "живого оконного live логгера", где честно отображена посланная в журнал строка. Подробно о том, что и как можно "откидывать" в лог смотрим в докладе Рея или статье Боба (ссылки выше). Естественно, туда можно посылать строки, переменные, объекты, исключения + возможность категоризации посланного. Также можно посылать данные в файловый (=невидимый) лог.

Теперь мы видим, что CodeSite - некое отладочное дополнение к Delphi IDE. Очень удобно, я, например, часто использую эту возможность, чтобы удостовериться в правильном подключении/запросе к БД. Не надо ставить брейкпойнты или выводить в самопальное Memo. Дополнительное окно появляется стабильно хорошо, обладает собственными кнопочками и мега-удобно в использовании. Конечно, раньше мы обходились и Delphi IDE для отладки, но в случае с мобильностью это - отличное решение. Сейчас мы научим наш мобильный клиент "откидывать" инфу на DataSnap-сервер в цивилизованном виде.

Но посылать "отладочные строки" - это же не наш метод! Возьмём сразу быню за … рога. Мы воспользуемся:

  • возможностью DataSnap автоматически (!) посылать объекты (!) от клиента к серверу;
  • возможностью CodeSite автоматически (!) принимать пользовательские объекты (!) и визуализировать их в "живом окне логгера".

Добавим в проект сервера новый модуль (MyObjectClass.pas), куда занесём немудрящий текст:

Листинг текста не привожу по причине его тривиальности и нежелания навязывать свои вкусы в плане именования.

После чего немного переделаем отклик на кнопку:

uses CodeSiteLogging, MyObjectClass;

procedure TForm1.Button1Click(Sender: TObject);
var
  ref : TMyClass;
begin
//  CodeSite.Send('hello in CodeSite live logger');
  ref := TMyClass.Create;
  ref.A := 12;
  ref.B := 34.56;
  CodeSite.Send('local object', ref);
  ref.Free;
  //see ARM Compiler language differences
  // ... and conditional compilation
end;

Для особо эстетствующих в плане языковых кунштюков - чтим статью Марко Канту по особенностям мобильного компилятора. Как кто кому "фри" вызывает и различия в сборках Win32/ARM.

Теперь же запущенное приложение при нажатии его кнопки добавляет "объект" в окно CodeSite:

Заметьте, что "посланный в CodeSite" объект давно уже убился, но в "живом окне" он будет жить столько, сколько мы хотим на него смотреть. Снимок объекта надолго переживает своего реального брата.

Экспонирование пользовательского метода

Краткое содержание предыдущей серии:

  • заходим по мнемоническуому правилу в серверном проекте в модуль ServerMethodsUnit1.pas. Ищем класс (он там один) и добавляем наш новый метод:

Сам метод будет выглядеть так (прикалываемся от сигнатуры):

uses System.StrUtils, Unit1, CodeSiteLogging;

//...

function TServerMethods1.LogObject(Value: TObject): string;
begin
  CodeSite.Send('remote object', Value);
end;

В чём прикол? Только в том, что данный метод будет "выставлен наружу" по факту его вхождения в нужный класс нужного модуля. А может ли "внешний" метод так впрямую принимать ссыль на TObject (да ещё и реально-полиморфную)? Забудьте COM, это - DataSnap. Такие трюки здесь проходят (обратите внимание, на связках Delphi-Client/C++Builder Server и наоборот тоже).

Компилируемся, запускаем без отладки, оставляем проект запущенным. Сейчас будем бросаться в сервер объектами, созданными в клиентском приложении.

Посылка клиентского объекта DataSnap серверу

Для реализации такой схемы нужно в проект DataSnap-клиента добавить описание класса. Правой кнопкой на проекте клиента - Add… - выбираем файл MyObjectClass.pas:

Теперь данный модуль MyObjectClass.pas будет использоваться и в клиентском проекте, и в серверном:

Вот для особо придирчивых (ко мне?) нужно сделать небольшое прагрматическое отступление. Проделанное выше означает, что при создании клиентского приложения должны быть доступны исходники серверного. И наоборот. При создании серверного приложения (в нашем случае так более актуально, т.к. сервер обслуживает логгирующие потребности клиента. Но "чистоты ради" (использование данного шаблона как образца для архитектурного построения многозвенной системы) нужно заметить, что клиент знает серверную реализацию. COM-подобные механизмы как раз и вводят идею "незнания" клиента реализации сервера, а клиенту сообщается только интерфейсы объектов, лишенные реализации. Это нужно для языковой независимости реализаций клиента и сервера, а также решения ситуации, когда "старый клиент" работает с "новым сервером". В предположении, что мы полностью контролируем исходные коды проектов и клиента, и сервера данный подход выглядит вполне разумно.

Доделываем клиентское приложение до передачи объекта. Но сначала поможем клиентскому проекту узнать, что в сервере появился новый метод. Заходим в клиентский проект и… "перегенерируем клиентские исходники" - серверное приложение должно быть запущенным на исполнение, а ip-адрес должен быть валидным:

Это мы проверили "HostName" свойства "Params" компонента SQLConnection1 в ClientModuleUnit1.

Теперь делаем "перегенерацию" методов (внимание, в предыдущих версиях Delphi пункт назывался "proxy", но я полагаюсь на использование XE5):

Теперь клиент точно знает, какие методы экспонированы сервером. Для тех, кто читал курсивный текст выше. Заметьте, что не было в данном месте "передачи исходников" от серверного проекта клиентскому. Т.е. что касается штатной работы DataSnap, разделение на "декларацию" и "реализацию" соблюдается строго. А как это? Да так - DataSnap (из Delphi IDE) "выковыривает" экспонированные методы и генерит клиентский класс (Generate DataSnap client classes, как показано на картинке выше). И на картинке ниже:

Теперь можно клиентом вызывать серверный метод, передавая ссылку на TObject.

Добавляем третью кнопку:

И код вызова серверного метода:

uses ClientModuleUnit1, MyObjectClass;

//...

procedure TForm2.Button3Click(Sender: TObject);
var
  MyObject : TMyClass;
begin
  MyObject := TMyClass.Create;
  MyObject.A := 777;
  MyObject.B := 3.1415926;
  ClientModule1.ServerMethods1Client.LogObject(MyObject);
end;

Здесь я прошу не придираться к коду. Естественно, локальный объект посылать в сервер смысла большого нет (и думать про создание/уничтожение). В реальной жизни бизнес-объект (скорее всего) будет элементом коллекции, поэтому его управление его временем существование будет частью ответственности более высокоуровневого прикладного кода. Если же нам нужно передать на сервер "просто значение" отладочного характера, то используем перегруженные методы Send сервиса CodeSite.

Только что мы послали объект по ссылке TObject из клиента в сервер DataSnap, где далее мы его по ссылке же TObject пере-направили в CodeSite:

function TServerMethods1.LogObject(Value: TObject): string;
begin
  CodeSite.Send('remote object', Value);
end;

Работа "по воздуху"

Пересобранные мобильные клиенты под iOS и Android показали работоспособность:

Мобильные планшеты полностью, они легко отчуждаются от провода. И даже из другой комнаты работают (нужно бы сделать панорамную фотку).

Магия RTTI

Смотрим внимательно, где здесь волшебство.

  • Клиент передаёт объект "по ссылке типа TObject", т.е. метод LogObject может считаться универсальным для клиента.
  • Сервер получает объект "по ссылке типа TObject", т.е. метода LogObject может считаться универсальным для сервера.
  • CodeSite также получает ссылку типа TObject и работает универсально со стороны сервиса логгирования/журналирования.

Единственный "накладной расход" - чтобы RTTI была добавлена в сервер для класса передаваемого объекта, нужно выполнить инстанцирование. Объекты же не передаются "по ссылке" - так выглядит вызов метода из кода Delphi. Вместо этого объекты пакуются в JSON и передаются на сервер. Там - "распаковываются". На эту тему вспоминаем нужную лабу, а также читаем отличный блог, который ведёт Daniele Teti со статьями по сабжу. Там много интересного по части "ручной запаковки объектов в JSON и последующей распаковки".

Заключение

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

Posted by Vsevolod Leonov on March 24th, 2014 under Uncategorized, public | Comment now »


Delphi (C++Builder) Android Mobile Client DataSnap Server

Преамбула

DataSnap – платформа создания многозвенных приложений. Её история достаточно продолжительна, начиная с совсем ранних версий Delphi. Роль и значимость этой технологии/платформы изменялась в течение эволюции Delphi/C++Builder/RAD Studio, но сейчас есть ряд очевиднейших преимуществ от её использования в контексте мобильной разработки.

DataSnap подходит для создания «бэкенда» для мобильного приложения в корпоративном использовании.  Проще говоря, создав первое мобильное Android/iOS приложение, вам захочется обеспечить его «связь с внешним миром», причем не с «совсем уже внешними» сервисами (для этого, вполне вероятно, подойдёт RESTClientLibrary здесь, хотя и про C++Builder, но можно также и тут). Своя же связь (настольного) приложения для большинства «дельфистов» означает работу в режиме клиент/сервер. Для работы в режиме клиент/сервер полезным будет использование связки FireDAC + InterBase (поясняющее видео, там, правда, сначала обзор конкурса - так случайно получилось, а уже про клиент-сервер – начиная с 12-ой минуты. Там про iPhone и C++Builder, но всё работает 100% для Delphi и Android).

Внешний web-сервис REST требует наличия как-минимум такового. Можно писать самому, кто обладает достаточной компетенцией в данном вопросе. Можно пытаться делать всё «классически» через клиент-сервер. Клиент-сервер в качестве технологии передачи данных от мобильного клиента в сервер БД сразу же зажимает разработчика в определенные рамки. Прежде всего, это – занесение данных в базу посредством SQL-запроса. Но для первого приближения хочется простого, милого, доброго и доступного – нажать кнопку на мобильном приложении и увидеть «отработку» в приложении, запущенном на настольном компьютере. Давайте это и сделаем.

DataSnap сервер

Начнём с проекта, которое будет играть роль сервера приложений. Это будет крайне просто, мы создадим «обычное» VCL-приложение. Единственное, что будет отличать его от «классического» - умение «слышать» обращения клиентов извне. В Delphi и C++Builder это будет феноменально просто.

В Delphi/C++Builder подобные вещи делаются интерактивно, визуально и легко (начиная с Delphi XE, когда платформа DataSnap была уже сформирована в практически готовом виде). Мы не будем «преобразовывать» этот просто VCL-desktop проект в нечто, способное реагировать на действия мобильного приложения (хотя это можно, я покажу потом как). Мы создадим новый DataSnap Server на основе VCL Forms Application. Будучи запущенным, он сыграет роль «обычного Windows-приложения на основе VCL» с несколько расширенными функциями.

Запускаем Delphi XE5/C++Builder XE5. Выполним File->New->Other… | <узел DataSnap> DataSnap Server, как показано на картинке:

Дальше пойдут окна мастера создания DataSnap Server, далее будут «правильные» скрин-шоты с небольшими пояснениями:

Мы оставим выбор «VCL Forms Application», хотя по названию двух других пунктов можно догадаться, что они означают. Да, это будет обычным VCL-приложением, которому будут добавлены функции «прослушки» обращений и реакции на обращения мобильных клиентов.

Кнопка «Next >>» явит следующее окно:

Оставим тоже всё как есть, альтернативы с протоколом понятны, а аутентификация есть предмет отдельной работы (например, здесь, также ищете по Pawel Glowacki и DataSnap). Но впоследствии можно «нагрузить» нашу связку и системой аутентификации – изобретать «велосипед» смысла большого нет. Далее есть еще и фильтры шифрования/сжатия для воздействия на передаваемый поток байтов, но это уже потом (давний материал релизов XE-XE3). Нам нужно перейти на следующую ступень (кнопка «Next>>»):

Тестируем порт (211) на предмет незанятости – успешный тест гарантирует «соединяемость» с сервером из клиентского приложения. Нажимаем «Next>>».

Здесь выбираем пункт TDSServerModule как самую «прокаченную» опцию. Можно прибедниться за счёт двух предыдущих пунктов, дабы сэкономить, но смысла большого нет. Выбираем «Finish».

Это – нормальное, обычное приложение, ему можно даже сделать какой-то вменяемый интерфейс, т.е. получить приложение, работающее самостоятельно и самодостаточно, но умеющее также выполнять некие методы, будучи вызванными извне.

Все эти «заморочки» с созданием сервера DataSnap, живущего внутри VCL-приложения, нужны, чтобы «выставить наружу» некий функционал. Технически это выглядит как добавление некоторых «странных» модулей, помимо классических Form1.pas и Form1.dfm за счет отработки мастера DataSnap Wizard (который мы только что использовали). Сохраним всё как есть, но зададим лишь другое имя проекта – DataSnapMobileServer (таким будет и результирующий exe – DataSnapMobileServer.exe). Разбираемся подробно:

Unit1.pas, Unit1.dfm – это «классика», не нуждающаяся в пояснении. Сама IDE (Delphi XE5/C++Builder XE5) по результатам работы с DataSnap Wizard (тем самым четырёхоконным мастером) выдала нам ещё парочку сладких модулей ServerContainerUnit1 и ServerMethodsUnit1.

ServerContainerUnit1 в виде визуального контейнера нам интересен будет потом, когда мы будем развивать функционал сервера в платформенной части (жизненный цикл серверных объектов, аутентификация, фильтры шифрования/сжатия и т.д.). Модуль в этом «юните» и есть главный серверный объект. Обратите внимание (в коде), что класс серверного контейнера наследуется от TDataModule, а с ним-то мы уже умеем работать! Серверный модуль – просто некий визуальный контейнер в IDE в design-time, а также определенный объект, создаваемый в runtime. В этом модуле и конфигурируется сервер приложений за счёт добавления на него определенных компонентов. Пока у нас лишь «прожиточный минимум» в виде трёх компонентов, функционал которых приблизительно ясен из названий.

ServerMethodsUnit1 вообще не блещет визуалкой, он – «пустышка». Но именно тут нам предстоит выполнить некое кодирование. Нажмем F12, войдем в редактор кода для данного модуля и увидим класс с двумя тестовыми методами:

TServerMethods1 = class(TDSServerModule)
  private
    { Private declarations }
  public
    { Public declarations }
    function EchoString(Value: string): string;
    function ReverseString(Value: string): string;
  end;

Запомним это место, скоро мы вернёмся сюда еще раз. Мнемоническое правило по разделению модулей ServerContainerUnit и ServerMethodsUnit таково: «контейнер» для размещения компонентов, «модуль методов» - для программирования методов. Два метода EchoString и ReverseString сгенерированы автоматом как тестовые функции сервера, однако уже доступные «извне».

Перейдём к главной (и единственной) VCL-форме проекта и добавим на неё компонент TMemo:

Если мы теперь попробуем использовать данный проект, то у нас будет VCL-приложение с двумя доступными «извне» методами: EchoString и ReverseString – см. код выше.

Нашей целью является создание DataSnap сервера, способного каким-нибудь интересным образом реагировать на запросы мобильного клиента. Мы добавим наш собственный метод. Мобильное приложение на мобильном устройстве будет пулять строку по WiFi на сервер при помощи этого метода.

Вернёмся в ServerMethodUnit1, найдем методы EchoString и ReverseString, а чуть ниже допишем свой собственный метод по образу и подобию:

function LogString(Value: string): string;

Нажмём Ctrl+C, получим сгенерированную «заглушку» реализации, куда допишем свой код:

function TServerMethods1.LogString(Value: string): string;
begin
  Form1.Memo1.Lines.Add(Value);
end;

Если у вас данный код не компилируется, нажмите Alt+F11 и выберите Unit1.pas. Этот модуль попадёт в список uses, поэтому можно будет обращаться к главной форме.

Скомпилируйтесь и запустите приложение кнопкой Run Without Degugging ("зелёный треугольник без жучка"). Фишка в том, чтобы приложение запустилось «без IDE» и спокойно «висело». В смысле, вас не должно беспокоить, что вы запустили и забыли приложение. Так и надо, наш мобильный клиент будет к нему подцепляться сначала из IDE, а потом самостоятельно.

DataSnap Mobile Client

Создадим приложение-клиент, которое будет запускаться на мобильном устройстве и вызывать методы созданного и запущенного сервера.

DataSnap сервер мы делали так: сразу и приложение, и серверный объект (форма и серенькое «облачко» выше). Клиент мы будем делать в два приёма – сначала сделаем приложение, а потом «внедрим» туда клиентскую часть (зелёное «облачко» на картинке выше).

Встанем на проектную группу в «менеджере проекта», правой мышью, Add New Project:

Затем в окне проектов кликнем на FireMonkey Mobile Application, затем Blank Application:

В менеджере проектов появиться новый проект. Сохраним его, изменив лишь название самого проекта на DataSnapMobileClient. В данном проекте пока нет ничего интересного, разве что по правой мышке добавим Win32 в список TargetPlatforms:

Это - хорошая идея, делать Win32 сборку для мобильного проекта. Отладка и тестирование гораздо эффективней на таком варианте, чем ждать "деплоймента" на железку. Делайте это на Win32 для:

  • разработка и отладка алгоритмов;
  • разработка и отладка бизнес-логики;
  • разработка и отладка работы с данными (локально, клиент-сервер, DataSnap - как в нашем случае, REST - библиотека REST Client Library как и всё перечисленное работают и в "настольных" Win32-сборках) - наш вебинар с Дмитрием Кузьменко как раз и показывает такую работу.

Оставаясь же на данном проект выполним File->New->Other | <узел DataSnap> DataSnap Client Module:

Теперь к существующему мобильному приложению будет добавлен функционал для связи с уже созданным (и запущенным) сервером! Это приложение станет "клиентом" (в нём появится "зелёное облачко"). Осталось всего несколько шагов.

Выбираем Remote server, т.к. клиентское приложение будет запущено (в конце концов) на отдельном устройстве (у меня на планшете Android – Nexus 7).

Выбираем первую опцию, так как у нас именно «изолированное VCL-приложение». Но остальные опции тоже полезно прочитать и запомнить.

При изготовлении сервера мы концентрировали наше внимание на TCP/IP, логично продолжить данную традицию.

Вот тут обратите внимание, что IP-адрес (он же Host name) берётся не «с потолка», а именно тот, на котором висит WiFi вашего компьютера, где запущен DataSnap сервер (не пишите туда localhost даже в шутку, такие шутки чреваты потерями времени и нервными криками "ну где-же коннект?").

Для совсем новичков в данной теме. Компьютеры под Windows 7 способны иметь два соединения одновременно - и «по проводу», и по «вайфай». Не надо выдёргивать сетевой шнур для тестирования работы по WiFi. Не забудьте узнать ip-адрес wifi компьютера и не путайте его «с тем, что по шнурку». Самое немудрящее – консоль cmd и ipconfig. Далее, пожалуйста, подключите к одной и той же сети WiFi и данный компьютер, и мобильной устройство . В офисе бывает несколько сетей, а автор данного текста потерял 30 минут времени, т.к. мобильные устройства могут самостоятельно менять WiFi сеть. И мобила, и десктоп должны быть на одной сети. Бывает, что сеть есть, а пинга нет (ip не пробивается с устройства на устройство). Как говорится, обратитесь к системному администратору. В любом случае, кнопка Test Connection вам в помощь, а если не работает, то самое время сделать перерыв и разобраться с сетью.

На картинке выше я показал, что "повесил всё на одну сеть" и точно знаю ip-адреса устройств.

Вернёмся к проекту:

Я аккуратно позакрывал все закладки с серверными исходниками, там уже все сделано. Напоминаю, что само серверное приложение запущено и остаётся таковым. Закрывать не нужно и нельзя. На минутку сбегаем в модуль ClientClasses1. О чудо! Там показаны сгеренированные на запущенном сервере методы. Еще раз: Delphi/C++Builder IDE накинулась на запущенный сервер при создании DataSnap Client Module и воспроизвела те методы, которые сервер «выставлял наружу»:

TServerMethods1Client = class(TDSAdminClient)function EchoString(Value: string): string;
    function ReverseString(Value: string): string;
    function LogString(Value: string): string;
  end;

Не путайтесь – это не общий исходник с серверным проектом. У сервера методы и их реализации. В клиенте – лишь «заглушки» для вызова этих методов. Да – методы выглядят «одинаково», но это лишь по сигнатурам. Классы их разные, а в сервере они реализованы, а в клиенте – нет. Они просто «отсюда» вызываются. Как? А вот это уже совсем а) не наше дело б) не интересно. Все сделает умный и добрый DataSnap с его транспортом, маршаллингом и т.д.

Нам осталось сделать парочку манипуляций.

Открываем главную форму мобильного приложения, добавляем на неё 2 кнопки:

Под код каждой кнопки подписываем следущее (событие OnClick для каждой кнопки программируется отдельно – а вдруг меня читают совсем «нулёвые»?):

uses ClientModuleUnit1;procedure TForm9.Button1Click(Sender: TObject);
begin
  ClientModule1.ServerMethods1Client.LogString('button 1');
end;

procedure TForm9.Button2Click(Sender: TObject);
begin
  ClientModule1.ServerMethods1Client.LogString('button 2');
end;

Не забываем магию Alt+F11 для ClientModuleunit1.pas, что породило первую строку с uses в листинге выше.

Пуско-наладочные работы

Сильно рекомендуется не стартовать мобильную сборку, а собрать проект под Win32 (для этого мы данную платформу и добавляли).

Собираем проект под Win32 и запускаем пока на одной машине. Кликаем – наслаждаемся эффектом. Пока не впечатляет в силу того, что всё происходит на одной машине и совсем без удалённого подключения мобильного устройства.

Дело – за малым. Пересобрать проект под мобильное устройство и еще раз протестировать великолепие грамотно спроектированного и эффективно реализованного функционала.

Я "оторвал" планшет сразу после успешного запуска клиентского приложения от USB-кабеля и "чисто по воздуху" управлял серверным приложением, нажимая кнопки на мобильному устройстве.

Висящий провод символизирует оторванность планшета Nexus 7 с мобильным клиентом от ноутбука, где запущен сервер приложений. Палец символизирует потребность пользователя в работающем приложении, что есть движущая сила разработки любого ПО.

Для тех, у кого получился данный пример, домашнее задание – проработать лабы в «настольном» варианте клиента (очень полезно, поверьте). Потом опять можно продолжить эксперименты с мобильными приложениями.

Пользуясь случаем, передаю привет Владимиру Крапоткину (семинар в Тюмени), который не просто профессионал высокого уровня, но и успешный пользователь DataSnap. Мы здорово пообсуждали его проекты с использованием DataSnap, а также достоинства и недостатки асинхронного вызова клиентских heavy-weight callbacks (еще раз - сделайте  лабы) в реальной жизни. Владимир - спасибо Вам! Такие вот "астральные братья" :)

Posted by Vsevolod Leonov on March 21st, 2014 under public | 8 Comments »


Nokia X + RAD Studio

Good reading, especially for Nokia fans.

Thanks to Anil Mahadev!

Posted by Vsevolod Leonov on March 7th, 2014 under Android Devices, public | Comment now »


Поэзия кода Delphi

Был свидетелем разноуровневой дискусси на тему "можно ли языком Delphi выражать простые человеческие мысли"? Да-да, я про это: If (YouLoveVCL = true) then TReadThisNow.Create();

Небольшой эксперимент в порядке трансляции человеческого текста на машинный.

If you are true when writing code,
Then adding a TItem node,
Then sitting button, labels, texts
On mobile forms. Press "Run" and next…

You’re thinking of your Delphi app
You’re doing right things, and no crap.
Embarcadero’s friend indeed
With RAD you’ll never be in need.

Android, Mac, and Windows 8
You feel no pain, you feel no hate
Devices… you can take them now
"You can", not "I don’t know how"

Create, design, compile, install
Extend your users’ list, and all
The problems will be sent away.
Be multi-platform every day!

  if you.Coding = true then
  begin
      NewItem := ListView1.Items.Add;
      MyButton := TButton.Create(self); // MobileForm
      MyButton.Parent := self; // MobileForm
      MyLabel := TLabel.Create(self); // MobileForm
      MyLabel.Parent := self; // MobileForm
  end;

  try
    You.Run;
    NewProject := TMobileProject.Create;
    if you.ThinkOf(NewProject) = true then
        You.AreDoing := DeveloperResult.RightThings;
  except
    you.correct;
  end;

  if Embarcadero.IsFriendOf(you) then
    You.Status := not NO_MONEY;

  MyPlatforms.Append;
  MyPlatforms.FieldByName('platform_name').Value := 'Android';
  MyPlatforms.Post;
  MyPlatforms.Append;
  MyPlatforms.FieldByName('platform_name').Value := 'Mac';
  MyPlatforms.Post;
  MyPlatforms.Append;
  MyPlatforms.FieldByName('platform_name').Value := 'Windows';
  MyPlatforms.FieldByName('platform_version').Value := '8';
  MyPlatforms.Post;

  if (noPain = true) and (noHate = true) then
  begin
    Targets := Targets + [tgAll];
  end;

  you.CreateProject;
  you.DesignGUI;
  you.CompileCode;
  you.Install;

  MyProductivity.SQl.Add('delete from problems');
  MyProductivity.ExecSQL;
  MyApps.SQL.Add('select * from platfroms where supported = true');
  MyApps.Open;

  while true do
  begin
     you.Develop(MultiPlatform);
     you.Sleep(28800);
  end;
Posted by Vsevolod Leonov on March 6th, 2014 under public | 6 Comments »


Changhong HonPhone W21

1. Александр, www.delphi-dev.ru

2. Changhong HonPhone W21

3. После подключения устройства к компьютеру естественно оно ни как не определилось. Погуглив, нашёл подходящий драйвер и устройство пусть и не правдиво, но все же определилось.

4. Попробовал запускать на нем различные примеры, вроде все работает. Сфотографировать не удалось, поэтому прикладываю скриншот с приложения DeviceInfo из примеров поставляемых с Delphi XE5.

5. В Delphi XE5 устройство определилось более правдиво:

6. Авторское описание здесь.

Posted by Vsevolod Leonov on March 6th, 2014 under Android Devices | Comment now »


Texet TM-7026

1. Владимир Тимофеев, rusdelphi.com

2. Texet TM-7026 (2012)

3. На официальном сайте драйверов для подключения не нашел.Найти его можно здесь

После установки в системе(Windows7 x64) устройство определяется вот так:

Планшеты Texet с завода идут рутоваными, что немного облегчает жизнь разработчикам.

4. А вот как он выглядит в жизни:

5. Вот как он выглядит в IDE:

6. Авторская публикация здесь.

Posted by Vsevolod Leonov on March 6th, 2014 under Android Devices | 1 Comment »


Новая книга по Delphi - вышла!

У нас большая радость, вышла книга про Delphi, посвященная кроссплатформенной разработке.

На фотографии Игорь Шишигин, зам. Главного редактора издательства БХВ-Петербург.

В ближайшее время опубликую разговор с автором - Дмитрием Осиповым, если согласится.

Спасибо издательству БХВ-Петербург и лично Игорю Шишигину за веру в популярность наших продуктов. Игорь тоже "из дельфистов", что вдвойне приятно.

Спасибо Дмитрию Осипову за целенаправленную и планомерную работу по популяризацию Delphi.

Кстати, предыдущая книга Delphi XE2 разошлась всем тиражом, последний авторский экземпляр пришлось отдать одной амбициозной команде. Так что новая - весьма ко времени!

Posted by Vsevolod Leonov on February 28th, 2014 under Uncategorized | 12 Comments »


Май код рейдж презентейшн (my CodeRage presentation)

Стартует онлайн-конференция CodeRage 8 для любителей программирования в стиле C++. Особой церемонии открытия не будет, сразу начнутся "игры". Список выступлений интеллектуальных спортсменов объявлен. Будет небольшая церемония открытия:

Вставать рано не надо (для внимательных), для нас это уже будет пост-рабочий вечер.

Я собираюсь совместно с Дмитрием Кузьменко (тонким ценителем изящных форм, выраженных в аппаратной мобильности) провести несколько эклеткичную сессию (Technical Session #14). Поскольку времени на быстрое изложение результатов конкурса в системном виде формата блога пока нет (есть только фрагментарные чествования), то я сделаю спец-блиц-шорт обзор некоторых проектов. Да, они сделаны на Delphi и для Android, но эта формула работает:

Delphi + Android = C++Builder + iOS

т.к. платформа-то одна!

В ходе конкурса выяснилось, что очень многие участники хотели бы, но не использовали пока технологию работы с данными на мобильных устройствах.Вторая часть презентации посвящена (и тут как раз Дмитрий внёс свой неоценимый вклад) рассмотрению правильных действий по оснащению мобильного приложения базой данных. В контексте enterprise mobility. материал универсальный, подходит и для Delphi. Использовали FireDAC.

Одна тонкость, конференция будет на английском языке, но мой "лет ми спик фром май харт" будет понятен всем.

Что послушать: рекомендую как минимум "сходить" на Fast Reports (Technical Session #13) с Денисом Зубовым, послушать Jim Tierney (Technical Session #7), так сказать, освежить восприятие Live Bindings. Также всегда великолепен Ray Konopka (Technical Session #20). Очень уважительное отношение у меня к Robert Love (Technical Session #3) - для закоренелых VCL-щиков. DataSnap для многих покажется более "добрым" после Marco Cantu (Technical Session #17) и Pawel Glowacki (Technical Session#19). REST ClientLibary доверили Jim McKeeth (Technical Session #11) - технология в надёжных руках!

Также стал весьма популярным жанр "рассказать о своих свершениях миру" - Brett Whittacre & Jared Johnson на тему "Ядерная медицина и молекулярка средствами C++Builder" (Technical Session #15).

Всем участникам - слушателям CodeRage 8 C++ - скидка в 10%на покупку средств разработки C++Builder XE5 и RAD Studio XE5 с 25 февраля до 14 марта 2014 г!

Posted by Vsevolod Leonov on February 25th, 2014 under CodeRage, Uncategorized, public | Comment now »


TapTap - Delphi for Android 2013 contest review (in GooglePlay)

TapTap - a winner of Delphi for Android 2013 contest. The project was a favorite at the beginning, as it represented a complete application, made with humor and the source codes were interesting to look at from the viewpoint of "design". The author - Nikolay Zverev - is a typical desktop-to-mobile developer, primerily mastering his enterprise-scale RDBMS-based application developer skills for years. Personally I liked the project the best as Delphi evangelist, while the other guys were in the contest jury.

TapTap sourcesready apk for TapTap (rus/eng GUI), exe buit for Win32.

TapTap app on GooglePlay

The author’s description (rus): part 1, part 2, part 3, part 4, part 5 (with sources, direct link above)

How to submit the Delphi app to GooglePlay (rus).

Little interview with the winner to give more light to the project design, coding and components in use.

1. Nikolay, let me congratulate you with your win. Separate thanks for detailed description in your blog and shared source codes. Did you experience some difficulties when starting a new FM project?

Thanks :)

Yes, I did experience some difficulties, but more precisely say "non-VCL-logical behavior" from my viewpoint of desktop developer.

I really miss "Caption" property for TButton and TLabel ("Text" is also ok, but not so habitual). For me the properties Left and Top are joint in one property "position", while Width and Height are not combined (in something like "Size"). But FM is not VCL and tastes differ, of course.

I cant say my project is so complicated. Form-factor independency was my initial goal, so I designed my GUI. I had no mobile development experience, so did it my way :).

2. Could you please make a short review of your project for those, who have the same zero-experience (you don’t already). Have you split GUI and logic into some different units?

The design is very simple: we have a main form, main and single, all the stuff is arranged in frames. Of course, many variants were possible, but I did my experiment. Frames are not linked somehow directly, they communicate via main form instance. The frames are:

  • Animated guy - some robot-Android, made from primitives in design-time and animation, triggered in runtime. The guy doesn’t know what is he about and has not links to the code. He lives his own life.
  • Game area. The main logic is there, while it is only a pair of methods. The area consists of N-characters, fires their animation, checks the game is done.
  • Menu - set of buttons "Play", "Settings", "Help", "Credits". Any button fires the methods of the main form.
  • Panel with high scores.
  • Settings.
  • Intro/Titles.

3. Is this design the same for your desktop projects or did you invented this particular for mobile app?

My desktop Delphi projects are DBMS oriented, so have nothing similar with this mobile project. But if I start similar small game project with VCL, I’d use the same approach.

4. You used frames. We have new Delphi users, who start their projects with Delphi for the first time. Please, explain, why the use of frames is a good practice?

Of course, one can do applications in Delphi without frames. But with frames the development is simpler and more convenient.

In my project the frame for the guy (character) was absolutely effective. The other frames were not so necessary.

Let me explain, why frames are good. Everybody knows, that code duplication is a bad practice. You should isolate code in a special unit to prevent doubling. The same is true for design! You sit components on the form and form-design-text is automatically generated, and you should care about not-duplicating it. It’s as bad, as code duplication. Use frames if you feel your design-"code" can be potentially duplicated. It happens when some parts of the design can be used in different part of the project.

Frames are pieces of GUI. You can first build up pieces of GUI as frames, and then use them as design-units to construct the complete picture. And it’s easy to manipulate with frames (pieces), rather than all-on-the-form.

5. Possibly, many developers will want to start from reviewing you project as a good beginning. How should one start analyzing your project?

There are always two approaches. Frist, from general to details, and, second, from details to the general idea. In my blog I’m describing step-by-step from the details. So now I’m describing "in direct order".

  • Open drp-file. See Project Manager and open "View Source" from Popup menu (right click).
    Here one can see the declaration of the units in the project. The main form is there.
  • The main form - frMain. All starts happening from FormShow even, settings are loaded, Intro is fired (see fraHello frame). Then all the objects are created (CreateMenuAndDesk). OnResize event arrange the objects (orientation does play a role).
  • fraMenu - the menu, the main form methods are called.
  • fraScore - time is counted, the frame contains methods, that are called from outside. StartNewGame, StopGame, Pause/Resume. RegClick to record clicks, RegWin to fix the win.
  • fraOptions - as simple as that.
  • fraHelp - the same trivial things.
  • fraDesk - is the constructor of characters. It changes their states, fires the anmiations. FRobots is an array for the characters created, FRobotsToToggle are characters, who are in process of animated changing their states. FHelloRobot is a character, which "gestures hello".
  • fraDroid - is the character itself. Be careful, some "dirty" code is still there.
  • uNPC - is a "basic" frame, it keeps design-time sizes of the objects-frames and calculates ScaleFactor. Primarily it was constructed as a base frame for characters, then it fitted as a parent for all the frames in the project.
  • uAni - is my attempt to optimize animation technology. The idea is instead of creating N objects of TFloatAnimation, I create the only TFloatAnimation instance, which controls all the process by calling the necessary methods. The names of these methods start from PA prefix.

6. A beginner takes your project and wants to use it as a prototype for his/her own game, if you don’t mind. What can be used and what should be re-make from scratch?

Of course, I don’t mind. Otherwise I won’t share the sources.

uAni, uNPC (I’d better name it uBaseFrame), fraDroid (derived from uNPC) are quite universal. I don’t feel like advising, it depends. And my experience is not enough to give advices.

7. What do you plan as the development of the project?

I was thinking of adding more animations, sound, a pair of new characters (with Windows or Apple logos). More levels. But now the mission is accomplished, the app is quite playable. The game is small, the plot is simple. I don’t think I can draw much attention by developing it further.

At the same time it’s not some "odd job". This is my first game, my first serious experience in mobile development. It’s really in my memory forever.

Preparing for Google Play

Final building the project

Future (by Seva):

I’m waiting for blog post on how the game runs on a new prize device (Nexus 4).

I’m waiting for short report (volunteer) on primary device Nikolay used to test his app.

I’ll migrate the project on iOS, many contest guys did this successfully, as Delphi is a relly mobile cross-platfrom dev tool.

Posted by Vsevolod Leonov on February 17th, 2014 under Delphi for Android 2013 contest, public | 1 Comment »




Server Response from: BLOGS2