<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>В наушниках по жизни: заметки с тегом программирование</title>
<link>https://alexbirukov.ru/?go=tags/programmirovanie/</link>
<description>Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.3 (v4134)</generator>

<itunes:subtitle>Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>Подключение Bluetooth модуля HM-10 (MLT-BT05) через программатор CH341A</title>
<guid isPermaLink="false">357</guid>
<link>https://alexbirukov.ru/?go=all/podklyuchenie-bluetooth-modulya-hm-10-mlt-bt05-cherez-programmat/</link>
<pubDate>Fri, 14 Aug 2020 23:45:08 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/podklyuchenie-bluetooth-modulya-hm-10-mlt-bt05-cherez-programmat/</comments>
<description>
&lt;p&gt;Всем привет.&lt;/p&gt;
&lt;p&gt;Сегодня обзавёлся простеньким Bluetooth модулем для работы с различными девайсами через BT, в частности, для беспроводного подключения к бортовому компьютеру квадрокоптера. Модуль был приобретён MLT-BT05, аналог HM-10. По различным причинам китайские модули часто бывают не совсем работоспособными «из коробки», а способы их проверки и прошивки требуют определённого навыка.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/module-hm-10-and-base-board-1-720x720.jpg" width="720" height="720" alt="HM-10 (MLT-BT05)" /&gt;
&lt;/div&gt;
&lt;p&gt;Вот и я, купив данный модуль, не сразу понял, как же его по-быстрому проверить. После подключения к квадрокоптеру, было очевидно, что модуль рабочий и подключить к нему удаётся. Но для нормальной работы необходимо было проверить работу команд, ответы от модуля, а так же произвести некоторые настройки дефолтных параметров.&lt;/p&gt;
&lt;p&gt;После изучения материала в интернете, стало понятно, что для детальной настройки и проверки модуля потребуется подключить модуль посредством UART к компьютеру или квадрокоптеру. Но т. к. модуль не настроен, то и работать с квадрокоптером он отказывался. Интернет же настойчиво советует работать со специальным переходником USB-UART, и все статьи, как под копирку вторят этому.&lt;/p&gt;
&lt;p&gt;Идти покупать отдельный модуль USB-UART совершенно не хотелось, и я вспомнил, что у меня есть программатор CH341A, который не просто программатор, а мультифункциональный конвертер из USB 2.0 в UART, EPP, I2C и SPI. &lt;a href="https://habr.com/ru/post/262731/"&gt;Вот тут есть немного полезной информации&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для работы по протоколу UART, необходимо переставить перемычку в положение 2-3 (изначально она установлена в положении 1-2). В видеоролике ниже всё показано более детально, поэтому не вижу смысла делать длинный мануал по переключению.&lt;/p&gt;
&lt;div class="e2-text-video"&gt;
&lt;iframe src="https://www.youtube.com/embed/AEEq7GMolls?enablejsapi=1" allow="autoplay" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Всё достаточно просто. Теперь наш программатор готов для работы по проверке и настройке Bluetooth модуля HM-10 (MLT-BT05). Подключить Bluetooth модуль достаточно просто. Контакты VCC и GND подключаем соответственно к аналогичным разъёмам на программаторе, а TXD и RXD накрест.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/95a93das-960.jpg" width="427" height="140" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Для соединения устройств я использовал простые перемычки, которые продаётся в радиомагазинах или магазинах RC моделей.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14-23-09-02.JPG" width="768" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;У меня получилось вот так.&lt;br /&gt;
Далее, остаётся лишь подключить программатор к компьютеру и открыть терминал для работы с COM портом. В моём случае, это порт COM10.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-13-06.png" width="721" height="253" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь, зная номер порта, проверим, доступен ли модуль Bluetooth. Для этого я лично решил воспользоваться &lt;a href="https://www.arduino.cc/en/Main/Software"&gt;Arduino IDE&lt;/a&gt;, если точнее, то встроенным средством «Монитор порта».&lt;/p&gt;
&lt;p&gt;Для этого, после установки Arduino IDE, запускаем программу, открываем меню «Инструменты» -&gt; «Порт» и выбираем COM порт. В моём случае это COM10.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-18-43.png" width="670" height="488" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;И теперь, заходим в меню «Инструменты» -&gt; «Монитор порта». Появится окно для ввода команд и просмотра ответов от модуля, подключенного к порту. Настройки скорости и конца строки должны быть выставлены так же, как на скриншоте.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-21-13.png" width="1523" height="427" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь пришло время проверить работу команд и ответ. Для старта можно ввести команду AT. По умолчанию данный модуль находится в режиме приёма команд, но если имеется хотя бы одно подключенное устройство, то команды пониматься модулем не будут. Ввод команды &lt;b&gt;AT&lt;/b&gt; должен вернуть ответ, в моём случае &lt;b&gt;«ОК»&lt;/b&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-24-10.png" width="572" height="377" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Если набрать команду &lt;b&gt;AT+HELP&lt;/b&gt;, то модуль выведет список всех доступных команд.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-26-56.png" width="478" height="533" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Больше всего меня интересовали следующие команды: &lt;b&gt;AT+VERSION&lt;/b&gt;, для отображения версии прошивки модуля. У моего модуля версия прошивки &lt;b&gt;MLT-BT05-V4.4&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Далее, мне необходимо было изменить имя Bluetooth, которое отображается при поиске модуля. Для это используется команда «&lt;b&gt;AT+NAME&lt;/b&gt;», которая в чистом виде вернёт текущее имя модуля, я же набрал её в варианте «&lt;b&gt;AT+NAMEAlex-BT&lt;/b&gt;», тем самым установив имя модуля в значение «&lt;b&gt;Alex-BT&lt;/b&gt;».&lt;/p&gt;
&lt;p&gt;Командой «AT+PIN» проверяем текущий пароль и ставим свой пароль при необходимости. Пароль по умолчанию «&lt;b&gt;123456&lt;/b&gt;», учтите, минимальная длинна пароля 6 символов. Если попробовать установить пароль короче, будет выведена ошибка.&lt;/p&gt;
&lt;p&gt;Ну, и осталось поднять скорость работы модуля. Текущая скорость по умолчанию 9600 бод, а хотелось бы немного побольше. Для проверки текущей скорости необходимо выполнить команду «&lt;b&gt;AT+BAUD&lt;/b&gt;». Будет отображен текeщий параметр, в случае если скорость 9600 бод, то будет выведено «&lt;b&gt;AT+BAUD4&lt;/b&gt;».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-38-59.png" width="680" height="373" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Для установки скорости 115200 бод необходимо выполнить команду «&lt;b&gt;AT+BAUD8&lt;/b&gt;».&lt;/p&gt;
&lt;p&gt;Ну вот и всё. Проверка и базовая настройка модуля на этом завершена. Для более детальной настройки вы можете изучить даташиты модуля и посмотреть команды, которые поддерживает модуль.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/2020-08-14_23-41-21.png" width="216" height="92" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Надеюсь, этот небольшой гайд поможет вам.&lt;/p&gt;
</description>
</item>

<item>
<title>Report Builder for Synadyn Broadcast 1.0</title>
<guid isPermaLink="false">330</guid>
<link>https://alexbirukov.ru/?go=all/report-builder-for-synadyn-broadcast-1-0/</link>
<pubDate>Fri, 15 Jan 2016 23:00:05 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/report-builder-for-synadyn-broadcast-1-0/</comments>
<description>
&lt;p&gt;Достаточно давно, ещё когда я работал на «Восточном Экспрессе» я &lt;a href="http://alexbirukov.ru/?go=2011/10/12/1/"&gt;написал и выложил в свободный доступ&lt;/a&gt; программу для генерации отчётов в РАО на основании отчётов о проигранных файлах, которые оставляет Synadyn Broadcast.&lt;/p&gt;
&lt;p&gt;Часто люди стали спрашивать у меня, можно ли сделать ту или иную модификацию, есть ли новые версии. И получилось так, что на данный момент есть более свежая версия программы, которую я ещё не публиковал. Её кардинальное отличие состоит в том, что данная версия позволяет создавать отчёты не за один месяц, а за необходимый период, собирая информацию из всех имеющихся файлов. Т. е. если вы указываете каталог, в который предварительно скопировали файлы отчётов за 3 месяца, то программа соберёт информацию из всех имеющихся фалов.&lt;/p&gt;
&lt;p&gt;Скомпилированная версия 1.0:&lt;br /&gt;
&lt;a href="http://alexbirukov.ru/files/rb/10/Report-Builder-for-Synadin-Broadcast-1.0.7z"&gt;Report Builder for Synadyn Broadcast 1.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Так же, для всех желающих, я выложил в открытый доступ исходные коды проекта:&lt;br /&gt;
&lt;a href="https://github.com/alexbirukov/report-builder"&gt;GitHub Report Builder for Synadyn Broadcast&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Убедительная просьба, если вы добавляете какой-либо функционал, который может быть полезен, создайте PullRequest на GitHub, чтобы включить ваши правки в новый релиз для развития проекта. Делитесь своими достижениями с другими.&lt;/p&gt;
&lt;p&gt;Данное программное обеспечение является совершенно бесплатным и поставляется как есть.&lt;/p&gt;
</description>
</item>

<item>
<title>Аудио-плеер на Delphi для iOS с применением библиотеки BASS.</title>
<guid isPermaLink="false">329</guid>
<link>https://alexbirukov.ru/?go=all/udio-pleer-na-delphi-dlya-ios-s-primeneniem-biblioteki-bass/</link>
<pubDate>Mon, 04 Jan 2016 02:00:24 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/udio-pleer-na-delphi-dlya-ios-s-primeneniem-biblioteki-bass/</comments>
<description>
&lt;p&gt;Прошло довольно много времени с момента написания первой статьи «&lt;a href="http://alexbirukov.ru/?go=all/udio-pleer-na-delphi-dlya-android-code-gear-rad-studio-xe7/"&gt;Аудио-плеер на Delphi для Android с применением библиотеки BASS&lt;/a&gt;». И теперь я решил написать вторую часть статьи про запуск и использование библиотеки BASS под iOS. В данном конкретном случае, так же? как и в предыдущей статье, целью подключения библиотеки, стало использование функции проигрывания сетевого аудиопотока.&lt;/p&gt;
&lt;h2&gt;Настройка&lt;/h2&gt;
&lt;p&gt;Как и в случае с настройкой под Android, для iOS нам потребуются дополнительные библиотеки, без которых скомпилировать проект не получиться. Воспользуемся набором библиотек &lt;a href="http://sourceforge.net/projects/dpfdelphiios/"&gt;DPF iOS Native Components&lt;/a&gt;. Данные библиотеки нужны для подключения iOS фреймворка работы со звуком.&lt;/p&gt;
&lt;p&gt;Скачиваем архив с файлами с &lt;a href="http://sourceforge.net/projects/dpfdelphiios/"&gt;официального сайта&lt;/a&gt; или с &lt;a href="http://alexbirukov.ru/files/radio-ios/DPF.iOS.Native.Components.v9.6.1.zip"&gt;моего сайта&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;После того, как мы скачали все необходимые дополнительные файлы, приступаем к установке компонентов.&lt;/p&gt;
&lt;p&gt;Я рекомендую (во избежании дополнительных проблем с подключением) распаковать файлы в папку DPF.iOS.Native.Components.v9.6.1.zip в корень диска C.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-00-54-41.png" width="1280" height="1024" alt="Распаковываем файлы фреймворка" /&gt;
&lt;/div&gt;
&lt;p&gt;В каталоге с файлами, имеется файл Install.txt. У кого хорошо с английским, могут сделать всё по инструкции описанной в файле, для тех, кто не совсем понимает, что необходимо делать, я опишу процесс подробно.&lt;/p&gt;
&lt;p&gt;Запускаем Codegear RAD Studio. Далее в верхнем меню открываем Tools-&gt;Options-&gt;Delphi Options-&gt;Library.&lt;/p&gt;
&lt;p&gt;Затем, в выпадающем списке поочерёдно выбираем следующие пункты платформ:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;32-bit windows&lt;/li&gt;
&lt;li&gt;iOSSimulator&lt;/li&gt;
&lt;li&gt;iOSDevice32&lt;/li&gt;
&lt;li&gt;iOSDevice64&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;В каждом из пунктов добавляем в раздел «Library path» путь к нашим компонентам. В нашем случае &lt;b&gt;C:\DPF.iOS.Native.Components.v9.6.1\&lt;/b&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-00-56-43.png" width="1280" height="1024" alt="Добавление фреймворка" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-00-57-19.png" width="1280" height="1024" alt="Добавление фреймворка" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Теперь, необходимо в разделе SDK Manager указать, какие фрейворки iOS нам потребуются. Для этого открываем Tools-&gt;Options-&gt;SDK Manager, пролистываем появившийся список вниз до раздела &lt;b&gt;Frameworks&lt;/b&gt;, выбираем в списке один из фремворков, нажимаем на кнопку &lt;b&gt;Add the new path item&lt;/b&gt; и добавляем следующие фреймворки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/System/Library/Frameworks/EventKit&lt;br /&gt;
/System/Library/Frameworks/MessageUI&lt;br /&gt;
/System/Library/Frameworks/AudioToolbox&lt;br /&gt;
/System/Library/Frameworks/Social&lt;br /&gt;
/System/Library/Frameworks/QuickLook&lt;br /&gt;
/System/Library/Frameworks/SystemConfiguration&lt;br /&gt;
/System/Library/Frameworks/GameKit&lt;br /&gt;
/System/Library/Frameworks/CoreBluetooth&lt;br /&gt;
/System/Library/Frameworks/Accounts&lt;br /&gt;
/System/Library/Frameworks/AdSupport&lt;br /&gt;
/System/Library/Frameworks/ExternalAccessory&lt;br /&gt;
/System/Library/Frameworks/AddressBookUI (No need in XE8 and later)&lt;br /&gt;
/System/Library/Frameworks/AddressBook (No need in XE8 and later)&lt;br /&gt;
/System/Library/Frameworks/MobileCoreServices (No need in XE8 and later)&lt;br /&gt;
/System/Library/Frameworks/MapKit (No need in XE8 and later)&lt;br /&gt;
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication (iOS 8.0 and later)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Add.png" width="1280" height="1024" alt="добавление фрейворков" /&gt;
&lt;/div&gt;
&lt;p&gt;В качестве пути на удалённом хосте требуется указывать путь «&lt;b&gt;$(SDKROOT)/System/Library/Frameworks&lt;/b&gt;», а качестве имени, название фремворка. Для примера:&lt;br /&gt;
&lt;b&gt;Путь:&lt;/b&gt; $(SDKROOT)/System/Library/Frameworks&lt;br /&gt;
&lt;b&gt;Имя:&lt;/b&gt; EventKit&lt;br /&gt;
Больше нигде никаких галочек ставить и выбирать не требуется.&lt;/p&gt;
&lt;p&gt;Должно получиться так.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-07-03.png" width="1280" height="1024" alt="Добавление фреймворков" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Frameworks.png" width="1199" height="733" alt="Список фремворков" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;В разделе &lt;b&gt;Libs&lt;/b&gt;, аналогичным образом необходимо добавить библиотеку &lt;b&gt;/usr/lib/libxml2.dylib&lt;/b&gt;. Путь к ней указать, как &lt;b&gt;$(SDKROOT)/usr/lib/&lt;/b&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-10-12.png" width="1280" height="1024" alt="Библиотека libxml2.dylib" /&gt;
&lt;/div&gt;
&lt;p&gt;После добавления всех фреймворков в список необходимо обязательно нажать на кнопку &lt;b&gt;Update local File Cache&lt;/b&gt;. При этом MAC с запущенным PAServer’ом должен быть настроен и доступен.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-18-15.png" width="1280" height="1024" alt="Update local File Cache" /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь нам потребуется скомпилировать и установить компоненты. Для этого нажимаем File -&gt; Open Project. Открываем проект из папки компонентов, соответствующий вашей среде программирования.&lt;/p&gt;
&lt;p&gt;Нажимаем правой кнопкой на проекте в инспекторе проекта и выбираем пункт &lt;b&gt;«Build»&lt;/b&gt;, начнётся построение проекта.&lt;/p&gt;
&lt;p&gt;После завершение построение, опять нажимаем правой кнопкой на проекте в инспекторе и выбираем пункт &lt;b&gt;«Install»&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Компоненты готовы к работе. Приступим к созданию проекта.&lt;/p&gt;
&lt;h2&gt;Проект&lt;/h2&gt;
&lt;p&gt;И вот, всё почти готово, для использования библиотек Bass на iOS. Осталось задействовать саму библиотеку и добавить некоторый код в проект.&lt;/p&gt;
&lt;p&gt;Для работы с библиотекой, нам потребуется файл &lt;b&gt;libbass.a&lt;/b&gt;. Его необходимо добавить в корень каталога проекта. Откуда конкретно у меня данный файл, я точно сказать не смогу, я нашёл его где-то на просторах форума &lt;a href="http://www.un4seen.com/"&gt;un4seen.com&lt;/a&gt;. Здесь я выкладываю &lt;a href="http://alexbirukov.ru/files/radio-ios/libbass.a"&gt;рабочий файл&lt;/a&gt; из своих проектов.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-28-45.png" width="1280" height="1024" alt="Файл libbass.a" /&gt;
&lt;/div&gt;
&lt;p&gt;Но, одного файла для работы будет недостаточно. Так же, в проект необходим добавить ещё 2 файла *.pas. Первый будет необходим для работы с функциями libbass, второй послужит для работы с фреймворком iOS для работы с сетевыми потоками.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-34-36.png" width="1280" height="1024" alt="Файлы проекта" /&gt;
&lt;/div&gt;
&lt;p&gt;Необходимо скачать данный архив, распаковать его содержимое в корень проекта и подключить &lt;a href="http://alexbirukov.ru/files/radio-ios/adv-libbass.7z"&gt;данные файлы&lt;/a&gt; к проекту.&lt;/p&gt;
&lt;p&gt;В раздел &lt;b&gt;implementation&lt;/b&gt; необходимо добавить следующий код:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;{$O-}
  function BASS_Init(device: LongInt; freq: DWORD; flags: DWORD; win: Pointer; clsid: Pointer) : BOOL; cdecl; external 'libbass.a' name 'BASS_Init';
  function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; cdecl; external 'libbass.a' name 'BASS_StreamPutData';
  function BASS_StreamFree(handle: HSTREAM): BOOL; cdecl;  external 'libbass.a' name 'BASS_StreamFree';
  function BASS_StreamCreate(freq: DWORD; chans: DWORD; flags: DWORD; proc: Pointer; user: Pointer): HSTREAM;  cdecl;  external 'libbass.a' name 'BASS_StreamCreate';
  function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: Cardinal): HSTREAM; cdecl; external 'libbass.a' name 'BASS_StreamCreateFile';
  function BASS_StreamCreateURL(url: Pointer; offset: Cardinal; flags: Cardinal; proc: DOWNLOADPROC; user: Pointer):HSTREAM; cdecl; external 'libbass.a' name 'BASS_StreamCreateURL';
  function BASS_ChannelPlay(handle: HSTREAM; restart: BOOL): BOOL; cdecl;  external 'libbass.a' name 'BASS_ChannelPlay';
  function BASS_ChannelStop(handle: DWORD): BOOL; cdecl; external 'libbass.a' name 'BASS_ChannelStop';
{$O+}&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Работа с аудиопотоком&lt;/h2&gt;
&lt;p&gt;Для корректной работы с аудипотоками, требуется подключение аудио-фреймворка iOS.  Самый простой способ сделать это, кинуть на форму компонент DPFAVPlayer, что именно я и сделал. Это исключает необходимость выполнения дополнительных манипуляций.&lt;/p&gt;
&lt;p&gt;Так же, для нормальной работы программы, я разделал функционал на несколько потоков, чтобы при проигрывании аудио потоков само приложение не тормозило и не останавливалось по неизвестным причинам. Приведу код работы из рабочего проекта.&lt;/p&gt;
&lt;p&gt;Глобальные переменные.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;uStream:HSTREAM;
chan: HSTREAM = 0;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;При нажатии на кнопку Play в приложении запускается поток:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Запускаем поток вещания
IdThreadComponent1.Start;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;«Тело» потока:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;try

    // Инициализируем libbass
    BASS_Init(-1,44100,0,Handle,nil);

    // Закрываем предыдущие потоки (не обязательно, взято из примера)
    BASS_StreamFree(uStream);

    messageText := 'Буферизация...';
    IdThreadComponent1.Synchronize(ShowMess);
    // Создаём поток данных
    uStream:=BASS_StreamCreateURL(Pchar(stantion),0,BASS_STREAM_STATUS or BASS_UNICODE,nil,nil);

    if uStream = 0 then
    begin
      ShowMessage('Ошибка создания потока!');
    end
    else
    begin

      if not Bass_ChannelPlay(uStream,true) then
      begin
        ShowMessage('Не удалось воспроизвести поток!');
      end;

      messageText := currentLabel;
      IdThreadComponent1.Synchronize(ShowMess);
      IdThreadComponent1.Synchronize(deactivateIndicator);
    end;

  except on E: Exception do
    begin
      {$IFDEF DEBUG}
        ShowMessage(e.Message);
      {$ELSE}
        ShowMessage('Ошибка подключения к выбранной радиостанции.');
      {$ENDIF}
    end;
  end;

  IdThreadComponent1.Terminate;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Остановка проигрывания&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Останавливаем плеер
BASS_ChannelStop(uStream);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как вы могли заметить, во время запуска потока, инициализируется библиотека Bass, очищаются имеющиеся потоки и создаётся новый интернет поток при помощи функции &lt;b&gt;BASS_StreamCreateURL&lt;/b&gt;, где &lt;b&gt;stantion&lt;/b&gt; строковая переменная, содержащая ссылку на поток.&lt;/p&gt;
&lt;p&gt;Данный набор минимальных настроек, позволит вам работать с библиотекой Bass на устройствах под управлением iOS.&lt;/p&gt;
&lt;h2&gt;Проигрывание в фоне&lt;/h2&gt;
&lt;p&gt;Чтобы заставить ваше приложение продолжать проигрывание в фоне, необходимо сделать дополнительные настройки проекта. В XE10 наконец-то появился параметр &lt;b&gt;UIBackgroundModes&lt;/b&gt;. В настройках проекта устанавливаем значения: &lt;b&gt;audio&lt;/b&gt; И &lt;b&gt;remote-notification&lt;/b&gt; (в случае использования Push уведомлений).&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-XE10-2016-01-04-01-52-53.png" width="1280" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;h2&gt;Окончание&lt;/h2&gt;
&lt;p&gt;Ну вот в общем и всё, что требуется сделать для создания проекта с использованием libbass на iOS. Возможно, при написании статьи я допустил какие-либо неточности и недочёты, т. к. проекты сделаны давно, а статья написана по следам этих проектов, поэтому я мог упустить нюансы. Обо всех замеченных недочётах и ошибках вы можете писать мне в комментариях, буду рад вашим отзывам.&lt;/p&gt;
</description>
</item>

<item>
<title>PHP сервер для рассылки Push на Android и iOS</title>
<guid isPermaLink="false">326</guid>
<link>https://alexbirukov.ru/?go=all/php-server-dlya-rassylki-push-na-android-i-ios/</link>
<pubDate>Fri, 02 Oct 2015 14:13:19 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/php-server-dlya-rassylki-push-na-android-i-ios/</comments>
<description>
&lt;p&gt;Долгое время искал в интернете нормальное решение для массовой рассылки Push сообщений на Android и iOS, но ничего подходящего и нормально работающего не попадалось.&lt;/p&gt;
&lt;p&gt;В Delphi долгое время приходилось использовать компоненты Kinvey (или Pasre). При этом возникали новые проблемы зависимости от платформы, ключей и пр. С любым серьёзным изменением приходилось изменять, как сам проект, так и настройки проекта. В некоторых случаях сторонние компоненты отказывались работать на той или иной платформе по не понятной причине. А так же, огромным минусом Kinvey, было то, что при получении Push сообщения на iOS не воспроизводилось звуковое уведомление. В конце концов, зависимость от третьей стороны всегда является определённым минусом любого проекта.&lt;/p&gt;
&lt;p&gt;И вот после очередных поисков я объединил все имеющиеся знания и сделал серверную часть для регистрации устройств и рассылки Push сообщений.&lt;/p&gt;
&lt;p&gt;Принцип работы скрипта достаточно прост. В нём имеются функции для регистрации (удаления) токенов устройств, ну и собственно сами функции рассылки. Большая часть мануалов? которые мне удалось найти были написаны либо неправильно, либо попросту были неполными.&lt;/p&gt;
&lt;h2&gt;Введение&lt;/h2&gt;
&lt;p&gt;Немного теории. Для отправки Push сообщений используются сервисы &lt;a href="https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html"&gt;APNS&lt;/a&gt; у Apple и &lt;a href="http://developer.android.com/google/gcm/index.html"&gt;GCM&lt;/a&gt; у Google. Наш скрипт может выступать в качестве самостоятельного сервера рассылки Push через сервера Apple и Google, а так же принимать токены устройств регистрируемых в базе данных.&lt;/p&gt;
&lt;h2&gt;Apple, iOS и ApnsPHP&lt;/h2&gt;
&lt;p&gt;Начнём с более сложной части.&lt;br /&gt;
Я не стану изобретать велосипед и воспользуюсь уже имеющимися в сети, бесплатными, библиотеками написанными на PHP. Набор библиотек ApnsPHP представляет собой набор классов для работы с Push сообщениями APNS. Скачать их с примерами можно на GitHub по &lt;a href="https://github.com/immobiliare/ApnsPHP/tree/master/ApnsPHP"&gt;ссылке&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Но одних библиотек нам мало. Самое сложное, это генерация и конвертирование сертификатов для работы с Push на iOS. Я опишу полный алгоритм экспорта и конвертации сертификатов, а затем их дальнейшее применение в скриптах.&lt;/p&gt;
&lt;h3&gt;Генерация сертификата для отправки Push сообщений&lt;/h3&gt;
&lt;p&gt;Будем предполагать, что вы уже создали и настроили сертификаты в личном кабинете разработчика и загрузили их в «Связку ключей» на ваш Mac.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Запускаем утилиту &lt;b&gt;«Связка ключей»&lt;/b&gt; и в левой части выбираем раздел &lt;b&gt;«Мои сертификаты»&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Раскрываем сертификат интересующего нас проекта. &lt;b&gt;БУДЬТЕ ВНИМАТЕЛЬНЫ!&lt;/b&gt; Есть две версии сертификатов, &lt;b&gt;Developer&lt;/b&gt; (используется при отладке и разработке) и &lt;b&gt;Production&lt;/b&gt; (используется для рабочей версии). Выбираем сертификат и закрытый ключ данного сертификата.&lt;/li&gt;
&lt;li&gt;Нажимаем правой кнопкой и выбираем пункт «Экспортировать объектов: 2». Сохраняем полученные сертификаты. Я сохранил с именами &lt;i&gt;&lt;b&gt;server_certificates_bundle_sandbox.p12&lt;/b&gt;&lt;/i&gt; (для сертификата разработки) и &lt;i&gt;&lt;b&gt;server_certificates_bundle_prod.p12&lt;/b&gt;&lt;/i&gt; (для сертификата публикации). &lt;b&gt;Внимание!&lt;/b&gt; При экспорте поле пароля оставляем пустым. В дальнейшем вы сможете усложнить систему защиты и выгрузить сертификаты с указанием пароля.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Для подтверждения валидности сертификатов пользователя которые мы только что получили, необходим корневой сертификат. Для получения корневого сертификата необходимо выполнить следующие действия:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Переходим на &lt;a href="https://www.entrust.net/downloads/root_index.cfm"&gt;сайт загрузки корневых сертификатов&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Выбираем &lt;b&gt;«Personal Use and Secure Server Installation»&lt;/b&gt; и нажимаем кнопку &lt;b&gt;«Download Certificates»&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Нажимаем на &lt;b&gt;«Root Certificates»&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Нас интересуют два сертификата &lt;b&gt;«entrust_ssl_ca.cer»&lt;/b&gt; и &lt;b&gt;«entrust_2048_ca.cer»&lt;/b&gt;. Скачиваем их. Вообще, в изначальном описании написано, что сертификат «entrust_ssl_ca.cer» используется в &lt;b&gt;Prodution&lt;/b&gt; режиме, а «entrust_2048_ca.cer» в режиме &lt;b&gt;Development&lt;/b&gt;. Но есть пометка, что после 22 декабря 2010 в качестве Production сертификата так же можно использовать «entrust_2048_ca.cer». &lt;b&gt;&lt;i&gt;Т. е. данный сертификат можно использовать в обоих режимах работы, меняя лишь сертификаты пользователя&lt;/i&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/keychain.png" width="1280" height="1024" alt="Открываем "Связку ключей"" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/keychain-2.png" width="1280" height="1024" alt="Экспортируем сертификаты" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Далее, нам необходимо открыть скачанные сертификаты на Mac’е, т. е. импортировать их в «Связку ключей». Для этого просто делаем двойной клик на каждом сертификате.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Открываем в левой части &lt;b&gt;«Связки ключей»&lt;/b&gt; раздел &lt;b&gt;«Вход»&lt;/b&gt; («Сертификаты»).&lt;/li&gt;
&lt;li&gt;Находим наш сертификат и экспортируем его &lt;b&gt;«entrust_root_certification_authority_2048.pem»&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/keychain3.png" width="1280" height="1024" alt="Открываем корневой сертификат." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/keychain4.png" width="1280" height="1024" alt="Экспортируем сертификат." /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;На данный момент, мы получили 3 основных файла для работы с сервисом APNS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;«entrust_root_certification_authority_2048.pem»&lt;/b&gt; — корневой сертификат.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;«server_certificates_bundle_sandbox.p12»&lt;/b&gt; — сертификат пользователя для режима Development.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;«server_certificates_bundle_prod.p12»&lt;/b&gt; — сертификат пользователя для режима Production.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Как можно заметить, сертификаты пользователя имеют расширение *.p12, но для работы нам необходимы файлы формата *.pem.&lt;/p&gt;
&lt;p&gt;Для конвертации я воспользовался бесплатным набором утилит &lt;a href="https://slproweb.com/products/Win32OpenSSL.html"&gt;OpenSSL для Windows&lt;/a&gt;.&lt;br /&gt;
После установки пакета, для простоты выполнения команд я использовал TotalCommander.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Открываем в левой части каталог установленного OpenSSL и переносим туда наши сертификаты.&lt;/li&gt;
&lt;li&gt;В нижней части TotalCommander в командной строке выполняем следующие команды:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;openssl pkcs12 -in server_certificates_bundle_sandbox.p12 -out server_certificates_bundle_sandbox.pem -nodes -clcerts
openssl pkcs12 -in server_certificates_bundle_prod.p12 -out server_certificates_bundle_prod.pem -nodes -clcerts&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;На запрос ввода пароля, просто нажимаем Enter.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/convert.png" width="1280" height="1024" alt="Подготавливаем сертификаты и программу." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/convert2.png" width="1280" height="1024" alt="Сертификаты." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/convert4.png" width="1280" height="1024" alt="Выполнение команд конвертации сертификатов." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/convert5.png" width="1280" height="1024" alt="Просто нажимаем Enter." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/convert3.png" width="1280" height="1024" alt="Готовые сертификаты." /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;И так, теперь у нас есть набор необходимых сертификатов для работы с Push сообщениями на iOS.&lt;/p&gt;
&lt;h2&gt;Google и GCM&lt;/h2&gt;
&lt;p&gt;Для работы с Google и GCM мы будем использовать библиотеку &lt;a href="https://github.com/CodeMonkeysRu/GCMMessage"&gt;GCM PHP Server Library&lt;/a&gt;. Скачанный архив библиотек и пример работы из коробки у меня по какой-то причине отказался работать, поэтому пришлось немного модифицировать код.&lt;/p&gt;
&lt;p&gt;Для работы с GCM нам потребуется API ключ проекта. Выполняем следующие действия:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Открываем &lt;a href="https://console.developers.google.com/project"&gt;консоль разработчика Google&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Выбираем интересующий нас проект.&lt;/li&gt;
&lt;li&gt;Открываем раздел &lt;b&gt;«APIs &amp; auth»&lt;/b&gt; — &lt;b&gt;«Credentials»&lt;/b&gt; и копируем ключ Server Key.&lt;/li&gt;
&lt;li&gt;Если вы ещё не создавали ключи, то вам потребуется включить API «Google Cloud Messaging for Android».&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/apikey.png" width="1280" height="864" alt="API ключ." /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь у нас имеются все необходимые данные для организации PHP сервера рассылки Push сообщений.&lt;/p&gt;
&lt;h2&gt;База данных&lt;/h2&gt;
&lt;p&gt;Для рассылки Push сообщений на устройства пользователей используются токены устройств, которые выдаётся серверами Google и Apple, т. е. для получения Push сообщения, токен устройства должен быть зарегистрирован в системе. Наш сервер так же отправки Push сообщений будет использовать токены устройств. Для хранения токено устройств, ID устройств и платформы я использовал базу данных.&lt;/p&gt;
&lt;p&gt;Текст скрипта для создания базы данных выглядит так.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;CREATE TABLE devices (
  id int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Уникальный идентификатор  записи в таблице',
  deviceID varchar(255) NOT NULL COMMENT 'Идентификатор устройства',
  deviceToken varchar(255) NOT NULL COMMENT 'Токен устройства',
  devicePlatform varchar(255) NOT NULL COMMENT 'Платформа устройства',
  PRIMARY KEY (id),
  UNIQUE INDEX deviceID (deviceID)
)
ENGINE = MYISAM
AUTO_INCREMENT = 20
AVG_ROW_LENGTH = 166
CHARACTER SET utf8
COLLATE utf8_general_ci
COMMENT = 'Зарегистрированные устройства для рассылки PUSH сообщений';&lt;/code&gt;&lt;/pre&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/db-table.png" width="263" height="179" alt="Таблица для хранения токенов." /&gt;
&lt;/div&gt;
&lt;p&gt;Для добавления устройств в базу данных используется отдельная функция скрипта сервера, но об этом чуть позже.&lt;/p&gt;
&lt;h2&gt;Сервер&lt;/h2&gt;
&lt;p&gt;Переходим к самому серверу и его настройке. Все файлы я выложу отдельным архивом.&lt;br /&gt;
Суть скрипта состоит в следующем: подключаем библиотеки для работы с Push, настраиваем сертификаты и API ключ и с помощью имеющихся функций выполняем необходимые действия, будь то рассылка сообщений, регистрация устройств и пр.&lt;/p&gt;
&lt;p&gt;В состав сервера входит файл конфигурации. Приведу отдельно его текст.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;&amp;lt;?php

# Переменные для работы  с базой данных
$config['db']['host'] = &amp;quot;localhost&amp;quot;;
$config['db']['name'] = &amp;quot;Имя БД&amp;quot;;
$config['db']['user'] = &amp;quot;Пользователь БД&amp;quot;;
$config['db']['pass'] = &amp;quot;Пароль БД&amp;quot;;

# Управление рассылкой. True - рассылка производится, false - рассылка отключена.
$config['apn']['send'] = true;
$config['gcm']['send'] = true;

# Ключи для доступа к сервисам
# Ключ для доступа Google Server API
$config['gcm']['apikey'] = &amp;quot;ВАШ API КЛЮЧ&amp;quot;;
# Путь к сертификатам APN для подключения к серверу рассылки
$config['apn']['sert'] = 'Certificates/server_certificates_bundle_sandbox.pem';
$config['apn']['sert_prod'] = 'Certificates/server_certificates_bundle_prod.pem';
$config['apn']['RootCertificat'] = 'Certificates/entrust_root_certification_authority_2048.pem';
$config['apn']['production'] = false;

?&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Думаю, что раздел конфигурации базы данных не требует объяснения, тут надо указать настройки для доступа к базе данных, в которой хранится таблица &lt;b&gt;«Devices»&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Параметры:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$config['apn']['send'] = true;
$config['gcm']['send'] = true;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Отвечают за включение или отключение рассылки Push сообщений, если значение false, то рассылка на указанную платформу не производится.&lt;/p&gt;
&lt;p&gt;Дальше идут настройки API ключа и указание каталогов сертификатов, что в общем-то тоже я думаю понятно всем.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# Ключи для доступа к сервисам
# Ключ для доступа Google Server API
$config['gcm']['apikey'] = &amp;quot;ВАШ API КЛЮЧ&amp;quot;;
# Путь к сертификатам APN для подключения к серверу рассылки
$config['apn']['sert'] = 'Certificates/server_certificates_bundle_sandbox.pem';
$config['apn']['sert_prod'] = 'Certificates/server_certificates_bundle_prod.pem';
$config['apn']['RootCertificat'] = 'Certificates/entrust_root_certification_authority_2048.pem';&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Отдельно рассмотрим ключ:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$config['apn']['production'] = false;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Данный ключ переключает режим работы сервера. Development или Production режимы рассылки.&lt;/p&gt;
&lt;p&gt;Как можно заметить, все сертификаты необходимо положить в каталог «Certificates» рядом со скрипом.&lt;/p&gt;
&lt;p&gt;Если при генерации сертификатов Apn использовался пароль, то в настройках, необходимо указать пароль:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$config['apn']['sertPass'] = 'пароль сертификата';&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Работа со скриптом&lt;/h2&gt;
&lt;p&gt;После заполнения файла конфигурации скрипт готов к работе, осталось зарегистрировать устройства.&lt;br /&gt;
Скрипт сервера push.php принимает 2 значения параметра &lt;b&gt;action&lt;/b&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;register-device&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;send-push&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В каждом действии требуются дополнительные параметры. Для регистрации устройства дополнительными параметрами являются:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;did&lt;/b&gt; — Идентификатор устройства (не используется, но на всякий случай).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;token&lt;/b&gt; — токен устройства, используется для рассылки Push сообщений.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;platform&lt;/b&gt; — платформа устройства, используется функциями рассылки. Может принимать 2 значения: &lt;b&gt;ios&lt;/b&gt; или &lt;b&gt;andoid&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для рассылки Push сообщений используется действие send-push и принимается всего 1 дополнительный параметр: &lt;b&gt;text&lt;/b&gt; — текст Push сообщения.&lt;/p&gt;
&lt;p&gt;Примеры запросов:&lt;/p&gt;
&lt;p&gt;Регистрация устройства iOS&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;http://example.ru/push.php?action=register-device&amp;amp;did=DC92EFED-9271&amp;amp;token=feaab9d122f53a4fdca&amp;amp;platform=ios&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Регистрация устройства Android&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;http://example.ru/push.php?action=register-device&amp;amp;did=DC92EFED-9271&amp;amp;token=feaab9d122f53a4fdca&amp;amp;platform=andoid&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Отправка Push сообщений&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;http://example.ru/push.php?action=send-push&amp;amp;text=Добрый день, мой господин!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Первые два запроса регистрируют устройства в базе данных и в момент рассылки скрипты выбирает токены устройств по полю platform и производит отправку Push сообщений.&lt;/p&gt;
&lt;p&gt;Второй запрос производит рассылку Push сообщения все зарегистрированным устройствам.&lt;/p&gt;
&lt;p&gt;В общем-то, всё достаточно просто, каждый желающий может в дальнейшем модифицировать скрипт по своему желанию, вводя защиту от несанкционированного доступа и пр. Прошу меня не пинать, за полное отсутствие защиты в скрипте, скрипт призван показать логику и рабочий пример работы с Push сообщениями. Плюс данного скрипта состоят в том, что данные мы можем отправлять с любой платформы, будь то веб форма, Windiws приложения или мобильные приложения.&lt;/p&gt;
&lt;h2&gt;Delphi&lt;/h2&gt;
&lt;p&gt;Настало время рассмотреть небольшой код написанный для Delphi, который позволяет регистрировать токены устройств на нашем сервере. Каждое мобильное устройство после запуска приложения получает свой DeviceID и токен, после чего отправляет полученные данные на наш сервер.&lt;/p&gt;
&lt;p&gt;В разделе public нашего юнита добавляем следующие строки:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;public
    { Public declarations }
    APushService : TPushService;
    AServiceConnection : TPushServiceConnection;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А в раздел type добавляем описание 2-х функций:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;procedure OnReceiveNotificationEvent(Sender: TObject; const ANotification : TPushServiceNotification);
    procedure OnServiceConnectionChange(Sender: TObject; AChange : TPushService.TChanges);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В момент отображения формы добавляем код получения DID и токена. Будьте внимательны, значение &lt;b&gt;PROJECTNUM&lt;/b&gt; необходимо заменить на свой номер проекта из личного кабинета Google разработчика.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;/// На данном этапе происходит регистрация устройства для получения Push.
procedure TMainForm.FormShow(Sender: TObject);
var
  ADeviceID, ADeviceToken : string;
begin

  // Получение и отправка токена устройства
  {$ifdef ANDROID}
    // Для Android
    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);
    APushService.AppProps[ TPushService.TAppPropNames.GCMAppID ] := 'PROJECTNUM';
  {$else}
    // Для iOS
    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS);
  {$endif}
  // Создаём подключение к серверу
  AServiceConnection := TPushServiceConnection.Create( APushService );
  // Активируем подключение
  AServiceConnection.Active   := True;
  // Подключаем делегаты
  AServiceConnection.OnChange := OnServiceConnectionChange;
  AServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent;

  ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];
  ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];

  if (ADeviceID &amp;lt;&amp;gt; '') AND (ADeviceToken &amp;lt;&amp;gt; '') then
  begin

    // Регистрируем устройство на сервере для отправки push сообщений
    RegisterDevice(ADeviceID, ADeviceToken);

  end;

end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так же, надо добавить функцию, которая срабатывает при изменении состояния получения DID и токена.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;/// Устройства не всегда успевают получить токен,
/// поэтому при изменении состояния опять проверяем токен
procedure TMainForm.OnServiceConnectionChange(Sender: TObject;
  AChange : TPushService.TChanges);
var
  ADeviceID, ADeviceToken : string;
begin
    // При измении состояния компонента
    ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];
    ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];

    if (ADeviceID &amp;lt;&amp;gt; '') AND (ADeviceToken &amp;lt;&amp;gt; '') then
    begin

      // Регистрируем устройство на сервере для отправки push сообщений
      RegisterDevice(ADeviceID, ADeviceToken);

    end;
end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Для вывода Push сообщения добавляем функцию:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;/// Процедура вывода сообщение при получении Push уведомления от сервера
procedure TMainForm.OnReceiveNotificationEvent(Sender: TObject;
  const ANotification : TPushServiceNotification);
var
  MessageText : string;
begin
  // Получаем текст сообщения в зависимости ль платформы
  {$ifdef ANDROID}
    MessageText := ANotification.DataObject.GetValue('message').Value;
  {$else}
    MessageText := ANotification.DataObject.GetValue('alert').Value;
  {$endif};

  // Выводим сообщение
  ShowNotification(MessageText, 0);
end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В результате мы получаем почти готовую программу. Кто был более внимательным, заметил, что в коде есть несколько функций, не объявленных ранее, таких как &lt;b&gt;ShowNotification&lt;/b&gt; или &lt;b&gt;RegisterDevice&lt;/b&gt;. Для удобства, я вынес их в отдельный файл global.pas. Достаточно добавить данный файл в проект, чтобы не копипастить функции. В данном файле вам потребуется заменить константу DOMAIN для указания пути к файлу скрипта на сервере, и если вы положили скрипт не в корне сервера, а в случайный каталог, то потребуется внести дополнительные изменения для указания точной адресации.&lt;/p&gt;
&lt;p&gt;Так же имеется функция &lt;b&gt;SendPush&lt;/b&gt;, которая позволяет отправлять Push сообщения прямо с устройства.&lt;/p&gt;
&lt;p&gt;Все функции в файле global.pas имеют подробное описание и думаю их использование не вызовет никаких вопросов.&lt;/p&gt;
&lt;p&gt;Таким образом мы получаем устройства, которые регистрируются в системе, отправляя свои DID и токены скрипту, а скрипт записывает их в базу данных для дальнейшего использования при отправке Push сообщений. Если в базе имеются токены устройств, на которых программа не установлен (удалена), то такие токены будут удалены из базы данных после попытки отправки Push сообщений.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/db.png" width="751" height="128" alt="Зарегистрированные устройства." /&gt;
&lt;/div&gt;
&lt;h2&gt;Используемые файлы.&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://alexbirukov.ru/files/push-server/global.pas"&gt;Файл global.pas&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://alexbirukov.ru/files/push-server/Push_Server.7z"&gt;PHP сервер Push сообщений&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Заключение&lt;/h2&gt;
&lt;p&gt;В данной статье я попытался максимально подробно изложить принципы и алгоритмы работы с Push сообщениями с использованием дополнительных библиотек GCMMessage и ApnsPHP в php скрипте и взаимодействие с программным обеспечением (в моём случае Windows приложения и мобильные платформы).&lt;/p&gt;
&lt;p&gt;Данная статья не претендует на оригинальность и истину последней инстанции. Имеются открытые места в безопасности, такие, как сертификаты без паролей, открытый доступ к функциям скрипта без идентификации пользователей и пр.&lt;/p&gt;
&lt;p&gt;Если у кого-нибудь будет желание доработать данный скрипт в плане безопасности или внести поправки я буду только рад. Ваши изменения и замечания вы можете писать в комментариях к статье.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Для удобства, загрузил проект на &lt;a href="https://github.com/alexbirukov/PHP-Push-Sender"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE 2&lt;/b&gt; из комментария читателя&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Если у кого не работает на Rad Studio 10.2, то вместо «AServiceConnection.Active := True;» сделайте так:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Активируем подключение
TTask.Run(
procedure
begin
AServiceConnection.Active := True;
end
);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В uses должно быть System.Threading.&lt;/p&gt;
</description>
</item>

<item>
<title>Ошибки и косяки Delphi XE10 Seattle и xCode 7</title>
<guid isPermaLink="false">325</guid>
<link>https://alexbirukov.ru/?go=all/oshibki-i-kosyaki-xe10-seattle-i-xcode-7/</link>
<pubDate>Mon, 21 Sep 2015 16:55:06 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/oshibki-i-kosyaki-xe10-seattle-i-xcode-7/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/maxresdefault.jpg" width="1280" height="720" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;И так, пока русскоязычная и англоязычная части интернета молчат по поводу работы в новой Delphi XE10 Seattle в связке с xCode 7, а компании представители описывают, какое замечательное вышло обновление, пользователи столкнулись с проблемой, что приложения, сделанные на XE10 Seattle, xCode 7 + SDK9, не запускаются на предыдущих платформах.&lt;/p&gt;
&lt;p&gt;Не совсем понятно, почему в упомянутых сегментах интернета нет совершенно никакой информации по данному поводу. Опять впереди планеты все &lt;a href="http://www.cnblogs.com/onechen/p/4821280.html"&gt;Китай&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Пользователь блога подробно описывает конфигурацию, на которой он тестировал запуск приложения и описание проблемы. Несколько реальных устройств на разных прошивках, разные версии ПО и пр.&lt;/p&gt;
&lt;p&gt;Коротко о главном. Если вы хотите, как можно скорей перейти на новую Delphi XE10 Seattle с целью писать свежие приложения\обновления для iOS, спешу вас разочаровать. Ваши программы перестанут работать на предыдущих версиях iOS. Статистика испытаний такова, что приложения собранные на XE10 Seattle, xCode 7 + SDK9 будут работать только на устройствах под управлением iOS9.&lt;/p&gt;
&lt;p&gt;Вторая проблема, состоит в том, что недавнего времени AppStore при проверке приложений стала проверять их именно на iOS 9, а приложения собранные на XE8.1 такую проверку не проходят, так как зависают на стартовой заставке приложения и как следствие их отклоняют. Вот так то. Прошла уже целая неделя, а интернет по данному поводу ничего сказать нам особо не может.&lt;/p&gt;
&lt;p&gt;На днях появилась &lt;a href="http://community.embarcadero.com/blogs/entry/workaround-steps-for-building-ios-32-bit-applications-for-ios-9-with-xe7-and-xe8"&gt;статья от Сарины Дю Понт&lt;/a&gt;, о том, как всё же запустить приложение сделанные в XE8.1 на iOS9.&lt;/p&gt;
&lt;p&gt;В результате изысканий Китайских друзей, получаем на данный момент такую картину:&lt;/p&gt;
&lt;p&gt;XE8 + iOS 6 = полёт нормальный&lt;br /&gt;
XE8 + iOS 7 = полёт нормальный&lt;br /&gt;
XE8 + iOS 8 = полёт нормальный&lt;br /&gt;
XE8 + iOS 9 = зависание на экране заставки (если не воспользоваться советом Сарины)&lt;/p&gt;
&lt;p&gt;XE10 + iOS 6 = приложение вылетает&lt;br /&gt;
XE10 + iOS 7 = приложение вылетает&lt;br /&gt;
XE10 + iOS 8 = приложение вылетает&lt;br /&gt;
XE10 + iOS 9 = полёт нормальный&lt;/p&gt;
&lt;p&gt;Таким образом в XE10 Seattle и xCode 7 можно получить на данный момент только приложение, работающее на iOS9.&lt;/p&gt;
&lt;p&gt;Ждём Delphi XE10 Seattle Update 1.&lt;/p&gt;
&lt;p&gt;P.S. А в на Android в Delphi XE10 Seattle приложение с компонентами для отправки Push не запускается в режиме Release — Application Store. Что тоже, очень и очень печально.&lt;/p&gt;
</description>
</item>

<item>
<title>Ошибка ERROR ITMS-90507 при публикации приложения в AppStore</title>
<guid isPermaLink="false">324</guid>
<link>https://alexbirukov.ru/?go=all/oshibka-error-itms-90507-pri-publikacii-prilozheniya-v-appstore/</link>
<pubDate>Fri, 28 Aug 2015 22:06:18 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/oshibka-error-itms-90507-pri-publikacii-prilozheniya-v-appstore/</comments>
<description>
&lt;h2&gt;Преамбула&lt;/h2&gt;
&lt;p&gt;В последнее время всё реже и реже встречаются статьи связанные с Delphi, при том, что язык в принципе развивается и появляются большие возможности в плане создания кроссплатформенных мобильных приложений. При этом в русскоязычной части интернета информации крайне мало, люди делятся знаниями крайне неохотно и большая часть ответов носит поверхностный характер. И это при том, что большая часть программистов училась именно на pascal и регулярно пишет приложения с использованием продуктов Borland (Embarcadero).&lt;/p&gt;
&lt;p&gt;В связи с этим, решил начать публиковать статьи связанные с разработкой мобильных и десктопных приложений на Delphi.&lt;/p&gt;
&lt;h2&gt;Соль&lt;/h2&gt;
&lt;p&gt;Apple регулярно ужесточает требования к описанию программ публикуемых в AppStore. И большое количество проблем, вызывает правильность формирования и описания содержимого файла Info.plist. В файле описывается приложение, версия, билд, наименование модулей и пр. С проблемами сталкиваются не только те, кто программирует на Delphi, но пользователи других сред.&lt;/p&gt;
&lt;p&gt;С недавнего времени при публикации приложения стала появляться ошибка &lt;b&gt;ERROR ITMS-90507: Missing Info.plist value. A value for the key ’DTPlatformName’ is required&lt;/b&gt;, которая сообщает программисту о том, что необходимый ключ &lt;b&gt;DTPlatformName&lt;/b&gt; не найден в файле Info.plist.&lt;/p&gt;
&lt;p&gt;Для исправления ошибки, необходимо выполнить следующие действия:&lt;/p&gt;
&lt;p&gt;Открываем настройки проекта и добавляем ключ для настроек «iOS 64 bits — Release».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/03000003.png" width="1164" height="761" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Имя ключа &lt;b&gt;DTPlatformName&lt;/b&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/03000004.png" width="430" height="121" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Указываем значение ключа «iphoneos». И сохраняем настройки. Теперь приложение должно без проблем быть принято к публикации в AppStore.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/03000005.png" width="1174" height="767" alt="" /&gt;
&lt;/div&gt;
</description>
</item>

<item>
<title>Аудио-плеер на Delphi для Android с применением библиотеки BASS.</title>
<guid isPermaLink="false">316</guid>
<link>https://alexbirukov.ru/?go=all/udio-pleer-na-delphi-dlya-android-code-gear-rad-studio-xe7/</link>
<pubDate>Tue, 24 Mar 2015 09:48:04 +0500</pubDate>
<author></author>
<comments>https://alexbirukov.ru/?go=all/udio-pleer-na-delphi-dlya-android-code-gear-rad-studio-xe7/</comments>
<description>
&lt;p&gt;В середине прошлого года появилась необходимость написания простого приложения для мобильных платформ Android и iOS. Первым рабочим проектом стал &lt;a href="http://alexbirukov.ru/?go=tags/kteam/"&gt;KTeam&lt;/a&gt;. После его успешного запуска, появилась необходимость написания аудио-плеера, способного воспроизводить потоковое вещание интернет радиостанций.&lt;/p&gt;
&lt;p&gt;И так, сегодня я подробно опишу, как создать простой плеер потокового вещания.&lt;/p&gt;
&lt;p&gt;Для работы нам понадобятся среда программирования Code Gear RAD Studio XE7, работать я рекомендую именно в данной версии программы, т. к. в используемых библиотеках, имеются некоторые не стыковки в работе с предыдущими версиями.&lt;/p&gt;
&lt;p&gt;По причине того, что встроенных средств проигрывания интернет потока не имеется, мы воспользуемся замечательной библиотекой BASS, для написания приложения для Android (для iOS следует использовать другие компоненты).&lt;/p&gt;
&lt;p&gt;Для корректной работы библиотеки BASS я рекомендую так же установить компоненты &lt;a href="http://sourceforge.net/projects/dpfdelphiandroid/"&gt;DPF Android Native Components&lt;/a&gt;, я в своём примере буду использовать версию 2.8.6.&lt;/p&gt;
&lt;h2&gt;Начало&lt;/h2&gt;
&lt;p&gt;Ну я думаю процесс установки Code Gear RAD Studio XE7 описывать не стоит, поэтому сразу переходим к установке дополнительных компонентов и библиотек, потому что именно эта часть вызывает наибольшие проблемы, и именно поэтому данный этап я опишу наиболее подробно.&lt;/p&gt;
&lt;h2&gt;BASS&lt;/h2&gt;
&lt;p&gt;Идём на &lt;a href="http://www.un4seen.com"&gt;официальный сайт un4seen.com&lt;/a&gt; библиотеки, нажимаем в левом меню на ссылку &lt;a href="http://www.un4seen.com/bass.html"&gt;BASS&lt;/a&gt; и скачиваем там последнюю версию для &lt;a href="http://www.un4seen.com/forum/?topic=13225"&gt;Android&lt;/a&gt;. На момент написания данной статьи на сайте опубликована версия 2.4 от 13 марта 2015 года. &lt;a href="http://www.un4seen.com/stuff/bass24-android.zip"&gt;Прямая ссылка&lt;/a&gt; на скачивание библиотеки с официального сайта. &lt;a href="http://alexbirukov.ru/files/radio-andr/bass24-android.zip"&gt;Ссылка на скачивание с моего сайта&lt;/a&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1276" data-ratio="1.3632478632479"&gt;
&lt;img src="https://alexbirukov.ru/pictures/-2015-03-24-09.25.46.png" width="1276" height="936" alt="Сайт библиотеки BASS" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/-2015-03-24-09.29.03.png" width="1274" height="959" alt="Ссылки на скачивание библиотек" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;i&gt;&lt;b&gt;Примечание:&lt;/b&gt; я рекомендую использовать именно данную версию библиотеки, потому что предыдущие версии не работают с XE7, и при инициализации библиотеки появляется ошибка.&lt;/i&gt;&lt;/p&gt;
&lt;h2&gt;BASSFunctions&lt;/h2&gt;
&lt;p&gt;Для корректной работы с библиотекой, нам потребуется ещё один дополнительный файл, это &lt;a href="http://alexbirukov.ru/files/radio-andr/BASSFunctions.pas"&gt;BASSFunctions.pas&lt;/a&gt;. Данный файл опубликовал на форуме пользователь с ником 3delite.&lt;a href="http://www.3delite.hu/Object%20Pascal%20Developer%20Resources/Download/BASSFunctions.pas"&gt;Ссылка&lt;/a&gt; на оригинальный файл.&lt;/p&gt;
&lt;h2&gt;DPF Android Native Components&lt;/h2&gt;
&lt;p&gt;Для корректной работы библиотек BASS, часто требуется установка компонентов DPF Android Native Components, т. к. в их составе имеется компонент для работы с аудио, без которого компилятор будет просто выдавать ошибку.&lt;/p&gt;
&lt;p&gt;Идём на &lt;a href="http://sourceforge.net/projects/dpfdelphiandroid/"&gt;официальный сайт&lt;/a&gt; и скачиваем последнюю версию компонентов. Или вы можете скачать версию &lt;a href="http://alexbirukov.ru/files/radio-andr/DPF.Android.Native.Components.v2.8.6.zip"&gt;2.8.6&lt;/a&gt; с моего сайта.&lt;/p&gt;
&lt;h2&gt;Поехали&lt;/h2&gt;
&lt;p&gt;После того, как мы скачали все необходимые дополнительные файлы, приступаем к установке компонентов.&lt;/p&gt;
&lt;p&gt;Начнём с DPF Android Native Components. Я рекомендую (во избежании дополнительных проблем с подключением) распаковать файлы в папку DPF.Android.Native.Components.v2.8.6 в корень диска C.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-09-55-10.png" width="1280" height="1024" alt="Распаковываем файлы" /&gt;
&lt;/div&gt;
&lt;p&gt;В каталоге с файлами, имеется файл Install.txt. У кого хорошо с английским, могут сделать всё по инструкции описанной в файле, для тех кто в школе учил немецкий, я опишу процесс установки компонентов подробно.&lt;/p&gt;
&lt;p&gt;Запускаем Codegear RAD Studio. Далее в верхнем меню открываем Tools-&gt;Options-&gt;Delphi Options-&gt;Library.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-09-58-33.png" width="1280" height="1024" alt="" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-00-13.png" width="1280" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;В выпадающем списке справа выбираем платформу «32-bit Windows» и добавляем в раздел «Library path» путь к нашим компонентам.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-06.png" width="1280" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь то же самое проделываем для платформы «Android».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-55.png" width="1280" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Теперь нам потребуется скомпилировать и установить компоненты. Для этого нажимаем File -&gt; Open Project. Открываем проект из папки компонентов, соответствующий вашей среде программирования.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-06-17.png" width="1280" height="1024" alt="Открываем проект" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-06-31.png" width="1280" height="1024" alt="DPFAndroidPackagesXE7.dproj" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Далее нам надо скомпилировать проект и установить полученные компоненты.&lt;/p&gt;
&lt;p&gt;Нажимаем правой кнопкой на проекте в инспекторе проекта и выбираем пункт &lt;b&gt;«Build»&lt;/b&gt;, начнётся построение проекта.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-13-23.png" width="1280" height="1024" alt="Выполняем Build" /&gt;
&lt;/div&gt;
&lt;p&gt;После завершение построение, опять нажимаем правой кнопкой на проекте в инспекторе и выбираем пункт &lt;b&gt;«Install»&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Компоненты готовы к работе. Приступим к созданию проекта.&lt;/p&gt;
&lt;p&gt;Я набросал уже небольшой проект с парой кнопок для запуска и остановки проигрывателя и картинкой для привлечения внимания :)&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-24-28.png" width="1280" height="1024" alt="Пробный проект." /&gt;
&lt;/div&gt;
&lt;p&gt;Для работы в библиотекой BASS, нам потребуется в каталог с проектом добавить файл BASSFunctions.pas и указать его в разделе &lt;b&gt;uses&lt;/b&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-21-50.png" width="1280" height="1024" alt="Добавляем файл BASSFunctions.pas." /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-22-52.png" width="1280" height="1024" alt="Добавляем в раздел uses." /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Теперь собственно сама библиотека &lt;b&gt;libbass.so&lt;/b&gt;. Нам необходимо добавить данную библиотек в наш проект, иначе ничего не заработает.&lt;/p&gt;
&lt;p&gt;Открываем архив bass24-android.zip и видим... Множество папок, нас интересует на данный момент только одна &lt;b&gt;libs&lt;/b&gt;. Распаковываем её в каталог нашего проекта.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://alexbirukov.ru/pictures/-2015-03-24-10.29.21.png" width="1273" height="993" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В каталоге libs, есть три подкаталога, нас интересуют 2 из них:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;armeabi-v7a&lt;/li&gt;
&lt;li&gt;armeabi&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В них находятся два разных файла libbass.so.&lt;/p&gt;
&lt;p&gt;После того, как мы скопировали данный каталог в каталог проекта, снова возвращаемся к среде программирования и открываем раздел &lt;b&gt;Deployment&lt;/b&gt;, для добавления наших библиотек в программу.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-36-12.png" width="1280" height="1024" alt="Deployment" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-37-49.png" width="1280" height="1024" alt="Добавляем библиотеки" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-38-56.png" width="1280" height="1024" alt="" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-39-15.png" width="1280" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;После того, как мы добавили библиотеки в наш проект, надо поменять параметр «Remote Path» для каждой библиотеки соответственно на «&lt;b&gt;library\lib\armeabi&lt;/b&gt;» и на «&lt;b&gt;library\lib\armeabi-v7a&lt;/b&gt;». Данную процедуру надо проделать для обеих конфигураций «Debug» и «Release».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1280" data-ratio="1.25"&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-43-47.png" width="1280" height="1024" alt="Библиотеки" /&gt;
&lt;img src="https://alexbirukov.ru/pictures/Windows-7-x64-Delphi-XE7-2015-03-24-10-42-46.png" width="1280" height="1024" alt="Конфигурации "Debug" и "Release"" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ну что, вот всё и готово к началу написания кода, а код на самом деле достаточно простой.&lt;/p&gt;
&lt;p&gt;Объявляем глобальную переменную.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;var
  uStream:HSTREAM;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В момент создания формы инициализируем библиотеку.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;procedure TmainForm.FormCreate(Sender: TObject);
begin
  // Загружаем и инициализируем библиотеку
  Loadbass;
  BASS_Init(-1,44100,0,Handle,nil);
end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;На кнопку «Играть» вещаем обработчик:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;procedure TmainForm.mainToolbarBarItems1Click(Sender: TObject);
var
  otStream : TStringStream;
  Result : integer;
begin
  try

    // Включаем индикатор загрузки контента
    ind1.Enabled := True;
    ind1.Visible := True;

    // Код проигрывателя
    Result := 0;

    // Закрываем старый поток
    BASS_StreamFree(uStream);

    // Создаём новый поток
    uStream :=
      BASS_StreamCreateURL(PChar('http://motochelyabinsk.ru:8000/play'),0,BASS_STREAM_STATUS or BASS_UNICODE,nil,nil);

    // Включаем проигрывание
    BASS_ChannelPlay(uStream, True);

    // Получаем и выводим название текущего трека из скрипта на сайте
    // Создаём поток UTF8
    otStream := TStringStream.Create('', CP_UTF8);
    // Делаем запрос к скрипту сайта
    IdHTTP1.Get('motochelyabinsk.ru/current-track.php', otStream);
    IdHTTP1.Disconnect;
    // Записываем название трека в Label
    Label1.Text := otStream.DataString;
    // Очищаем переменную потока
    otStream.Free;

    // Запустить таймер отслеживания изменений названия трека
    Timer1.Enabled := True;

    // Включаем и отключаем кнопки
    btn1.Enabled := False;
    btn2.Enabled := True;

  except on E: Exception do
    begin
      ShowMessage('Ошибка доступа к сети!');
    end;
  end;

end;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну вот в общем самый простой и работающий пример создания проигрывателя интернет радиостанций.&lt;br /&gt;
P.S. Чуть позже, выложу готовый пример данного приложения.&lt;/p&gt;
</description>
</item>


</channel>
</rss>