понедельник, 31 марта 2014 г.

Как жить с таким TNumberBox?

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


Сначала обсудим, что в нём вкусного. Во-первых, он нацелен на цифровую виртуальную клавиатуру. Это хорошо. А то ужас как неудобно устанавливать KeyboardType в vktNumberPad. Шучу, конечно. Но ведь в самом деле, вряд ли только из-за этого нужен дополнительный контрол. Поэтому смотрим, что там во-вторых.

Во вторых, он обрабатывает вертикальный и горизонтальный жесты, позволяя менять численное значение без ввода цифр. Да и мышь в Windows (и, наверно, на Mac ) тоже прекрасно работает. Причём мы можем отдельно регулировать скорость приращения по вертикали и по горизонтали! Допустим, вдоль длинной горизонтали меняется целая часть числа, а вдоль короткой вертикали - десятые доли. Такого поведения в VCL не было!

В третьих, ЧисловойКоробок способен форматировать ввод и обеспечивать валидный (от франц. valide - законный, действующий) результат ввода в виде численного значения Value. Для форматирования и валидации у нас есть количество точек после запятой и диапазон значений Min и Max. Вот это уже кажется настоящим делом для нового контрола.


А теперь рассмотрим некоторые сложности. Обратите внимание - Min и Max = 0..100. Вас устроит такое ограничение? А если вообще ограничения не нужны, если нужен диапазон "по-максимуму"? Установка 0..0 по моей логике должна бы отменить всякие ограничения, но - нет. Стоит отвернуться, отвлечься и нажать даже не другой контрол, а всего лишь какую-нибудь "не такую" клавишу, как значение в поле редактирования сбрасывается в 0. Вот беда! Да ладно, не беда! - скажем мы, посмотрим в справкепосмотрим в справке ещё и найдём диапазон Single = 1.5e-45..3.4e+38 и ... Увы, Object Inspector не понимает таких значений. Я лично оставляю -1E38..1E38. Если переборщить, то мы даже можем увидеть нехорошее слово из трёх букв - INF (я думаю, что это Infinity - бесконечность). Нехороши эти буквы потому, что вместо обещания Infinity они не только не дадут нам диапазон -∞↔+∞, но и не дадут запустить программу, и, что особенно неприятно, не дадут загрузить  в следующий раз саму форму, если нечаянно записать её с этими буквами вместо цифр. Придётся открывать <unit>.FMX в текстовом редакторе и менять буквы на на 0. При этом не помешает соблюдать осторожность, чтобы не споткнуться о какой-нибудь [Inf]o или Ma[inF]orm.

Теперь жесты. Казалось бы - вот здорово! А оказалось - а вот и не очень. Если поле ввода перекрывается всплывающей клавиатурой, то что надо сделать с полем? Да, мы его двигаем вверх, да ещё и, как real programmers, с анимацией. А пока мы двигаем поле, NumberBox отслеживает точку нажатия относительно своих границ. Т.е. он думает, что это не он перемещается, а что это мы двигаем пальцем! Он меняет значение, хотя палец просто ткнулся и стоит там, где только что было поле ввода. Мне кажется, что когда программа вдруг меняет значение, которое должен менять лично сам пользователь, то это доверия пользователя к программе совсем не добавляет. Это какая-то ерунда. Но тогда, может, ну их - жесты эти - к лешему? Мы как-то и без них раньше обходились. Верно? К чему тут виски напрягать да копья ломать? Возьмём просто и отключим их! Это же кажется легче лёгкого - достаточно установить HorizontalIncrement и/или VerticalIncrement в 0. Но увы и снова увы - после запуска (!) приложения мы обнаруживаем, в VerticalIncrement что 0 заменяется дефолтным 5! Когда я столкнулся с этим мне почему-то вспомнилось классическое "Братья и сёстры! Это ли не чудо?!" Я пробовал организовать чудоборство запоминанием в TagString текста контрола перед каждым FloatAnimation1.Start и, соответственно, восстановлением на OnFinish анимации. Но - увы, ничего хорошего не получилось. Кстати, что мешало сделать TAnimation.OnStart? Если кто знает как уведомить EMBT о целесообразности этого события, напишите, пожалуйста.

И форматирование ввода - тоже не слишком похоже на ожидаемое. Когда при значении 0 вводится какая-то цифра, то вводится следующая цифра! Что это за число такое "008,9" или "+00"? Что это за левые (во всех смыслах) нолики? Может, это мода такая новая? Мне  лично эта мода кажется ругательной, и я прошу её ко мне не применять! Поэтому я вешаюсь на ChangeTracking и режу первый символ, если он 0 и при этом второй - цифра (минус бы тоже учесть можно, но это уже для гурманов). Такую ерунду подвешивать к каждому полю - это разве дело? Но иначе я на поле ввода числа смотреть не могу. Чес-сло, я уже с теплом начинаю вспоминать TMaskEdit. И ещё вопрос у меня - а кому там нужен плюсик? Ведь любое ненулевое число без минуса - уже плюс! Просветите меня, если можете. Мне кажется, я какой-то малопрозрачный.

А как апофеоз моих исследований - свойство Value. Я-то думал, что стоит ValueType установить в vtFloat, так сразу буду получать введённое пользователем значение типа Single. Ну да, кто-то кое-где у нас порой этого не хочет, ему подавай Int64, а Value - только Single. Но это уже не так важно, как то, что не получится получить значение "сразу". Я имею в виду, что если по какой-то причине вы захотите получить значение Value сразу, как только пользователь нажмёт Enter (Ну и что же тут криминального, если в OnKeyDown установить if Key = vkReturn then AddValue?), то скорее всего в Value будет что-то такое, что напоминает число в свойстве Text очень и очень отдалённо. Вешаться же на OnChange для того, чтобы отследить нажатие Enter на виртуальной клавиатуре я вам не советую - оно срабатывает совсем не только на Enter и совсем не всегда на Enter. Слава Богу, что он вдохновил программиста (или его начальника) вынести в интерфейс модуля FMX.Edit процедуру TryTextToValue, которую я использую сам, и рекомендую вам. Она запускает старый (как время летит!) добрый TryStrToFloat, которому входная строка причёсывается по пробелам и десятичному сепаратору. В случае неудачи возвращается дефолтное значение. Вот спасибо!

Эпилог

TNumberBox, не смотря на далеко не первую версию платформы FM,  выглядит довольно сыро. Возможно, это связано с небольшим опытом его применения программистами. Возможно,  это связано с небольшим количеством обращений программистов в qc.embarcadero.com. Я лично (это моя стандартная отговорка) плохо формулирую свои мысли даже на русском. А то, что получилось сложить - слишком многословно, чтобы внятно перевести на английский. Если вы чувствуете в себе силы написать о проблемах этого контрола в EMBT, то прошу вас, напишите. Если вы можете что-то подсказать мне по применению этого контрола - тоже пишите.

Спасибо за внимание!
Всем всего доброго!

ЗЫ: Спустя некоторое время я стал использовать специальную заглушку-перехватчик, чтобы обойти основные проблемы контрола. http://alhymov.blogspot.ru/2014/04/tnumberbox.html

вторник, 11 февраля 2014 г.

Помоги зоопарку. Samsung GALAXY Note 10.1,Fly IQ440 Energie,МТС 970H,Samsung Galaxy S III GT-I9300

Широко известный в наших кругах Всеводод Леонов обратился к общественности с манифестом Спаси Delphi, помоги зоопарку! Я уже писал ранее про Nexus 4. В ответ на призыв я отправил ему несколько заметок, некоторые из которых он опубликовал. Также Всеволод мне написал, что ничего плохого не случится, если я помещу свои заметки в своём блоге. Так красиво оформлять заметки, как он, я ленюсь, но думаю, что больших неудобств Читателю это не доставит.  Итак:

Samsung GALAXY Note 10.1 (http://www.samsung.com/ru/consumer/mobile-devices/tablet-pc-slate-pc/samsung-galaxy-note/GT-N8000EAASER-gallery)


Android 4.1.2. Купил в позапрошлом году  планшет супруге на ДР. Обошёлся с картой памяти примерно в 25 килорубля + чехол. Колебался - iPad или Android? Выбрал по цифрам самый мощный Андроид. Яблоки мне казались снобизмом, пугали я-мелодии, отсутствие поддержки Flash, отсутствие SD-карточки, платность всего-привсего, странность поведения поклонников торговой марки. 

После приобретения был неприятно поражён стоимостью чехлов и непродуманностью их конструкций. Оказалось, что планшет не поддерживает Flash! К тому же ещё и кабель имеет проприетарный разъём. Кнопки по периметру расположены неудачно - легко случайно выключить, взяв устройство за угол. По сравнению с яблоком - тяжёл, экран проигрывает в качестве. Гориллное стекло в женской сумке без чехла быстро получило заметную царапину от ключей. Рекламируемый стилус терялся пару раз и в настоящее время сидит в своём гнезде и практически не используется. Детям купил уже яблочные дощечки.


Аппарат был подключен к Win7 и сразу оснащён ПО Kies от производителя ещё до установки Делфи. Когда настала пора - сразу стал в работу. Но! При переходе на другой комп(Win8) работать с отладчиком отказался. Кто виноват? - Делфи? Win8? USB3? Оказалось, что если поставить Kies, то и тут всё работает - кто бы мог подумать?!


Fly IQ440 Energie (http://www.fly-phone.com/devices/smartphones/iq440_energie/?sphrase_id=56721)


Андроид 4.0.4. Это мой первый смартфон. Я посмотрел, как люди постоянно держат на верёвке свои аппараты, и решил взять повышенной ёмкости. К тому же, для меня было важно иметь 2 симки. Удалось уложиться в 10 килорублей вместе с картой на 32 Гига.


Аппарат действительно может целый день активно использоваться. Неактивно может легко провести выходные. Весьма тяжёл. Скоростью не балует. Фронтальная камера так плоха, что в помещении трудно считать штрих- или QR-код. Разъём под провод сбоку мешает разместить аппарат в моём автомобильном держателе. Плюс (точнее - минус) разъём довольно скоро хрустнул, и теперь провод слегка люфтит, что несколько тревожит, но пока не привело к каким-то проблемам. Большая проблема - подобрать гарнитуру: многие "пробки" шумят, тикают и стучат при прослушивании, а прилагаемые в комплекте свои - без резинок, в ушах не держаться.

Сначала аппарат был не виден, и я не знал почему - это был мой первый опыт с телефоном. У меня тогда оказался ещё другой аппарат (планшет жены), для которого я стал компилить программу, а потом просто заливал приложение на Fly и запускал. С Делфи телефон заработал через пару недель ВНЕЗАПНО! По ощущениям :) дело в том, что приходили люди с HTC-аппаратом и проставили свой софт. Увы, ничего подробнее сказать не могу - теперь Муха прекрасно себя чувствует и на Win7, и на Win8.


МТС 970H (http://www.shop.mts.ru/smartfony/mts/smartfon-970-black-dlya-raboty-v-seti-mts.html)


Андроид 4.1.1. Куплен ребёнку задёшево - меньше 3 килорублей. Вполне себя оправдывает. Народ интересуется - чё так дёшево? Глючный? Тормозной? Ни разу глюков и тормозов. Очень лёгкая машинка как по весу, так и по отзывчивости. По-шустрее моей энергичной мухи iq440, да и легче раза в два.

Дешевизна сказывается на экране - инерционность и узкий угол обзора. Не слишком приятно листать списки и смотреть фотки, особенно после iPad Air. Но, скажем, в Cut the Rope играть вполне можно. А небольшой размер - даже плюс для людей с пальцами менее 5":)


Сначала был не виден, и я уже знал почему - нужен драйвер. Почти первая ссылка в поисковике отправила меня на известный форум, а оттуда я попал на сайт настоящих производителей аппарата - alcatel(http://www.alcatelonetouch.com/global-en/support/faq/usbdriver.html), где, как рекомендовали на форуме, скачал именно ВТОРОЙ драйвер, и все заработало. В общем - всё оказалось довольно легко и быстро. :)

Samsung Galaxy S III GT-I9300 (http://www.samsung.com/ru/consumer/mobile-devices/smart-phones/samsung-galaxy/GT-I9300RWDSER-gallery)


Аппарат не мой, в руках почти не держал, подробностей не скажу. Но запускает мою программу давно и исправно. Мне дали воткнуть шнурок чисто из любопытства - посмотреть, как выглядит отладка в Делфи на Андроиде.

При первом подключении в Делфи был не виден, хотя в диспетчере задач висел как вполне хорошее и нормальное "переносное устройство" GT-I9300. После включения на аппарате режима отладки (да, это тоже камлание - настройки, о телефоне, 10 раз ткнуть в номерок версии, вернуться, зайти в таинственно появившееся программисткое меню, включить отладку) появилось неопределённое Composite Device( Вин8 выдала банер "Составное устройство"). 


Яндекс массово советовал поставить ПО от изготовителя - Kies. Но я уже знаком с этим обеспечением и не хотел его излишней заботы. Поэтому выбрал на (уж не знаю, реклама ли это) сайте http://www.sidenxab.ru USB Android Драйвер. Как только диспетчер устройств снова увидел GT-I9300, Делфи также смогла с ним работать.

Вывод.


Я хочу, чтобы начинающие Андроид-программисты поняли, что "проблема подключения Андроид к Делфи" или "Делфи к Андроид" - не проблема Делфи, а проблема драйверов Windows. Тот, кто впервые сталкивается с этим в Делфи, винит в первую очередь Делфи, также как, например, в своё время винил я. Но на самом деле, если посмотреть вокруг, видно, что эта проблема встречается У ВСЕХ систем разработки, а не конкретно у Делфи. Так что некоторые трудности с андроидными устройствами - это, как говорит Елена Малышева, НОРМА. И не надо расстраиваться, просто надо понимать ситуацию, и знать, куда копать. А копать-то на самом деле особо глубоко - и не нужно. Просто Диспетчер Устройств, просто Драйвер.

Всем удачи!!!

воскресенье, 9 февраля 2014 г.

TestFlightApp - рекомендую

Как раздавать свои мелкие утилитарные йОс-ные(а между прочим, об Андроиде здесь тоже речь будет) приложения? Есть (я буду по-колхозному писать) АпСторе, есть Дебагинг со шнурком, и есть ещё один странный штук - АдХук. 

Первый вариант для нас - не вариант. Это только "продукт" можно в магазин отдать и ждать полмесяца пока его на полку выложат. А могут и не выложить хотя бы потому, что у Яблончан ВНЕЗАПНО изменились какие-то взгляды на жизнь. Програмульку, которую дать попробовать и быстро отзыв получить для дальнейшей модификации, с таким выходом на исполняющие устройства - не сделать никак. 

Отладкой по шнурку тоже не сильно далеко разбежишься. Это надо брать устройство, отвлекать человека, смотреть его фотки, которые в айТюнз при подключении очень хотят выскочить и резервно скопироваться - жутко невежливо. Никто не любит, когда его почти(да можно и без "почти") интимную вещь подключают к чужому компу, когда какой-то электрический провод втыкают в  это милое родное существо, и какой-то хаккер-багописатель пытается туда внедрить свою колхозную самоделку, да ещё и неизвестно, сколько времени это займёт. А надо учесть, что люди с надкусанными яблоками ещё и очень заняты всегда на разных очень важных совещаниях в самых разных местах нашей необъятной Родины(да что там, Планеты!). Короче - всё плохо.

АдХук - вот спасение! Надо взять с устройства идентификатор, сформировать провижинг(кто не знает перевод - я не виноват), выслать программу на устройство, там перенести в айТюнз, и установить. Хм.. - тоже как-то, уже начиная с " взять идентификатор", не очень чтобы просто...

Что же делать? А вот - прошу обратить внимание на чудо-сайт "TestFlightApp.com" - превосходное решение для мелкоштучных поделий! Вы регистрируетесь сами, просите зарегистрироваться своих тестеров, шлёте им приглашения, и когда они принимают эти приглашения, то вам - о, чудо! - безо всяких подключений к посторонним компам сразу приходят идентификаторы тестовых устройств. Осталось только заполнить провижинг на Developer.Apple.Com, чтобы скомпилить-подписать новым провижингом приложение и загрузить свежеиспечённый билд на этот замечательный сайт TestFlightApp. Нет, ещё не совсем всё. Ещё вы на сайте должны отметить, кому дать разрешение на публикуемое приложение. При этом можно попросить сайт отправить тестерам уведомление. Очень удобно.

А как это выглядит со стороны пользователя? Ему приходит от нас письмо с просьбой подтвердить участие в нашем проекте. Он регистрируется, и на столе его устройства появляется значок TestFlight. Это ссылка на сайт,  где можно посмотреть список доступных приложений с описанием. Нетерпеливый пользователь может сам следить за новостями, периодически заглядывая в TestFlight, а нормальные люди просто получают письма счастья от разработчика. И - чудо из чудес! - совсем как в АпСторе - на столе,  стоит только немного подождать пока пройдёт загрузка,  появляется иконка нашего(вашего) приложения. И всё - вперёд и с песней!

Ура! Никаких проводов и ограничений по времени или местности! Это ли не чудо?!

Разумеется, TestFlightApp предлагает дополнительные функции, связанные с тестированием приложений. Но это уже мелочи по сравнению с тем, что мы уже получили.

Теперь пару слов о том, каковы особенности переустановки йОс-приложения через TestFlight. Я слышал жалобы, что при переустановке все накопленные данные, изменения - всё пропадает. Если с Андроидом проблем больших нет - надо просто все изменения класть во внешнее место, то Яблочная песочница нас файловой системой не сильно балует. А как установить приложение через айТюнз, если оно уже стоит? Надо старое удалить. И если что-то совсем специальное не придумать, то всякие данные (настройки, например) - тю-тю. Так вот - TestFlight пишет новую версию программы поверх старой, не затрагивая те файлы, которые получились в результате прикладной деятельности! Т.е. все изменения и дополнения пользователя сохраняются! Здорово?

Будьте осторожны. Делфи-приложение при запуске начинает выделять из себя в песочницу файлы, которые нужны ему в работе. При этом если файл уже существует, то он не будет перезаписан. И вот представьте, что вы положили в деплоймент не просто новую картинку, а  изменённую картинку. Что будет? Да, изменений на устройстве вы не увидите - новая картинка не будет выгружена из пакета приложения. Имейте это в виду. Praemonitus praemunitus!

Итак, желаю всем, кто ещё не изведал прелестей TestFlight,  приятного знакомства!

И, кстати, Андроид-приложения также могут участвовать в процессе тестирования под опекой TestFlightApp.

пятница, 7 февраля 2014 г.

DropBox против файлов

Есть у меня утилитка DeployFolder (http://alhymov.blogspot.ru/2013/12/deployfolder.html), которая текстовый файл меняет. Файл - проект Делфи. Т.е. XML, но без заголовка. И как этот заголовок отрезать, я не знаю (может, кто надоумит?). Поэтому тупо взял, записанный на диск XML всосал в TStringList, ну и, после удаления верхней строки, записал обратно.

Сначала всё было хорошо, а потом - как-то не очень: ругань пошла о занятом файле. Я, поскольку утилитка-то из Дельфи-студии запускается, решил, что Дельфи его как-то блокирует. Причём маленькие проекты - ОК, а большие - плохо. Тогда я стал проект в Дельфи ручками закрывать перед запуском утилиты, и как-бы стало работать. А потом прошло время, и - опять 25!

Ну, понял я - дело не в Делфи. Наверно, в Винде дело - она не успевает от предыдущей записи отблокироваться. Бред, конечно, но мозгный натиск не сразу Измаил берёт.

И вот я так думал-думал, и - придумал! Т.е. догадался! Проект, который "блокируется" - лежит в DropBox-е, и я его там и пользую. А если посмотреть в проводник, то в окошке этом очень хорошо видно, что на файликах значки меняются - DropBox апдэйтит файлы. А когда DropBox апдэйтит файлы, то что? - правильно! - файл блокируется от внешних посягательств.

Э! - сказали мы с Петром Ивановичем (Это я так раздваиваю свою личность иногда) - так надо же самому первому блокировку положить! Но как вспомнишь про Win32 API, так что-то хочется ещё немного подумать.

Решил я мысль свою в блоге отразить, и по ходу изложения (слава блогу!) догадался, что глупый я, однако, совсем! Зачем же я на диск пишу, и потом тут же считываю, если можно в памятный поток всё сложить, и к диску обращаться только однажды!

Вот сколько буковок из себя выдавил. А смысл - избаловали нас ПК, а не всё, что прокатывает в нормальных условиях, прокатывает в распределённой системе, в DropBox-е. Т.е. польза от буковок должна быть. А мыслеметания бредовые свои я здесь изложил, чтобы читатель понял, что он-то гораздо умнее, и было бы ему от этого очень приятно мои буковки читать. Т.е. полезное с приятным. Так, мне кажется, в мире будет больше счастья и радости.

Итого. Было:

    XMLDocument1.SaveToFile( XMLDocument1.FileName );
    XMLDocument1.Active := False;
 
    ShowStatus( 'Set standard header' ) ;
    with TStringList.Create do
    try
      LoadFromFile( XMLDocument1.FileName );
      Delete( 0 );
      SaveToFile( XMLDocument1.FileName );
    finally Free;
    end;
 
Стало:

    Memory := TMemoryStream.Create;
    try
  //    XMLDocument1.SaveToFile( XMLDocument1.FileName );
      XMLDocument1.SaveToStream( Memory );
      XMLDocument1.Active := False;
 
      ShowStatus( 'Set standard header' ) ;
      with TStringList.Create do
      try
//        LoadFromFile( XMLDocument1.FileName );
        Memory.Position := 0;
        LoadFromStream( Memory );
        Delete( 0 );
        SaveToFile( XMLDocument1.FileName );
      finally Free;
      end;
    finally FreeAndNil( Memory );
    end;
 
Жизнь покажет, будет ли теперешнее отсутствие ошибок постоянным. А читателя благодарю за внимание и надеюсь, что грабли сии минуют его, а сам я буду впредь рачительнее использовать вычислительные ресурсы.

суббота, 18 января 2014 г.

Как DelphiFeeds.RU ловит статьи с блогов?

Это вторая статья по одной теме. Предыдущая здесь: http://alhymov.blogspot.ru/2014/01/delphifeeds.html

Итак, делаем вторую статью. На этот раз - с заголовком. Если лента формируется действительно " в режиме реального времени", то я тут же увижу заголовок "Как DelphiFeeds.RU ловит статьи с блогов?" на DelphiFeeds.

Смотрим?
У меня закралось подозрение, что DelphiFeeds.RU не вполне корректно ловит статьи с блогов. А именно - если в моём блоге я забуду указать заголовок, то статья не будет опубликована на сайте DelphiFeeds.RU.

Проверим. Сейчас я сделал первую публикацию - без заголовка. А потом сделаю вторую - с заголовком. Ожидается, что будет опубликована только вторая.

Объясню, почему две статьи, а не 12. Я писал в форму обратной связи на сайте, что одна моя статья не публикуется. Вот текст:

> Это сообщение было отправлено через раздел Контакты сайта http://delphifeeds.ru/:
> Павел <alhymov@mail.ru>
> Всех благ!
http://alhymov.blogspot.ru/2013/12/deployfolder.html
> пятница, 27 декабря 2013 г.
> DeployFolder - Развёртывание мобильного подкаталога
> Предыдущие и последующие статьи в моей категории у вас есть, этой
> нет. Причины технического или политического порядка?

Мне почти сразу ответили: "В ленту попадают последние 2 статьи в режиме реального времени."

Ответ мне не ясен - чьи "последние 2" и за какой период? Кажется, что просто 2 от каждого зарегистрированного блога. Но моих статей в ленте больше. Там даже самый первый пробник. А вот про DeployFolder почему-то нет. Причина, мне кажется, кроется в отсутствии заголовка.

Не буду терзать перепиской администрацию сайта, а просто проверю. Итак - Публикация!

пятница, 17 января 2014 г.

Nexus 4 - хорошо



УРА!! EMBT (при личном участии Всеволода Леонова) прислала мне на работу пакет с призом за конкурс "Осенняя мобилизация". Нет, с ПРИЗАМИ! Я не знаю как вам, а мне - просто СУПЕРСКАЯ футболка!

А теперь о главном: я получил 100% совместимый дивайс! Хорошо, что у него не 2 симки. Иначе мне пришлось бы думать - куда потерять свой свой старый аппарат, чтобы не отдавать жене новый.

Устройство при включении моментально обнаружило, что нужно поднять уровень программного обеспечения до следующей версии желейных бобов, потом перейти к формату Кристофера Кэтлинга, а потом ещё и к формуле 4.4.2. Однако, не смотря на обновления, и якобы 100% совместимости, работать с Delphi аппарат не хотел. Как я расстроился! А надо было найти сайт http://all4nexus.ru/ После всех установок я едва не потерял меню настроек и обнаружил новую заставку при включении. Всё это так интересно!

TLocation действительно работает на этом телефоне. А вот пример Gyroscope так и не хочет крутить кубик - показатели датчика не меняются. Значит, дело уже точно не в машинке.

Здорово, что я не поленился поучаствовать в конкурсе!

среда, 15 января 2014 г.

Nexus 4 - правильное устройство

Ла-ла, ла-ла-ла! Ла-ла, ла-ла-ла!
http://delphimobile.ru/
Ну и кто сомневался в успехе?

Я стал призёром конкурса Emarcadero

ОСЕННЯЯ МОБИЛИЗАЦИЯ

Теперь мне пришлют телефон Nexus 4, официально включённый в список совместимости Delphi XE5 (http://docwiki.embarcadero.com/RADStudio/XE5/en/Android_Devices_Supported_for_Application_Development#Results_of_Our_Android_Device_Testing) как 100% совместимое устройство. Это важно.

Надеюсь, TLocation на нём заработает (проблемы с TLocation отмечены в официальном списке и у других телефонов), что сразу даст мне приличную вспышку в конце тоннеля. Осталось потерпеть совсем чуть-чуть. Держу скрещенными пальцы в тапочках  и мычу священный звук ОМММММММ.

Я подписан на Андроид-форум (https://forums.embarcadero.com//forum.jspa?forumID=522), где некоторые люди XE5 высоко поднимают вопрос об отсутствии совместимости с "не NEON"-аппаратами. Вероятно, в этой же плоскости лежит вопрос и несовместимости с Андроид-устройствами на процессорах INTEL. Мне уже пришлось столкнуться с этим. Это, естественно, следует принимать во внимание.

Но у корпоративного софта есть такая штука как Технические Условия. И если эти условия пишет Исполнитель (а по большей части так и бывает), то - просто добавь в ТУ нужную строчку, и проблема решена. Если для iOS-программ применять устройства от одной фирмы нормально, то почему не подойти таким же образом к распределённому программно-аппаратному комплексу с мобильными компонентами на основе Android?


Кое-кто говорит (http://www.tdelphiblog.com/2013/10/sovmestimostjandroididelphi.html) о 89%-й совместимости XE5 с Андроид-устройствами. Примерно такой же процент был у платформы Windows 3.x в начале её победного шествия (см. наверху диаграмму, которую мы видели неоднократно на встречах с Embarcadero). И этого было настолько достаточно, что и думать об остальных процентах нужды не было. Я думаю, рынок покажет, насколько сейчас Embarcadero нужно думать об этом. Сейчас они и так уже сделали достаточно и для дум, и для дел.

пятница, 27 декабря 2013 г.

DeployFolder - Развёртывание мобильного подкаталога

DeployFolder - Развёртывание мобильного подкаталога

Автоматическое прописывание пути развёртывания файла для мобильного приложения.


Для конкурса Embarcadero "Осеннее настроение 2013" исходник выложен в папку с программой, разработка которой без DeployFolder была бы совершенно невозможной: https://subversion.assembla.com/svn/who-is-who/trunk/WhoIsWho

Вы можете отдельно взять исходный код программы здесь: https://db.tt/YAOLB40g. Но я не гарантирую, что оставлю его без изменения.


Итак, с чего началось создание программы - с простого вопроса: как добавить файл в проект мобильного приложения? Казалось бы, есть простой ответ: Project|Deployment и Add Files. Так? Не совсем. Вам ещё следует прописать каталог, в который файл попадёт на мобильном устройстве. Доступ к этому файлу в коде будет выглядеть примерно так:

  DataDir :=
{$IF Defined(MSWINDOWS)}
    '..\..'{runing in windows - <Platform>\<Configuration>}
{$ELSE}
    TPath.GetDocumentsPath
{$ENDIF}
    +PathDelim + 'Data' + PathDelim;


В данном случае 'Data' – это имя подпапки, в которой лежат мои файлы для приложения внутри папки проекта. А что значит TPath.GetDirectory – зависит от мобильной системы. Для iOs – это '.\StartUp\Documents', а для Android – ‘.\assets\internal’.





К сожалению, эти константы вы вынуждены вносить вручную для кучи разных конфигураций. Не вздумайте что-нибудь забыть или перепутать – приложение может не найти ваш файл после запуска на устройстве или в эмуляторе! Это не очень удобно, не правда ли? Давайте немного облегчим себе жизнь и заполним пути автоматически. Тем более, если количество добавленных файлов больше одного!


Итак, где хранятся пути развёртывания файла? Нет, не в <ProjectName>.deployproj, а в <ProjectName>.dproj! По правде говоря, сначала я был немного озадачен файлом <deployproj>. С одной стороны – расширение файла «.deployproj» так и просит заглянуть в этот файл. И – да! – там перечислены все те файлы, которые были добавлены в проект. Но с другой стороны - всё, что я менял в <deployproj>, вдруг исчезало самым таинственным образом - мистика! Если вы читаете эти строки, то вы уже не попадётесь в эту ловушку. А теперь давайте посмотрим внутрь <dproj> и сравним его кусочек с таблицей Deployment <ProjectName> в IDE.

                </Excluded_Packages>
            </Delphi.Personality>
            <Platforms>
                <Platform value="Android">True</Platform>
                <Platform value="iOSDevice">True</Platform>
                <Platform value="iOSSimulator" ActiveMobileDevice="iPad">True</Platform>
                <Platform value="Win32">True</Platform>
            </Platforms>
            <Deployment>
                <DeployFile LocalName="Data\896.jpg" Class="File">
                    <Platform Name="Android">
                        <RemoteDir>.\assets\internal\Data\</RemoteDir>
                        <RemoteName>896.jpg</RemoteName>
                    </Platform>
                    <Platform Name="iOSDevice">
                        <RemoteDir>.\StartUp\Documents\Data\</RemoteDir>
                        <RemoteName>896.jpg</RemoteName>
                    </Platform>
                    <Platform Name="Win32">
                        <RemoteName>896.jpg</RemoteName>
                    </Platform>
                    <Platform Name="iOSSimulator">
                        <RemoteDir>.\StartUp\Documents\Data\</RemoteDir>
                        <RemoteName>896.jpg</RemoteName>
                    </Platform>
                </DeployFile>
                <DeployFile LocalName="Data\816.jpg" Class="File">
                    <Platform Name="Android">


Без труда можно заметить, что добавленные нами файлы имеют тип “File”. В зависимости от платформы у файла может быть разный каталог размещения. Зная, что <dproj> - это в сущности XML, мы можем бросить на форму из палитры Internet компонент TXMLDocument, найти узел “\Project\ProjectExtensions\BorlandProject\Deployment” и расставить теги <RemoteDir>, в которых хранятся пути развёртывания наших файлов.


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

 Ещё отмечу, что новый путь я ставлю только для платформ из списка 'Android','iOSDevice','iOSSimulator'.

Стоит также заметить, что после обработки проекта я вставил ещё несколько действий. Во-первых - вы можете смеяться, но я не знаю, как удалить строку XML-заголовка, которая появляется в файле проекта после сохранения его компонентом XMLDocument1. Поэтому, не сильно задумываясь, я опять считываю файл на этот раз в TStringList и удаляю первую строчку. Во-вторых, моя Delphi (наткнулся на это в XE5 trial) не хочет собирать проект, если остался старый deployproj. Что ж, удалить его не сложно.

DeployFolder очень удобно поместить в IDE как инструмент c параметром $PROJECT. Этот инструмент можно вызывать каждый раз, когда вы добавили файлы в развёртывание проекта. Например так:


После обработки новым инструментом файла проекта Delphi сама обнаруживает изменение, и достаточно будет просто согласиться на предложение, чтобы перегрузить проект.


Но, увы - на больших проектах происходит ошибка занятости файла*. Ещё одна проблема - при открытой странице Project|Deployment новые файлы задваиваются. Поэтому я закрываю проект после добавления новых файлов и вызываю инструмент без параметров. Обычно, когда работа идёт над одним и тем же проектом, никаких неудобств не возникает - имя проекта сохраняется.

Кстати. Я стал задумываться, не сделать ли каталогам псевдонимы, например c:\mo\x=\x. Что вы об этом думаете? Есть у вас ещё предложения? Пишите мне – alhymov@mail.ru

И да, ВНИМАНИЕ, УВАГА, ATTENTION, ACHTUNG: При формировании для Андроид списка дополнительных файлов Delphi (или SDK?) формирует список, где имена каталогов в нижнем регистре! Имена самих каталогов в пакете приложения при этом остаются в том регистре, в котором вы написали на вкладке Project|Deployment. При старте приложения на устройстве происходит выгрузка файлов из пакета приложения в "песочницу". И, поскольку имена каталогов в списке и в пакете не совпадают, приложение даже не проходит строчку begin в проекте. Будьте бдительны! А в моей программе это обстоятельство уже учитывается.
---
ошибка занятости файла судя по всему связана с тем, что проект хранится в DropBpox. Т.е. как только файл изменился, его начинают тащить в сеть и, видимо, для этого блокируют. Т.е. надо перед первой записью самому файл захватить и отпустить только после второй записи. Если кто-то сразу мне кинет ссылку на блокировку файла, буду признателен. Но я скорее всего пойду по другому пути - однократной записи. Т.е. ХМL записать в поток и считать его уже оттуда в StringList, а не из файла. И уже потом сохранить один раз. Пока руки не дошли.**
---
** Руки дошли - см. DropBox против файлов http://alhymov.blogspot.ru/2014/02/dropbox.html

воскресенье, 15 декабря 2013 г.

Конкурс Осенняя Мобилизация

Конкурс Осеняя Мобилизация

Embarcadero предлагает приятный повод поближе познакомиться со своими новыми технологиями в Delphi. Широко рекламируемые FireMonkey, FireDAC, Android и iOS - всё, что хотелось попробовать, но до чего всё никак не доходили мои усталые натруженные руки. Овладевание тем инструментом, который есть, но лежит ещё без дела - не единственный плюс от участия в конкурсе. Есть ещё, конечно, слабая надежда на выигрыш. А с надеждой жить гораздо интереснее. И ещё есть надежда, что читая блоги участников, жюри сделает выводы о том, как лучше помогать программистам в разработке, как улучшить Delphi. Ну и, как знать, возможно удастся подсмотреть что-нибудь полезное у других участников. Обмен, так сказать, опытом.

Мной на конкурс представлено приложение WhoIsWho - аналог нашего корпоративного телефонного справочника. Слепленное на пробу из примеров приложение вдруг стало популярным в нашем коллективе. Люди гораздо охотнее пользуются приложением, чем смотрят те же данные на корпоративном сайтеТакое вот открытие.

https://subversion.assembla.com/svn/who-is-who/trunk/WhoIsWho

Описание назначения приложения:

WhoIsWho - Программа предназначена для знакомства сотрудников в организации друг с другом. И ещё хотелось бы обратить внимание общественности на DeployFolder - сопутствующая программа, которую, возможно, также следует считать кандидатом на участие в конкурсе.

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

В исходный код включены следующие проекты:
1.WhoIsWho - Заявленное на конкурс приложение для Android, iOs, Windows.
2.GetWIWDate - Windows-приложение для получения данных из корпоративной базы данных для приложения WhoIsWho. Сначала я просто сохранял таблицу из MS Management Studio через MS Excel, но потом решился на FireDAC. FireDAC - страшное слово, куча страшных компонентов. Но на удивление, пользоваться оказалось не страшно, и даже можно сказать - удобно. Только исходники FireDAC в поставке с Delphi - явно устаревшие.
3.mess - Windows-приложение для подготовки данных к конкурсу - превращение реальных данных в случайные. Там есть пример смены символов в строке.
4.DeployFolder - Windows-приложение для формирования части deployment Delphi-проекта. Не смотря на то, что это не android, это важный инструмент для разработки на android.

Основной сценарий работы:

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

А теперь надо рассказать о создании программы, проблемах, с которыми пришлось столкнуться и решениях, выраженных в исходном коде.

Идея и реализация.
За основу были взяты примеры TabletMasterDetailWithSearch и шаблон нового приложения Phone-Master Detail.  Славный Ярослав Бровин показывал, как делать формы для разного формата экрана для iOS, но пример для Андроида  - PhotoEditorDemo я увидел только спустя некоторое время. Поэтому я не стал наследовать формы. Может быть, оно и к лучшему.

Хранение данных - трудности выбора
Как и FM, FireDAC был мне чужд. Но как быть? Предлагался IBlite, были примеры с SQLite. И главная непонятность - биндинг! IB напугал лицензированием и разнообразием форм. Не возникло к IB доверия и из-за неудачного примера в поставке к Delphi. SQLite тоже вызвал вопросы. Хотя в поставке для Windows не было нужной DLL, она легко нашлась в Сети. А с русскими буквами - тоже проблема. Опять-таки в поставку вошёл неудачный пример для SQLite. Позднее я увидел, что FireDAC() спасает. Но FireDAC - это ещё одна terra incognita. Слишком много неизвестного для начала - FMX, binding, new DB engine. Совершенно было непонятно, как перейти от источника примерных данных к источнику данных реальных.

Хранение данных - простое решение
Добрый Всеволод Леонов в своём блоге как-то писал о простом текстовом IO для мобильных устройств. Я попробовал - да. Так что - в топку binding, здравствуйте мои дорогие TStringList и INI! Осталось только положить рядом фотографии - и что ещё нужно?

Проблема множества файлов
Deployment сделан ужасно. Мало того, что он сортировку сбрасывает, глючит - задваивает и вдруг перестаёт видеть файлы, так им ещё и просто невозможно добавить количество файлов, превышающее пару десятков. Попробуйте добавить для всех конфигураций путь на устройстве - это каторга.  Я разговаривал на конференциях с людьми - как и что делать, никто не знал. Тогда я сделал для Deployment специальный инструмент DeployFolder. Теперь стало легко добавлять тысячу файлов. И даже когда добавлен только один файл - гораздо удобнее запустить DeployFolder, чем писать пути руками.

Проблема именования пути
Вот это была засада! Пока у меня не было исходников (в триале), выяснить причину беды было невозможно. На симуляторе iOS - всё прекрасно. А на Androide - даже не запускается. Оказывается, дело в искажении имён каталогов при деплойменте. Сами файлы, размещаемые в подкаталогах, остаются в том регистре, в котором они и были. И имя папки - тоже в том же регистре. Но! - в списке файлов для распаковки на устройстве каталоги - в нижнем регистре! И при этом, когда приложение стартует и выделяет из себя данные, в System.StartUpCopy.CopyAssetToFile даже нет никакого assert, на доступность упакованных в приложение файлов.Там написано "// We have a valid AssetManager. Start", но нет "// We have a valid Asset File". Так что вот.

Проблема с добавлением своего стиля
Как добавить новую стильную картинку на компонент, чтобы на разных платформах отражалось по-разному? Я не знаю. Евгений Крюков рассказывал, что не сложно - стоит нажать правую кнопку, и... И вот нет на мобильной форме команды редактирования стиля. А на немобильной - нет ни правой части редактора, где отображена структура разметки, ни содержимого центральной. Редактор стилей не работает.

Что использовать вместо пиктограммы
В Windows вообще нет пиктограмм. Я использовал вместо пиктограммы текст. Мне так понравилось использовать символы, что я так и оставил в телефонной форме букву @ вместо стиля actiontoolbuttonbordered. А как взять из стиля пиктограмму для некнопочного контрола? Просто так картинку нельзя, она должна быть в общем стиле, меняться от платформы к платформе. Я захотел сделать свой сплиттер-експандер, чтобы увеличивать и уменьшать область фотографии. Мне понравились значки "вверх" и "вниз", но они разные на разных платформах. Пришлось взять кнопки целиком. Но они всё время хотели съехать вниз. Чтобы отцентровать их по вертикали я использовал дополнительные Layout. Что получилось - можно увидеть на вертикальной телефонной форме.

Интерактивные жесты 
Интерактивные жесты лучше кликов и стандартных жестов дают обратную реакцию - не надо ждать завершения касания. Но в этом и трудность - они непрерывны, и когда реакция обработана, пользователь ещё не закончил движение, и мы снова ловим жест, который уже не нужен. Например, двойное нажатие на фото и сдвиг по нему - если двигать часто, то это может сойти за двойной тап. Не забываем про Handled! А чтобы "прекратить" отслеживать интерактивный сдвиг я придумал смотреть на время. Если с последнего зафиксированного и обработанного сдвига прошло меньше четверти секунды, то это ещё остаток обработанного движения, и на него не стоит реагировать.

Права на внешнее хранение
Я не знаю, как обновить приложение, не убив его внутренние данные. К счастью, в Android есть внешние каталоги. Но! - если использовать что-то вроде TPath.GetSharedDocumentsPath, то можно нарваться на пустую строку! Шайтан спрятался в пермишинах проекта - надо посмотреть список прав и поставить нужные external write галочки.

Каталог устройства, легко доступный с ПК
Я посмотрел, что корни файловой системы на разных Android-устройствах разные. Но есть у них общее - там лежит папка /Android/. Вроде, все так и делают - берут SharedDocumentsPath и оставляют от него только корень, чтобы сделать свою папку с понятным названием. Но об этом в учебниках не сказано.

OnChange
Событие OnChange в FMX ведёт себя совсем не так, как в VCL. Раньше присвоение ItemIndex или IsChecked не вело к вызову события. А теперь - да. Поэтому при инициализации формы я использую специальный флаг - IsCreated, чтобы отличить внутренние присвоения от действий пользователя.

TPopup
Когда я запускаю TPopup, он выскакивает там, где мышь или было нажатие. Хотелось бы управлять позицией TPopup, но не знаю как. Не сразу я поборол прозрачность TPopup - оказалось, что надо не забывать установить StyleLookup. Ещё при старте следует ограничивать размер TPopup - иначе, он вылезет за границу экрана.

TComboBox vs TPopupBox
TComboBox и TPopupBox выглядят на мобильных устройствах одинаково:  "барабан" на iOS и диалог с радиокнопками на Android. Явное различие появляется на Windows: TComboBox делает прокручиваемый список, а TPopupBox рисует панель, которая может вылезти далеко за пределы экрана.

Хардварный Бэк
Пока не нашёл, как по кнопке "Назад" в Андроиде программно прятать приложение. Когда ходим по закладкам и возвращаемся, то запросто нажать кнопку лишний раз. Если спросить пользователя о закрытии, то что бы он ни ответил, программа не закроется. Пока прибиваю Halt(0). Но это - конечно, варварство.

Флушинг конфига
Я пишу в INI-файл конфигурацию сразу, как что-то поменялось. Но если программу взять в список задач и выкинуть оттуда, то она закроется, не успев сказать "ой", и изменения не будут записаны. Поэтому сразу после Write<T> нужно делать UpdateFile.

Unicode - Проблема со шрифтами 
Википедия даёт нам знаки зодиака в виде юникодных кодов. В Windows эти знаки прекрасно отображаются. Казалось бы, Unicode должен работать на всех платформах, но увы. Пришлось отрезать значки на мобильных устройствах.

Unicode - Особенности текста 
Во-первых, нельзя забывать об указании кодировки при работе с TStringList. Иначе, по умолчанию под Windows будет сохранятся Ansi, который не стоит перетаскивать на мобильное устройство.  Ещё одной особенностью является необходимость указания разделителя строк #13#10 для iOS. Иначе при разборе текста строка может перенестись "вдруг" где-нибудь в середине.

Локализация
Все диалоги имеют кнопки на английском, хотя я указал, что приложение имеет русский язык в качестве предпочтения. Либо FMX не понимает этого, либо я не понимаю, как ей это сказать

Проблемы iOS - Delphi
Конкурс проводится, конечно, для Android. Но суть мобильной разработки на Delphi - многоплатформенность. Поэтому нужно сказать, что у меня с iOS большие проблемы. Во-первых, я не могу запустить отладчик с реальным устройством - Delphi ругается, что у меня два одинаковых сертификата - в системной и в пользовательской связках ключей. Во-вторых, после Ad Hok Delphi виснет с указанием последнего файла в списке Deployment. Delphi я снимаю диспетчером, а файл на Маке получается рабочий.

Проблемы iOS - FMX
Я использую TPopup для ввода параметров. Если для закрытия используется кнопка - не важно, TButton или TSpeedButton, то всё падает. Убрал для iOS кнопки - приходится тыкать в свободное место, что мне кажется неудобным. Кроме того, событие OnClose срабатывает дважды! Ну и зашарить картинку - никак: едва показывается какая-то панель со значками, и всё вылетает. Уж iOs, казалось бы, не первый год осваивается FMX. Вот же ж.

Проблемы iOS - Apple
Не придумал, как сохранить файлы конфигурации, чтобы при обновлении программы настройки сохранялись. Особенно актуально это стало, когда в программе появились пользовательские заметки.

Досадные мелочи при разработке
Мне досаждает порча dpr при добавлении юнита в проект. Delphi добавляет кучу строк  Application.CreateForm(TPhoneMasterDetail, PhoneMasterDetail) и убирает , Androidapi.JNI.GraphicsContentViewText. Я захожу в историю (спасибо челу, который сделал эту штуку в Delphi!) и копирую Androidapi.JNI.GraphicsContentViewText оттуда. Возможно, следует вынести переключение формы в отдельный модуль, но как-то лениво. 

Ограничения смены ориентации
Не понимаю, зачем в FMX сознательно исключается из ориентации телефонного форм-фактора "обратно-вертикальное" положение. Типа, "кнопки" вверху на телефоне не должны быть. С чего бы это? Мало ли, как у телефона провода или ещё какие боковые элементы управления расположены! Иногда перевернуть телефон - очень нормально. Например, Yandex Navigator вертится всяко. А некоторые приложения - не хотят. Но пусть это нежелание лежит на совести программиста. Нельзя лишать программиста возможности сделать "неправильно", но так, как удобно пользователю.

Нехватка мощностей
Люди жалуются, что некоторые фото на Андроиде - прямоугольник Малевича, т.е. чернота. Я посмотрел - да, начиная примерно с около 400 КБ фото чернеют. Поэтому при загрузке данных я добавил в GetWIWDate пробежку по картинкам, где уменьшаю на 3/4 габариты фото, которые больше 375 КБ. Если фото не уменьшилось до нужного размера, процесс повторяется. Интересно, что от владельцев iOS жалоб не поступало.

Прочие мелочи-находки
Не сразу нашёл, поэтому, наверно, кому-то, новичку интересно будет. По умолчанию FMX делает форму для Windows на весь полный экран без заголовка и панели задач. Эта неприятность исправляется в Object Inspector - Full Screen. Убрать "макет устройства" - Alt+F12 и DesignerMobile = False. Ф-я IsTablet присутствует в платформенных модулях графики.  Я за образец взял PhotoEditorDemo - пример, где Ярослав сложил эти ф-ии вместе. Это скорее всего просто косяк FM, но после того, как я изменил содержимое memo (даже внутри BeginUpdate-EndUpdate) в Windows надо вызывать Repaint - иначе изменений не видно, пока не кликнешь по контролу мышкой. Ещё удивился, что (см.GetWIWDate ) между TBitmap.CreateFromFile и TBitmap.SaveToFile надо вставлять TFile.Delete - иначе при записи файл будет занят!

А ещё - мне ОЧЕНЬ-ОЧЕНЬ-ОЧЕНЬ не хватает WITH. Любил я его.


понедельник, 7 октября 2013 г.

Начинаю блог

Пока не ясно, как делать стили, оформлять исходный код.

program MyProg;
begin
  WriteLn('Hello, World!');
end.