{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "В наушниках по жизни: заметки с тегом программирование",
    "_rss_description": "Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/alexbirukov.ru\/?go=tags\/programmirovanie\/",
    "feed_url": "https:\/\/alexbirukov.ru\/?go=tags%2Fprogrammirovanie%2Fjson%2F",
    "icon": "https:\/\/alexbirukov.ru\/pictures\/userpic\/userpic@2x.jpg?1683051473",
    "authors": [
        {
            "name": "Бирюков Александр",
            "url": "https:\/\/alexbirukov.ru\/",
            "avatar": "https:\/\/alexbirukov.ru\/pictures\/userpic\/userpic@2x.jpg?1683051473"
        }
    ],
    "items": [
        {
            "id": "357",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/podklyuchenie-bluetooth-modulya-hm-10-mlt-bt05-cherez-programmat\/",
            "title": "Подключение Bluetooth модуля HM-10 (MLT-BT05) через программатор CH341A",
            "content_html": "<p>Всем привет.<\/p>\n<p>Сегодня обзавёлся простеньким Bluetooth модулем для работы с различными девайсами через BT, в частности, для беспроводного подключения к бортовому компьютеру квадрокоптера. Модуль был приобретён MLT-BT05, аналог HM-10. По различным причинам китайские модули часто бывают не совсем работоспособными «из коробки», а способы их проверки и прошивки требуют определённого навыка.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/module-hm-10-and-base-board-1-720x720.jpg\" width=\"720\" height=\"720\" alt=\"HM-10 (MLT-BT05)\" \/>\n<\/div>\n<p>Вот и я, купив данный модуль, не сразу понял, как же его по-быстрому проверить. После подключения к квадрокоптеру, было очевидно, что модуль рабочий и подключить к нему удаётся. Но для нормальной работы необходимо было проверить работу команд, ответы от модуля, а так же произвести некоторые настройки дефолтных параметров.<\/p>\n<p>После изучения материала в интернете, стало понятно, что для детальной настройки и проверки модуля потребуется подключить модуль посредством UART к компьютеру или квадрокоптеру. Но т. к. модуль не настроен, то и работать с квадрокоптером он отказывался. Интернет же настойчиво советует работать со специальным переходником USB-UART, и все статьи, как под копирку вторят этому.<\/p>\n<p>Идти покупать отдельный модуль USB-UART совершенно не хотелось, и я вспомнил, что у меня есть программатор CH341A, который не просто программатор, а мультифункциональный конвертер из USB 2.0 в UART, EPP, I2C и SPI. <a href=\"https:\/\/habr.com\/ru\/post\/262731\/\">Вот тут есть немного полезной информации<\/a>.<\/p>\n<p>Для работы по протоколу UART, необходимо переставить перемычку в положение 2-3 (изначально она установлена в положении 1-2). В видеоролике ниже всё показано более детально, поэтому не вижу смысла делать длинный мануал по переключению.<\/p>\n<div class=\"e2-text-video\">\n<iframe src=\"https:\/\/www.youtube.com\/embed\/AEEq7GMolls?enablejsapi=1\" allow=\"autoplay\" frameborder=\"0\" allowfullscreen><\/iframe>\n<\/div>\n<p>Всё достаточно просто. Теперь наш программатор готов для работы по проверке и настройке Bluetooth модуля HM-10 (MLT-BT05). Подключить Bluetooth модуль достаточно просто. Контакты VCC и GND подключаем соответственно к аналогичным разъёмам на программаторе, а TXD и RXD накрест.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/95a93das-960.jpg\" width=\"427\" height=\"140\" alt=\"\" \/>\n<\/div>\n<p>Для соединения устройств я использовал простые перемычки, которые продаётся в радиомагазинах или магазинах RC моделей.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14-23-09-02.JPG\" width=\"768\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<p>У меня получилось вот так.<br \/>\nДалее, остаётся лишь подключить программатор к компьютеру и открыть терминал для работы с COM портом. В моём случае, это порт COM10.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-13-06.png\" width=\"721\" height=\"253\" alt=\"\" \/>\n<\/div>\n<p>Теперь, зная номер порта, проверим, доступен ли модуль Bluetooth. Для этого я лично решил воспользоваться <a href=\"https:\/\/www.arduino.cc\/en\/Main\/Software\">Arduino IDE<\/a>, если точнее, то встроенным средством «Монитор порта».<\/p>\n<p>Для этого, после установки Arduino IDE, запускаем программу, открываем меню «Инструменты» -> «Порт» и выбираем COM порт. В моём случае это COM10.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-18-43.png\" width=\"670\" height=\"488\" alt=\"\" \/>\n<\/div>\n<p>И теперь, заходим в меню «Инструменты» -> «Монитор порта». Появится окно для ввода команд и просмотра ответов от модуля, подключенного к порту. Настройки скорости и конца строки должны быть выставлены так же, как на скриншоте.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-21-13.png\" width=\"1523\" height=\"427\" alt=\"\" \/>\n<\/div>\n<p>Теперь пришло время проверить работу команд и ответ. Для старта можно ввести команду AT. По умолчанию данный модуль находится в режиме приёма команд, но если имеется хотя бы одно подключенное устройство, то команды пониматься модулем не будут. Ввод команды <b>AT<\/b> должен вернуть ответ, в моём случае <b>«ОК»<\/b>.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-24-10.png\" width=\"572\" height=\"377\" alt=\"\" \/>\n<\/div>\n<p>Если набрать команду <b>AT+HELP<\/b>, то модуль выведет список всех доступных команд.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-26-56.png\" width=\"478\" height=\"533\" alt=\"\" \/>\n<\/div>\n<p>Больше всего меня интересовали следующие команды: <b>AT+VERSION<\/b>, для отображения версии прошивки модуля. У моего модуля версия прошивки <b>MLT-BT05-V4.4<\/b>.<\/p>\n<p>Далее, мне необходимо было изменить имя Bluetooth, которое отображается при поиске модуля. Для это используется команда «<b>AT+NAME<\/b>», которая в чистом виде вернёт текущее имя модуля, я же набрал её в варианте «<b>AT+NAMEAlex-BT<\/b>», тем самым установив имя модуля в значение «<b>Alex-BT<\/b>».<\/p>\n<p>Командой «AT+PIN» проверяем текущий пароль и ставим свой пароль при необходимости. Пароль по умолчанию «<b>123456<\/b>», учтите, минимальная длинна пароля 6 символов. Если попробовать установить пароль короче, будет выведена ошибка.<\/p>\n<p>Ну, и осталось поднять скорость работы модуля. Текущая скорость по умолчанию 9600 бод, а хотелось бы немного побольше. Для проверки текущей скорости необходимо выполнить команду «<b>AT+BAUD<\/b>». Будет отображен текeщий параметр, в случае если скорость 9600 бод, то будет выведено «<b>AT+BAUD4<\/b>».<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-38-59.png\" width=\"680\" height=\"373\" alt=\"\" \/>\n<\/div>\n<p>Для установки скорости 115200 бод необходимо выполнить команду «<b>AT+BAUD8<\/b>».<\/p>\n<p>Ну вот и всё. Проверка и базовая настройка модуля на этом завершена. Для более детальной настройки вы можете изучить даташиты модуля и посмотреть команды, которые поддерживает модуль.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-41-21.png\" width=\"216\" height=\"92\" alt=\"\" \/>\n<\/div>\n<p>Надеюсь, этот небольшой гайд поможет вам.<\/p>\n",
            "date_published": "2020-08-14T23:45:08+05:00",
            "date_modified": "2021-01-30T20:16:04+05:00",
            "tags": [
                "CH341A",
                "DIY",
                "квадрокоптер",
                "программирование",
                "прошивка"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/module-hm-10-and-base-board-1-720x720.jpg",
            "_date_published_rfc2822": "Fri, 14 Aug 2020 23:45:08 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "357",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/module-hm-10-and-base-board-1-720x720.jpg",
                    "https:\/\/alexbirukov.ru\/pictures\/remote\/youtube-AEEq7GMolls-cover.jpg",
                    "https:\/\/alexbirukov.ru\/pictures\/95a93das-960.jpg",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14-23-09-02.JPG",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-13-06.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-18-43.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-21-13.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-24-10.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-26-56.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-38-59.png",
                    "https:\/\/alexbirukov.ru\/pictures\/2020-08-14_23-41-21.png"
                ]
            }
        },
        {
            "id": "330",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/report-builder-for-synadyn-broadcast-1-0\/",
            "title": "Report Builder for Synadyn Broadcast 1.0",
            "content_html": "<p>Достаточно давно, ещё когда я работал на «Восточном Экспрессе» я <a href=\"http:\/\/alexbirukov.ru\/?go=2011\/10\/12\/1\/\">написал и выложил в свободный доступ<\/a> программу для генерации отчётов в РАО на основании отчётов о проигранных файлах, которые оставляет Synadyn Broadcast.<\/p>\n<p>Часто люди стали спрашивать у меня, можно ли сделать ту или иную модификацию, есть ли новые версии. И получилось так, что на данный момент есть более свежая версия программы, которую я ещё не публиковал. Её кардинальное отличие состоит в том, что данная версия позволяет создавать отчёты не за один месяц, а за необходимый период, собирая информацию из всех имеющихся файлов. Т. е. если вы указываете каталог, в который предварительно скопировали файлы отчётов за 3 месяца, то программа соберёт информацию из всех имеющихся фалов.<\/p>\n<p>Скомпилированная версия 1.0:<br \/>\n<a href=\"http:\/\/alexbirukov.ru\/files\/rb\/10\/Report-Builder-for-Synadin-Broadcast-1.0.7z\">Report Builder for Synadyn Broadcast 1.0<\/a><\/p>\n<p>Так же, для всех желающих, я выложил в открытый доступ исходные коды проекта:<br \/>\n<a href=\"https:\/\/github.com\/alexbirukov\/report-builder\">GitHub Report Builder for Synadyn Broadcast<\/a><\/p>\n<p>Убедительная просьба, если вы добавляете какой-либо функционал, который может быть полезен, создайте PullRequest на GitHub, чтобы включить ваши правки в новый релиз для развития проекта. Делитесь своими достижениями с другими.<\/p>\n<p>Данное программное обеспечение является совершенно бесплатным и поставляется как есть.<\/p>\n",
            "date_published": "2016-01-15T23:00:05+05:00",
            "date_modified": "2016-01-16T09:49:31+05:00",
            "tags": [
                "digiton",
                "Report Builder for Synadyn Broadcast",
                "Synadyn",
                "программирование",
                "программы",
                "проекты",
                "работа"
            ],
            "_date_published_rfc2822": "Fri, 15 Jan 2016 23:00:05 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "330",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "329",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/udio-pleer-na-delphi-dlya-ios-s-primeneniem-biblioteki-bass\/",
            "title": "Аудио-плеер на Delphi для iOS с применением библиотеки BASS.",
            "content_html": "<p>Прошло довольно много времени с момента написания первой статьи «<a href=\"http:\/\/alexbirukov.ru\/?go=all\/udio-pleer-na-delphi-dlya-android-code-gear-rad-studio-xe7\/\">Аудио-плеер на Delphi для Android с применением библиотеки BASS<\/a>». И теперь я решил написать вторую часть статьи про запуск и использование библиотеки BASS под iOS. В данном конкретном случае, так же? как и в предыдущей статье, целью подключения библиотеки, стало использование функции проигрывания сетевого аудиопотока.<\/p>\n<h2>Настройка<\/h2>\n<p>Как и в случае с настройкой под Android, для iOS нам потребуются дополнительные библиотеки, без которых скомпилировать проект не получиться. Воспользуемся набором библиотек <a href=\"http:\/\/sourceforge.net\/projects\/dpfdelphiios\/\">DPF iOS Native Components<\/a>. Данные библиотеки нужны для подключения iOS фреймворка работы со звуком.<\/p>\n<p>Скачиваем архив с файлами с <a href=\"http:\/\/sourceforge.net\/projects\/dpfdelphiios\/\">официального сайта<\/a> или с <a href=\"http:\/\/alexbirukov.ru\/files\/radio-ios\/DPF.iOS.Native.Components.v9.6.1.zip\">моего сайта<\/a>.<\/p>\n<p>После того, как мы скачали все необходимые дополнительные файлы, приступаем к установке компонентов.<\/p>\n<p>Я рекомендую (во избежании дополнительных проблем с подключением) распаковать файлы в папку DPF.iOS.Native.Components.v9.6.1.zip в корень диска C.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-54-41.png\" width=\"1280\" height=\"1024\" alt=\"Распаковываем файлы фреймворка\" \/>\n<\/div>\n<p>В каталоге с файлами, имеется файл Install.txt. У кого хорошо с английским, могут сделать всё по инструкции описанной в файле, для тех, кто не совсем понимает, что необходимо делать, я опишу процесс подробно.<\/p>\n<p>Запускаем Codegear RAD Studio. Далее в верхнем меню открываем Tools->Options->Delphi Options->Library.<\/p>\n<p>Затем, в выпадающем списке поочерёдно выбираем следующие пункты платформ:<\/p>\n<ol start=\"1\">\n<li>32-bit windows<\/li>\n<li>iOSSimulator<\/li>\n<li>iOSDevice32<\/li>\n<li>iOSDevice64<\/li>\n<\/ol>\n<p>В каждом из пунктов добавляем в раздел «Library path» путь к нашим компонентам. В нашем случае <b>C:\\DPF.iOS.Native.Components.v9.6.1\\<\/b><\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-56-43.png\" width=\"1280\" height=\"1024\" alt=\"Добавление фреймворка\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-57-19.png\" width=\"1280\" height=\"1024\" alt=\"Добавление фреймворка\" \/>\n<\/div>\n<\/div>\n<p>Теперь, необходимо в разделе SDK Manager указать, какие фрейворки iOS нам потребуются. Для этого открываем Tools->Options->SDK Manager, пролистываем появившийся список вниз до раздела <b>Frameworks<\/b>, выбираем в списке один из фремворков, нажимаем на кнопку <b>Add the new path item<\/b> и добавляем следующие фреймворки:<\/p>\n<ul>\n<li>\/System\/Library\/Frameworks\/EventKit<br \/>\n\/System\/Library\/Frameworks\/MessageUI<br \/>\n\/System\/Library\/Frameworks\/AudioToolbox<br \/>\n\/System\/Library\/Frameworks\/Social<br \/>\n\/System\/Library\/Frameworks\/QuickLook<br \/>\n\/System\/Library\/Frameworks\/SystemConfiguration<br \/>\n\/System\/Library\/Frameworks\/GameKit<br \/>\n\/System\/Library\/Frameworks\/CoreBluetooth<br \/>\n\/System\/Library\/Frameworks\/Accounts<br \/>\n\/System\/Library\/Frameworks\/AdSupport<br \/>\n\/System\/Library\/Frameworks\/ExternalAccessory<br \/>\n\/System\/Library\/Frameworks\/AddressBookUI (No need in XE8 and later)<br \/>\n\/System\/Library\/Frameworks\/AddressBook (No need in XE8 and later)<br \/>\n\/System\/Library\/Frameworks\/MobileCoreServices (No need in XE8 and later)<br \/>\n\/System\/Library\/Frameworks\/MapKit (No need in XE8 and later)<br \/>\n\/System\/Library\/Frameworks\/LocalAuthentication.framework\/LocalAuthentication (iOS 8.0 and later)<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Add.png\" width=\"1280\" height=\"1024\" alt=\"добавление фрейворков\" \/>\n<\/div>\n<p>В качестве пути на удалённом хосте требуется указывать путь «<b>$(SDKROOT)\/System\/Library\/Frameworks<\/b>», а качестве имени, название фремворка. Для примера:<br \/>\n<b>Путь:<\/b> $(SDKROOT)\/System\/Library\/Frameworks<br \/>\n<b>Имя:<\/b> EventKit<br \/>\nБольше нигде никаких галочек ставить и выбирать не требуется.<\/p>\n<p>Должно получиться так.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-07-03.png\" width=\"1280\" height=\"1024\" alt=\"Добавление фреймворков\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Frameworks.png\" width=\"1199\" height=\"733\" alt=\"Список фремворков\" \/>\n<\/div>\n<\/div>\n<p>В разделе <b>Libs<\/b>, аналогичным образом необходимо добавить библиотеку <b>\/usr\/lib\/libxml2.dylib<\/b>. Путь к ней указать, как <b>$(SDKROOT)\/usr\/lib\/<\/b><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-10-12.png\" width=\"1280\" height=\"1024\" alt=\"Библиотека libxml2.dylib\" \/>\n<\/div>\n<p>После добавления всех фреймворков в список необходимо обязательно нажать на кнопку <b>Update local File Cache<\/b>. При этом MAC с запущенным PAServer’ом должен быть настроен и доступен.<\/p>\n<div class=\"e2-text-picture\">\n<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\" \/>\n<\/div>\n<p>Теперь нам потребуется скомпилировать и установить компоненты. Для этого нажимаем File -> Open Project. Открываем проект из папки компонентов, соответствующий вашей среде программирования.<\/p>\n<p>Нажимаем правой кнопкой на проекте в инспекторе проекта и выбираем пункт <b>«Build»<\/b>, начнётся построение проекта.<\/p>\n<p>После завершение построение, опять нажимаем правой кнопкой на проекте в инспекторе и выбираем пункт <b>«Install»<\/b>.<\/p>\n<p>Компоненты готовы к работе. Приступим к созданию проекта.<\/p>\n<h2>Проект<\/h2>\n<p>И вот, всё почти готово, для использования библиотек Bass на iOS. Осталось задействовать саму библиотеку и добавить некоторый код в проект.<\/p>\n<p>Для работы с библиотекой, нам потребуется файл <b>libbass.a<\/b>. Его необходимо добавить в корень каталога проекта. Откуда конкретно у меня данный файл, я точно сказать не смогу, я нашёл его где-то на просторах форума <a href=\"http:\/\/www.un4seen.com\/\">un4seen.com<\/a>. Здесь я выкладываю <a href=\"http:\/\/alexbirukov.ru\/files\/radio-ios\/libbass.a\">рабочий файл<\/a> из своих проектов.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-28-45.png\" width=\"1280\" height=\"1024\" alt=\"Файл libbass.a\" \/>\n<\/div>\n<p>Но, одного файла для работы будет недостаточно. Так же, в проект необходим добавить ещё 2 файла *.pas. Первый будет необходим для работы с функциями libbass, второй послужит для работы с фреймворком iOS для работы с сетевыми потоками.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-34-36.png\" width=\"1280\" height=\"1024\" alt=\"Файлы проекта\" \/>\n<\/div>\n<p>Необходимо скачать данный архив, распаковать его содержимое в корень проекта и подключить <a href=\"http:\/\/alexbirukov.ru\/files\/radio-ios\/adv-libbass.7z\">данные файлы<\/a> к проекту.<\/p>\n<p>В раздел <b>implementation<\/b> необходимо добавить следующий код:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{$O-}\n  function BASS_Init(device: LongInt; freq: DWORD; flags: DWORD; win: Pointer; clsid: Pointer) : BOOL; cdecl; external 'libbass.a' name 'BASS_Init';\n  function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DWORD; cdecl; external 'libbass.a' name 'BASS_StreamPutData';\n  function BASS_StreamFree(handle: HSTREAM): BOOL; cdecl;  external 'libbass.a' name 'BASS_StreamFree';\n  function BASS_StreamCreate(freq: DWORD; chans: DWORD; flags: DWORD; proc: Pointer; user: Pointer): HSTREAM;  cdecl;  external 'libbass.a' name 'BASS_StreamCreate';\n  function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length: QWORD; flags: Cardinal): HSTREAM; cdecl; external 'libbass.a' name 'BASS_StreamCreateFile';\n  function BASS_StreamCreateURL(url: Pointer; offset: Cardinal; flags: Cardinal; proc: DOWNLOADPROC; user: Pointer):HSTREAM; cdecl; external 'libbass.a' name 'BASS_StreamCreateURL';\n  function BASS_ChannelPlay(handle: HSTREAM; restart: BOOL): BOOL; cdecl;  external 'libbass.a' name 'BASS_ChannelPlay';\n  function BASS_ChannelStop(handle: DWORD): BOOL; cdecl; external 'libbass.a' name 'BASS_ChannelStop';\n{$O+}<\/code><\/pre><h2>Работа с аудиопотоком<\/h2>\n<p>Для корректной работы с аудипотоками, требуется подключение аудио-фреймворка iOS.  Самый простой способ сделать это, кинуть на форму компонент DPFAVPlayer, что именно я и сделал. Это исключает необходимость выполнения дополнительных манипуляций.<\/p>\n<p>Так же, для нормальной работы программы, я разделал функционал на несколько потоков, чтобы при проигрывании аудио потоков само приложение не тормозило и не останавливалось по неизвестным причинам. Приведу код работы из рабочего проекта.<\/p>\n<p>Глобальные переменные.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">uStream:HSTREAM;\nchan: HSTREAM = 0;<\/code><\/pre><p>При нажатии на кнопку Play в приложении запускается поток:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Запускаем поток вещания\nIdThreadComponent1.Start;<\/code><\/pre><p>«Тело» потока:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">try\n\n    \/\/ Инициализируем libbass\n    BASS_Init(-1,44100,0,Handle,nil);\n\n    \/\/ Закрываем предыдущие потоки (не обязательно, взято из примера)\n    BASS_StreamFree(uStream);\n\n    messageText := 'Буферизация...';\n    IdThreadComponent1.Synchronize(ShowMess);\n    \/\/ Создаём поток данных\n    uStream:=BASS_StreamCreateURL(Pchar(stantion),0,BASS_STREAM_STATUS or BASS_UNICODE,nil,nil);\n\n    if uStream = 0 then\n    begin\n      ShowMessage('Ошибка создания потока!');\n    end\n    else\n    begin\n\n      if not Bass_ChannelPlay(uStream,true) then\n      begin\n        ShowMessage('Не удалось воспроизвести поток!');\n      end;\n\n      messageText := currentLabel;\n      IdThreadComponent1.Synchronize(ShowMess);\n      IdThreadComponent1.Synchronize(deactivateIndicator);\n    end;\n\n  except on E: Exception do\n    begin\n      {$IFDEF DEBUG}\n        ShowMessage(e.Message);\n      {$ELSE}\n        ShowMessage('Ошибка подключения к выбранной радиостанции.');\n      {$ENDIF}\n    end;\n  end;\n\n  IdThreadComponent1.Terminate;<\/code><\/pre><p>Остановка проигрывания<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Останавливаем плеер\nBASS_ChannelStop(uStream);<\/code><\/pre><p>Как вы могли заметить, во время запуска потока, инициализируется библиотека Bass, очищаются имеющиеся потоки и создаётся новый интернет поток при помощи функции <b>BASS_StreamCreateURL<\/b>, где <b>stantion<\/b> строковая переменная, содержащая ссылку на поток.<\/p>\n<p>Данный набор минимальных настроек, позволит вам работать с библиотекой Bass на устройствах под управлением iOS.<\/p>\n<h2>Проигрывание в фоне<\/h2>\n<p>Чтобы заставить ваше приложение продолжать проигрывание в фоне, необходимо сделать дополнительные настройки проекта. В XE10 наконец-то появился параметр <b>UIBackgroundModes<\/b>. В настройках проекта устанавливаем значения: <b>audio<\/b> И <b>remote-notification<\/b> (в случае использования Push уведомлений).<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-52-53.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<h2>Окончание<\/h2>\n<p>Ну вот в общем и всё, что требуется сделать для создания проекта с использованием libbass на iOS. Возможно, при написании статьи я допустил какие-либо неточности и недочёты, т. к. проекты сделаны давно, а статья написана по следам этих проектов, поэтому я мог упустить нюансы. Обо всех замеченных недочётах и ошибках вы можете писать мне в комментариях, буду рад вашим отзывам.<\/p>\n",
            "date_published": "2016-01-04T02:00:24+05:00",
            "date_modified": "2021-01-30T20:39:54+05:00",
            "tags": [
                "BASS",
                "Delphi",
                "iOS",
                "libbass",
                "Seattle",
                "XE10",
                "программирование"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-54-41.png",
            "_date_published_rfc2822": "Mon, 04 Jan 2016 02:00:24 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "329",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js",
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-54-41.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-56-43.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-00-57-19.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Add.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-07-03.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Frameworks.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-10-12.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-18-15.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-28-45.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-34-36.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-XE10-2016-01-04-01-52-53.png"
                ]
            }
        },
        {
            "id": "326",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/php-server-dlya-rassylki-push-na-android-i-ios\/",
            "title": "PHP сервер для рассылки Push на Android и iOS",
            "content_html": "<p>Долгое время искал в интернете нормальное решение для массовой рассылки Push сообщений на Android и iOS, но ничего подходящего и нормально работающего не попадалось.<\/p>\n<p>В Delphi долгое время приходилось использовать компоненты Kinvey (или Pasre). При этом возникали новые проблемы зависимости от платформы, ключей и пр. С любым серьёзным изменением приходилось изменять, как сам проект, так и настройки проекта. В некоторых случаях сторонние компоненты отказывались работать на той или иной платформе по не понятной причине. А так же, огромным минусом Kinvey, было то, что при получении Push сообщения на iOS не воспроизводилось звуковое уведомление. В конце концов, зависимость от третьей стороны всегда является определённым минусом любого проекта.<\/p>\n<p>И вот после очередных поисков я объединил все имеющиеся знания и сделал серверную часть для регистрации устройств и рассылки Push сообщений.<\/p>\n<p>Принцип работы скрипта достаточно прост. В нём имеются функции для регистрации (удаления) токенов устройств, ну и собственно сами функции рассылки. Большая часть мануалов? которые мне удалось найти были написаны либо неправильно, либо попросту были неполными.<\/p>\n<h2>Введение<\/h2>\n<p>Немного теории. Для отправки Push сообщений используются сервисы <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/NetworkingInternet\/Conceptual\/RemoteNotificationsPG\/Chapters\/ApplePushService.html\">APNS<\/a> у Apple и <a href=\"http:\/\/developer.android.com\/google\/gcm\/index.html\">GCM<\/a> у Google. Наш скрипт может выступать в качестве самостоятельного сервера рассылки Push через сервера Apple и Google, а так же принимать токены устройств регистрируемых в базе данных.<\/p>\n<h2>Apple, iOS и ApnsPHP<\/h2>\n<p>Начнём с более сложной части.<br \/>\nЯ не стану изобретать велосипед и воспользуюсь уже имеющимися в сети, бесплатными, библиотеками написанными на PHP. Набор библиотек ApnsPHP представляет собой набор классов для работы с Push сообщениями APNS. Скачать их с примерами можно на GitHub по <a href=\"https:\/\/github.com\/immobiliare\/ApnsPHP\/tree\/master\/ApnsPHP\">ссылке<\/a>.<\/p>\n<p>Но одних библиотек нам мало. Самое сложное, это генерация и конвертирование сертификатов для работы с Push на iOS. Я опишу полный алгоритм экспорта и конвертации сертификатов, а затем их дальнейшее применение в скриптах.<\/p>\n<h3>Генерация сертификата для отправки Push сообщений<\/h3>\n<p>Будем предполагать, что вы уже создали и настроили сертификаты в личном кабинете разработчика и загрузили их в «Связку ключей» на ваш Mac.<\/p>\n<ol start=\"1\">\n<li>Запускаем утилиту <b>«Связка ключей»<\/b> и в левой части выбираем раздел <b>«Мои сертификаты»<\/b>.<\/li>\n<li>Раскрываем сертификат интересующего нас проекта. <b>БУДЬТЕ ВНИМАТЕЛЬНЫ!<\/b> Есть две версии сертификатов, <b>Developer<\/b> (используется при отладке и разработке) и <b>Production<\/b> (используется для рабочей версии). Выбираем сертификат и закрытый ключ данного сертификата.<\/li>\n<li>Нажимаем правой кнопкой и выбираем пункт «Экспортировать объектов: 2». Сохраняем полученные сертификаты. Я сохранил с именами <i><b>server_certificates_bundle_sandbox.p12<\/b><\/i> (для сертификата разработки) и <i><b>server_certificates_bundle_prod.p12<\/b><\/i> (для сертификата публикации). <b>Внимание!<\/b> При экспорте поле пароля оставляем пустым. В дальнейшем вы сможете усложнить систему защиты и выгрузить сертификаты с указанием пароля.<\/li>\n<\/ol>\n<p>Для подтверждения валидности сертификатов пользователя которые мы только что получили, необходим корневой сертификат. Для получения корневого сертификата необходимо выполнить следующие действия:<\/p>\n<ol start=\"1\">\n<li>Переходим на <a href=\"https:\/\/www.entrust.net\/downloads\/root_index.cfm\">сайт загрузки корневых сертификатов<\/a>.<\/li>\n<li>Выбираем <b>«Personal Use and Secure Server Installation»<\/b> и нажимаем кнопку <b>«Download Certificates»<\/b>.<\/li>\n<li>Нажимаем на <b>«Root Certificates»<\/b>.<\/li>\n<li>Нас интересуют два сертификата <b>«entrust_ssl_ca.cer»<\/b> и <b>«entrust_2048_ca.cer»<\/b>. Скачиваем их. Вообще, в изначальном описании написано, что сертификат «entrust_ssl_ca.cer» используется в <b>Prodution<\/b> режиме, а «entrust_2048_ca.cer» в режиме <b>Development<\/b>. Но есть пометка, что после 22 декабря 2010 в качестве Production сертификата так же можно использовать «entrust_2048_ca.cer». <b><i>Т. е. данный сертификат можно использовать в обоих режимах работы, меняя лишь сертификаты пользователя<\/i><\/b>.<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain.png\" width=\"1280\" height=\"1024\" alt=\"Открываем \"Связку ключей\"\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain-2.png\" width=\"1280\" height=\"1024\" alt=\"Экспортируем сертификаты\" \/>\n<\/div>\n<\/div>\n<p>Далее, нам необходимо открыть скачанные сертификаты на Mac’е, т. е. импортировать их в «Связку ключей». Для этого просто делаем двойной клик на каждом сертификате.<\/p>\n<ol start=\"1\">\n<li>Открываем в левой части <b>«Связки ключей»<\/b> раздел <b>«Вход»<\/b> («Сертификаты»).<\/li>\n<li>Находим наш сертификат и экспортируем его <b>«entrust_root_certification_authority_2048.pem»<\/b>.<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain3.png\" width=\"1280\" height=\"1024\" alt=\"Открываем корневой сертификат.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/keychain4.png\" width=\"1280\" height=\"1024\" alt=\"Экспортируем сертификат.\" \/>\n<\/div>\n<\/div>\n<p>На данный момент, мы получили 3 основных файла для работы с сервисом APNS:<\/p>\n<ul>\n<li><b>«entrust_root_certification_authority_2048.pem»<\/b> — корневой сертификат.<\/li>\n<li><b>«server_certificates_bundle_sandbox.p12»<\/b> — сертификат пользователя для режима Development.<\/li>\n<li><b>«server_certificates_bundle_prod.p12»<\/b> — сертификат пользователя для режима Production.<\/li>\n<\/ul>\n<p>Как можно заметить, сертификаты пользователя имеют расширение *.p12, но для работы нам необходимы файлы формата *.pem.<\/p>\n<p>Для конвертации я воспользовался бесплатным набором утилит <a href=\"https:\/\/slproweb.com\/products\/Win32OpenSSL.html\">OpenSSL для Windows<\/a>.<br \/>\nПосле установки пакета, для простоты выполнения команд я использовал TotalCommander.<\/p>\n<ol start=\"1\">\n<li>Открываем в левой части каталог установленного OpenSSL и переносим туда наши сертификаты.<\/li>\n<li>В нижней части TotalCommander в командной строке выполняем следующие команды:<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">openssl pkcs12 -in server_certificates_bundle_sandbox.p12 -out server_certificates_bundle_sandbox.pem -nodes -clcerts\nopenssl pkcs12 -in server_certificates_bundle_prod.p12 -out server_certificates_bundle_prod.pem -nodes -clcerts<\/code><\/pre><p>На запрос ввода пароля, просто нажимаем Enter.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert.png\" width=\"1280\" height=\"1024\" alt=\"Подготавливаем сертификаты и программу.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert2.png\" width=\"1280\" height=\"1024\" alt=\"Сертификаты.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert4.png\" width=\"1280\" height=\"1024\" alt=\"Выполнение команд конвертации сертификатов.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert5.png\" width=\"1280\" height=\"1024\" alt=\"Просто нажимаем Enter.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/convert3.png\" width=\"1280\" height=\"1024\" alt=\"Готовые сертификаты.\" \/>\n<\/div>\n<\/div>\n<p>И так, теперь у нас есть набор необходимых сертификатов для работы с Push сообщениями на iOS.<\/p>\n<h2>Google и GCM<\/h2>\n<p>Для работы с Google и GCM мы будем использовать библиотеку <a href=\"https:\/\/github.com\/CodeMonkeysRu\/GCMMessage\">GCM PHP Server Library<\/a>. Скачанный архив библиотек и пример работы из коробки у меня по какой-то причине отказался работать, поэтому пришлось немного модифицировать код.<\/p>\n<p>Для работы с GCM нам потребуется API ключ проекта. Выполняем следующие действия:<\/p>\n<ol start=\"1\">\n<li>Открываем <a href=\"https:\/\/console.developers.google.com\/project\">консоль разработчика Google<\/a>.<\/li>\n<li>Выбираем интересующий нас проект.<\/li>\n<li>Открываем раздел <b>«APIs & auth»<\/b> — <b>«Credentials»<\/b> и копируем ключ Server Key.<\/li>\n<li>Если вы ещё не создавали ключи, то вам потребуется включить API «Google Cloud Messaging for Android».<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/apikey.png\" width=\"1280\" height=\"864\" alt=\"API ключ.\" \/>\n<\/div>\n<p>Теперь у нас имеются все необходимые данные для организации PHP сервера рассылки Push сообщений.<\/p>\n<h2>База данных<\/h2>\n<p>Для рассылки Push сообщений на устройства пользователей используются токены устройств, которые выдаётся серверами Google и Apple, т. е. для получения Push сообщения, токен устройства должен быть зарегистрирован в системе. Наш сервер так же отправки Push сообщений будет использовать токены устройств. Для хранения токено устройств, ID устройств и платформы я использовал базу данных.<\/p>\n<p>Текст скрипта для создания базы данных выглядит так.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE TABLE devices (\n  id int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Уникальный идентификатор  записи в таблице',\n  deviceID varchar(255) NOT NULL COMMENT 'Идентификатор устройства',\n  deviceToken varchar(255) NOT NULL COMMENT 'Токен устройства',\n  devicePlatform varchar(255) NOT NULL COMMENT 'Платформа устройства',\n  PRIMARY KEY (id),\n  UNIQUE INDEX deviceID (deviceID)\n)\nENGINE = MYISAM\nAUTO_INCREMENT = 20\nAVG_ROW_LENGTH = 166\nCHARACTER SET utf8\nCOLLATE utf8_general_ci\nCOMMENT = 'Зарегистрированные устройства для рассылки PUSH сообщений';<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/db-table.png\" width=\"263\" height=\"179\" alt=\"Таблица для хранения токенов.\" \/>\n<\/div>\n<p>Для добавления устройств в базу данных используется отдельная функция скрипта сервера, но об этом чуть позже.<\/p>\n<h2>Сервер<\/h2>\n<p>Переходим к самому серверу и его настройке. Все файлы я выложу отдельным архивом.<br \/>\nСуть скрипта состоит в следующем: подключаем библиотеки для работы с Push, настраиваем сертификаты и API ключ и с помощью имеющихся функций выполняем необходимые действия, будь то рассылка сообщений, регистрация устройств и пр.<\/p>\n<p>В состав сервера входит файл конфигурации. Приведу отдельно его текст.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&lt;?php\n\n# Переменные для работы  с базой данных\n$config['db']['host'] = &quot;localhost&quot;;\n$config['db']['name'] = &quot;Имя БД&quot;;\n$config['db']['user'] = &quot;Пользователь БД&quot;;\n$config['db']['pass'] = &quot;Пароль БД&quot;;\n\n# Управление рассылкой. True - рассылка производится, false - рассылка отключена.\n$config['apn']['send'] = true;\n$config['gcm']['send'] = true;\n\n# Ключи для доступа к сервисам\n# Ключ для доступа Google Server API\n$config['gcm']['apikey'] = &quot;ВАШ API КЛЮЧ&quot;;\n# Путь к сертификатам APN для подключения к серверу рассылки\n$config['apn']['sert'] = 'Certificates\/server_certificates_bundle_sandbox.pem';\n$config['apn']['sert_prod'] = 'Certificates\/server_certificates_bundle_prod.pem';\n$config['apn']['RootCertificat'] = 'Certificates\/entrust_root_certification_authority_2048.pem';\n$config['apn']['production'] = false;\n\n?&gt;<\/code><\/pre><p>Думаю, что раздел конфигурации базы данных не требует объяснения, тут надо указать настройки для доступа к базе данных, в которой хранится таблица <b>«Devices»<\/b>.<\/p>\n<p>Параметры:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['send'] = true;\n$config['gcm']['send'] = true;<\/code><\/pre><p>Отвечают за включение или отключение рассылки Push сообщений, если значение false, то рассылка на указанную платформу не производится.<\/p>\n<p>Дальше идут настройки API ключа и указание каталогов сертификатов, что в общем-то тоже я думаю понятно всем.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Ключи для доступа к сервисам\n# Ключ для доступа Google Server API\n$config['gcm']['apikey'] = &quot;ВАШ API КЛЮЧ&quot;;\n# Путь к сертификатам APN для подключения к серверу рассылки\n$config['apn']['sert'] = 'Certificates\/server_certificates_bundle_sandbox.pem';\n$config['apn']['sert_prod'] = 'Certificates\/server_certificates_bundle_prod.pem';\n$config['apn']['RootCertificat'] = 'Certificates\/entrust_root_certification_authority_2048.pem';<\/code><\/pre><p>Отдельно рассмотрим ключ:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['production'] = false;<\/code><\/pre><p>Данный ключ переключает режим работы сервера. Development или Production режимы рассылки.<\/p>\n<p>Как можно заметить, все сертификаты необходимо положить в каталог «Certificates» рядом со скрипом.<\/p>\n<p>Если при генерации сертификатов Apn использовался пароль, то в настройках, необходимо указать пароль:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">$config['apn']['sertPass'] = 'пароль сертификата';<\/code><\/pre><h2>Работа со скриптом<\/h2>\n<p>После заполнения файла конфигурации скрипт готов к работе, осталось зарегистрировать устройства.<br \/>\nСкрипт сервера push.php принимает 2 значения параметра <b>action<\/b>:<\/p>\n<ul>\n<li><b>register-device<\/b><\/li>\n<li><b>send-push<\/b><\/li>\n<\/ul>\n<p>В каждом действии требуются дополнительные параметры. Для регистрации устройства дополнительными параметрами являются:<\/p>\n<ul>\n<li><b>did<\/b> — Идентификатор устройства (не используется, но на всякий случай).<\/li>\n<li><b>token<\/b> — токен устройства, используется для рассылки Push сообщений.<\/li>\n<li><b>platform<\/b> — платформа устройства, используется функциями рассылки. Может принимать 2 значения: <b>ios<\/b> или <b>andoid<\/b>.<\/li>\n<\/ul>\n<p>Для рассылки Push сообщений используется действие send-push и принимается всего 1 дополнительный параметр: <b>text<\/b> — текст Push сообщения.<\/p>\n<p>Примеры запросов:<\/p>\n<p>Регистрация устройства iOS<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=register-device&amp;did=DC92EFED-9271&amp;token=feaab9d122f53a4fdca&amp;platform=ios<\/code><\/pre><p>Регистрация устройства Android<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=register-device&amp;did=DC92EFED-9271&amp;token=feaab9d122f53a4fdca&amp;platform=andoid<\/code><\/pre><p>Отправка Push сообщений<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">http:\/\/example.ru\/push.php?action=send-push&amp;text=Добрый день, мой господин!<\/code><\/pre><p>Первые два запроса регистрируют устройства в базе данных и в момент рассылки скрипты выбирает токены устройств по полю platform и производит отправку Push сообщений.<\/p>\n<p>Второй запрос производит рассылку Push сообщения все зарегистрированным устройствам.<\/p>\n<p>В общем-то, всё достаточно просто, каждый желающий может в дальнейшем модифицировать скрипт по своему желанию, вводя защиту от несанкционированного доступа и пр. Прошу меня не пинать, за полное отсутствие защиты в скрипте, скрипт призван показать логику и рабочий пример работы с Push сообщениями. Плюс данного скрипта состоят в том, что данные мы можем отправлять с любой платформы, будь то веб форма, Windiws приложения или мобильные приложения.<\/p>\n<h2>Delphi<\/h2>\n<p>Настало время рассмотреть небольшой код написанный для Delphi, который позволяет регистрировать токены устройств на нашем сервере. Каждое мобильное устройство после запуска приложения получает свой DeviceID и токен, после чего отправляет полученные данные на наш сервер.<\/p>\n<p>В разделе public нашего юнита добавляем следующие строки:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">public\n    { Public declarations }\n    APushService : TPushService;\n    AServiceConnection : TPushServiceConnection;<\/code><\/pre><p>А в раздел type добавляем описание 2-х функций:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">procedure OnReceiveNotificationEvent(Sender: TObject; const ANotification : TPushServiceNotification);\n    procedure OnServiceConnectionChange(Sender: TObject; AChange : TPushService.TChanges);<\/code><\/pre><p>В момент отображения формы добавляем код получения DID и токена. Будьте внимательны, значение <b>PROJECTNUM<\/b> необходимо заменить на свой номер проекта из личного кабинета Google разработчика.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ На данном этапе происходит регистрация устройства для получения Push.\nprocedure TMainForm.FormShow(Sender: TObject);\nvar\n  ADeviceID, ADeviceToken : string;\nbegin\n\n  \/\/ Получение и отправка токена устройства\n  {$ifdef ANDROID}\n    \/\/ Для Android\n    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);\n    APushService.AppProps[ TPushService.TAppPropNames.GCMAppID ] := 'PROJECTNUM';\n  {$else}\n    \/\/ Для iOS\n    APushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS);\n  {$endif}\n  \/\/ Создаём подключение к серверу\n  AServiceConnection := TPushServiceConnection.Create( APushService );\n  \/\/ Активируем подключение\n  AServiceConnection.Active   := True;\n  \/\/ Подключаем делегаты\n  AServiceConnection.OnChange := OnServiceConnectionChange;\n  AServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent;\n\n  ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];\n  ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];\n\n  if (ADeviceID &lt;&gt; '') AND (ADeviceToken &lt;&gt; '') then\n  begin\n\n    \/\/ Регистрируем устройство на сервере для отправки push сообщений\n    RegisterDevice(ADeviceID, ADeviceToken);\n\n  end;\n\nend;<\/code><\/pre><p>Так же, надо добавить функцию, которая срабатывает при изменении состояния получения DID и токена.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ Устройства не всегда успевают получить токен,\n\/\/\/ поэтому при изменении состояния опять проверяем токен\nprocedure TMainForm.OnServiceConnectionChange(Sender: TObject;\n  AChange : TPushService.TChanges);\nvar\n  ADeviceID, ADeviceToken : string;\nbegin\n    \/\/ При измении состояния компонента\n    ADeviceID    := APushService.DeviceIDValue[ TPushService.TDeviceIDNames.DeviceID ];\n    ADeviceToken := APushService.DeviceTokenValue[ TPushService.TDeviceTokenNames.DeviceToken ];\n\n    if (ADeviceID &lt;&gt; '') AND (ADeviceToken &lt;&gt; '') then\n    begin\n\n      \/\/ Регистрируем устройство на сервере для отправки push сообщений\n      RegisterDevice(ADeviceID, ADeviceToken);\n\n    end;\nend;<\/code><\/pre><p>Для вывода Push сообщения добавляем функцию:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/\/ Процедура вывода сообщение при получении Push уведомления от сервера\nprocedure TMainForm.OnReceiveNotificationEvent(Sender: TObject;\n  const ANotification : TPushServiceNotification);\nvar\n  MessageText : string;\nbegin\n  \/\/ Получаем текст сообщения в зависимости ль платформы\n  {$ifdef ANDROID}\n    MessageText := ANotification.DataObject.GetValue('message').Value;\n  {$else}\n    MessageText := ANotification.DataObject.GetValue('alert').Value;\n  {$endif};\n\n  \/\/ Выводим сообщение\n  ShowNotification(MessageText, 0);\nend;<\/code><\/pre><p>В результате мы получаем почти готовую программу. Кто был более внимательным, заметил, что в коде есть несколько функций, не объявленных ранее, таких как <b>ShowNotification<\/b> или <b>RegisterDevice<\/b>. Для удобства, я вынес их в отдельный файл global.pas. Достаточно добавить данный файл в проект, чтобы не копипастить функции. В данном файле вам потребуется заменить константу DOMAIN для указания пути к файлу скрипта на сервере, и если вы положили скрипт не в корне сервера, а в случайный каталог, то потребуется внести дополнительные изменения для указания точной адресации.<\/p>\n<p>Так же имеется функция <b>SendPush<\/b>, которая позволяет отправлять Push сообщения прямо с устройства.<\/p>\n<p>Все функции в файле global.pas имеют подробное описание и думаю их использование не вызовет никаких вопросов.<\/p>\n<p>Таким образом мы получаем устройства, которые регистрируются в системе, отправляя свои DID и токены скрипту, а скрипт записывает их в базу данных для дальнейшего использования при отправке Push сообщений. Если в базе имеются токены устройств, на которых программа не установлен (удалена), то такие токены будут удалены из базы данных после попытки отправки Push сообщений.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/db.png\" width=\"751\" height=\"128\" alt=\"Зарегистрированные устройства.\" \/>\n<\/div>\n<h2>Используемые файлы.<\/h2>\n<p><a href=\"http:\/\/alexbirukov.ru\/files\/push-server\/global.pas\">Файл global.pas<\/a><br \/>\n<a href=\"http:\/\/alexbirukov.ru\/files\/push-server\/Push_Server.7z\">PHP сервер Push сообщений<\/a><\/p>\n<h2>Заключение<\/h2>\n<p>В данной статье я попытался максимально подробно изложить принципы и алгоритмы работы с Push сообщениями с использованием дополнительных библиотек GCMMessage и ApnsPHP в php скрипте и взаимодействие с программным обеспечением (в моём случае Windows приложения и мобильные платформы).<\/p>\n<p>Данная статья не претендует на оригинальность и истину последней инстанции. Имеются открытые места в безопасности, такие, как сертификаты без паролей, открытый доступ к функциям скрипта без идентификации пользователей и пр.<\/p>\n<p>Если у кого-нибудь будет желание доработать данный скрипт в плане безопасности или внести поправки я буду только рад. Ваши изменения и замечания вы можете писать в комментариях к статье.<\/p>\n<p><b>UPDATE<\/b><\/p>\n<p>Для удобства, загрузил проект на <a href=\"https:\/\/github.com\/alexbirukov\/PHP-Push-Sender\">GitHub<\/a>.<\/p>\n<p><b>UPDATE 2<\/b> из комментария читателя<\/p>\n<blockquote>\n<p>Если у кого не работает на Rad Studio 10.2, то вместо «AServiceConnection.Active := True;» сделайте так:<\/p>\n<\/blockquote>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Активируем подключение\nTTask.Run(\nprocedure\nbegin\nAServiceConnection.Active := True;\nend\n);<\/code><\/pre><p>В uses должно быть System.Threading.<\/p>\n",
            "date_published": "2015-10-02T14:13:19+05:00",
            "date_modified": "2018-12-23T22:27:53+05:00",
            "tags": [
                "Android",
                "ApnsPHP",
                "Delphi",
                "GCMMessage",
                "iOS",
                "PHP",
                "Push",
                "кроссплатформенность",
                "программирование",
                "сервер"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/keychain.png",
            "_date_published_rfc2822": "Fri, 02 Oct 2015 14:13:19 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "326",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js",
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/keychain.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain-2.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain3.png",
                    "https:\/\/alexbirukov.ru\/pictures\/keychain4.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert2.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert4.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert5.png",
                    "https:\/\/alexbirukov.ru\/pictures\/convert3.png",
                    "https:\/\/alexbirukov.ru\/pictures\/apikey.png",
                    "https:\/\/alexbirukov.ru\/pictures\/db-table.png",
                    "https:\/\/alexbirukov.ru\/pictures\/db.png"
                ]
            }
        },
        {
            "id": "325",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/oshibki-i-kosyaki-xe10-seattle-i-xcode-7\/",
            "title": "Ошибки и косяки Delphi XE10 Seattle и xCode 7",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/maxresdefault.jpg\" width=\"1280\" height=\"720\" alt=\"\" \/>\n<\/div>\n<p>И так, пока русскоязычная и англоязычная части интернета молчат по поводу работы в новой Delphi XE10 Seattle в связке с xCode 7, а компании представители описывают, какое замечательное вышло обновление, пользователи столкнулись с проблемой, что приложения, сделанные на XE10 Seattle, xCode 7 + SDK9, не запускаются на предыдущих платформах.<\/p>\n<p>Не совсем понятно, почему в упомянутых сегментах интернета нет совершенно никакой информации по данному поводу. Опять впереди планеты все <a href=\"http:\/\/www.cnblogs.com\/onechen\/p\/4821280.html\">Китай<\/a>.<\/p>\n<p>Пользователь блога подробно описывает конфигурацию, на которой он тестировал запуск приложения и описание проблемы. Несколько реальных устройств на разных прошивках, разные версии ПО и пр.<\/p>\n<p>Коротко о главном. Если вы хотите, как можно скорей перейти на новую Delphi XE10 Seattle с целью писать свежие приложения\\обновления для iOS, спешу вас разочаровать. Ваши программы перестанут работать на предыдущих версиях iOS. Статистика испытаний такова, что приложения собранные на XE10 Seattle, xCode 7 + SDK9 будут работать только на устройствах под управлением iOS9.<\/p>\n<p>Вторая проблема, состоит в том, что недавнего времени AppStore при проверке приложений стала проверять их именно на iOS 9, а приложения собранные на XE8.1 такую проверку не проходят, так как зависают на стартовой заставке приложения и как следствие их отклоняют. Вот так то. Прошла уже целая неделя, а интернет по данному поводу ничего сказать нам особо не может.<\/p>\n<p>На днях появилась <a href=\"http:\/\/community.embarcadero.com\/blogs\/entry\/workaround-steps-for-building-ios-32-bit-applications-for-ios-9-with-xe7-and-xe8\">статья от Сарины Дю Понт<\/a>, о том, как всё же запустить приложение сделанные в XE8.1 на iOS9.<\/p>\n<p>В результате изысканий Китайских друзей, получаем на данный момент такую картину:<\/p>\n<p>XE8 + iOS 6 = полёт нормальный<br \/>\nXE8 + iOS 7 = полёт нормальный<br \/>\nXE8 + iOS 8 = полёт нормальный<br \/>\nXE8 + iOS 9 = зависание на экране заставки (если не воспользоваться советом Сарины)<\/p>\n<p>XE10 + iOS 6 = приложение вылетает<br \/>\nXE10 + iOS 7 = приложение вылетает<br \/>\nXE10 + iOS 8 = приложение вылетает<br \/>\nXE10 + iOS 9 = полёт нормальный<\/p>\n<p>Таким образом в XE10 Seattle и xCode 7 можно получить на данный момент только приложение, работающее на iOS9.<\/p>\n<p>Ждём Delphi XE10 Seattle Update 1.<\/p>\n<p>P.S. А в на Android в Delphi XE10 Seattle приложение с компонентами для отправки Push не запускается в режиме Release — Application Store. Что тоже, очень и очень печально.<\/p>\n",
            "date_published": "2015-09-21T16:55:06+05:00",
            "date_modified": "2021-01-30T20:42:19+05:00",
            "tags": [
                "Delphi",
                "iOS",
                "Seattle",
                "xCode",
                "XE10",
                "программирование",
                "программы"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/maxresdefault.jpg",
            "_date_published_rfc2822": "Mon, 21 Sep 2015 16:55:06 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "325",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/maxresdefault.jpg"
                ]
            }
        },
        {
            "id": "324",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/oshibka-error-itms-90507-pri-publikacii-prilozheniya-v-appstore\/",
            "title": "Ошибка ERROR ITMS-90507 при публикации приложения в AppStore",
            "content_html": "<h2>Преамбула<\/h2>\n<p>В последнее время всё реже и реже встречаются статьи связанные с Delphi, при том, что язык в принципе развивается и появляются большие возможности в плане создания кроссплатформенных мобильных приложений. При этом в русскоязычной части интернета информации крайне мало, люди делятся знаниями крайне неохотно и большая часть ответов носит поверхностный характер. И это при том, что большая часть программистов училась именно на pascal и регулярно пишет приложения с использованием продуктов Borland (Embarcadero).<\/p>\n<p>В связи с этим, решил начать публиковать статьи связанные с разработкой мобильных и десктопных приложений на Delphi.<\/p>\n<h2>Соль<\/h2>\n<p>Apple регулярно ужесточает требования к описанию программ публикуемых в AppStore. И большое количество проблем, вызывает правильность формирования и описания содержимого файла Info.plist. В файле описывается приложение, версия, билд, наименование модулей и пр. С проблемами сталкиваются не только те, кто программирует на Delphi, но пользователи других сред.<\/p>\n<p>С недавнего времени при публикации приложения стала появляться ошибка <b>ERROR ITMS-90507: Missing Info.plist value. A value for the key ’DTPlatformName’ is required<\/b>, которая сообщает программисту о том, что необходимый ключ <b>DTPlatformName<\/b> не найден в файле Info.plist.<\/p>\n<p>Для исправления ошибки, необходимо выполнить следующие действия:<\/p>\n<p>Открываем настройки проекта и добавляем ключ для настроек «iOS 64 bits — Release».<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/03000003.png\" width=\"1164\" height=\"761\" alt=\"\" \/>\n<\/div>\n<p>Имя ключа <b>DTPlatformName<\/b><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/03000004.png\" width=\"430\" height=\"121\" alt=\"\" \/>\n<\/div>\n<p>Указываем значение ключа «iphoneos». И сохраняем настройки. Теперь приложение должно без проблем быть принято к публикации в AppStore.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/03000005.png\" width=\"1174\" height=\"767\" alt=\"\" \/>\n<\/div>\n",
            "date_published": "2015-08-28T22:06:18+05:00",
            "date_modified": "2021-01-30T20:45:17+05:00",
            "tags": [
                "Delphi",
                "iOS",
                "ошибка",
                "программирование"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/03000003.png",
            "_date_published_rfc2822": "Fri, 28 Aug 2015 22:06:18 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "324",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/03000003.png",
                    "https:\/\/alexbirukov.ru\/pictures\/03000004.png",
                    "https:\/\/alexbirukov.ru\/pictures\/03000005.png"
                ]
            }
        },
        {
            "id": "316",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/udio-pleer-na-delphi-dlya-android-code-gear-rad-studio-xe7\/",
            "title": "Аудио-плеер на Delphi для Android с применением библиотеки BASS.",
            "content_html": "<p>В середине прошлого года появилась необходимость написания простого приложения для мобильных платформ Android и iOS. Первым рабочим проектом стал <a href=\"http:\/\/alexbirukov.ru\/?go=tags\/kteam\/\">KTeam<\/a>. После его успешного запуска, появилась необходимость написания аудио-плеера, способного воспроизводить потоковое вещание интернет радиостанций.<\/p>\n<p>И так, сегодня я подробно опишу, как создать простой плеер потокового вещания.<\/p>\n<p>Для работы нам понадобятся среда программирования Code Gear RAD Studio XE7, работать я рекомендую именно в данной версии программы, т. к. в используемых библиотеках, имеются некоторые не стыковки в работе с предыдущими версиями.<\/p>\n<p>По причине того, что встроенных средств проигрывания интернет потока не имеется, мы воспользуемся замечательной библиотекой BASS, для написания приложения для Android (для iOS следует использовать другие компоненты).<\/p>\n<p>Для корректной работы библиотеки BASS я рекомендую так же установить компоненты <a href=\"http:\/\/sourceforge.net\/projects\/dpfdelphiandroid\/\">DPF Android Native Components<\/a>, я в своём примере буду использовать версию 2.8.6.<\/p>\n<h2>Начало<\/h2>\n<p>Ну я думаю процесс установки Code Gear RAD Studio XE7 описывать не стоит, поэтому сразу переходим к установке дополнительных компонентов и библиотек, потому что именно эта часть вызывает наибольшие проблемы, и именно поэтому данный этап я опишу наиболее подробно.<\/p>\n<h2>BASS<\/h2>\n<p>Идём на <a href=\"http:\/\/www.un4seen.com\">официальный сайт un4seen.com<\/a> библиотеки, нажимаем в левом меню на ссылку <a href=\"http:\/\/www.un4seen.com\/bass.html\">BASS<\/a> и скачиваем там последнюю версию для <a href=\"http:\/\/www.un4seen.com\/forum\/?topic=13225\">Android<\/a>. На момент написания данной статьи на сайте опубликована версия 2.4 от 13 марта 2015 года. <a href=\"http:\/\/www.un4seen.com\/stuff\/bass24-android.zip\">Прямая ссылка<\/a> на скачивание библиотеки с официального сайта. <a href=\"http:\/\/alexbirukov.ru\/files\/radio-andr\/bass24-android.zip\">Ссылка на скачивание с моего сайта<\/a>.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1276\" data-ratio=\"1.3632478632479\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-09.25.46.png\" width=\"1276\" height=\"936\" alt=\"Сайт библиотеки BASS\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-09.29.03.png\" width=\"1274\" height=\"959\" alt=\"Ссылки на скачивание библиотек\" \/>\n<\/div>\n<\/div>\n<p><i><b>Примечание:<\/b> я рекомендую использовать именно данную версию библиотеки, потому что предыдущие версии не работают с XE7, и при инициализации библиотеки появляется ошибка.<\/i><\/p>\n<h2>BASSFunctions<\/h2>\n<p>Для корректной работы с библиотекой, нам потребуется ещё один дополнительный файл, это <a href=\"http:\/\/alexbirukov.ru\/files\/radio-andr\/BASSFunctions.pas\">BASSFunctions.pas<\/a>. Данный файл опубликовал на форуме пользователь с ником 3delite.<a href=\"http:\/\/www.3delite.hu\/Object%20Pascal%20Developer%20Resources\/Download\/BASSFunctions.pas\">Ссылка<\/a> на оригинальный файл.<\/p>\n<h2>DPF Android Native Components<\/h2>\n<p>Для корректной работы библиотек BASS, часто требуется установка компонентов DPF Android Native Components, т. к. в их составе имеется компонент для работы с аудио, без которого компилятор будет просто выдавать ошибку.<\/p>\n<p>Идём на <a href=\"http:\/\/sourceforge.net\/projects\/dpfdelphiandroid\/\">официальный сайт<\/a> и скачиваем последнюю версию компонентов. Или вы можете скачать версию <a href=\"http:\/\/alexbirukov.ru\/files\/radio-andr\/DPF.Android.Native.Components.v2.8.6.zip\">2.8.6<\/a> с моего сайта.<\/p>\n<h2>Поехали<\/h2>\n<p>После того, как мы скачали все необходимые дополнительные файлы, приступаем к установке компонентов.<\/p>\n<p>Начнём с DPF Android Native Components. Я рекомендую (во избежании дополнительных проблем с подключением) распаковать файлы в папку DPF.Android.Native.Components.v2.8.6 в корень диска C.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-09-55-10.png\" width=\"1280\" height=\"1024\" alt=\"Распаковываем файлы\" \/>\n<\/div>\n<p>В каталоге с файлами, имеется файл Install.txt. У кого хорошо с английским, могут сделать всё по инструкции описанной в файле, для тех кто в школе учил немецкий, я опишу процесс установки компонентов подробно.<\/p>\n<p>Запускаем Codegear RAD Studio. Далее в верхнем меню открываем Tools->Options->Delphi Options->Library.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-09-58-33.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-00-13.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<\/div>\n<p>В выпадающем списке справа выбираем платформу «32-bit Windows» и добавляем в раздел «Library path» путь к нашим компонентам.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-06.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<p>Теперь то же самое проделываем для платформы «Android».<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-55.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<p>Теперь нам потребуется скомпилировать и установить компоненты. Для этого нажимаем File -> Open Project. Открываем проект из папки компонентов, соответствующий вашей среде программирования.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-06-17.png\" width=\"1280\" height=\"1024\" alt=\"Открываем проект\" \/>\n<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\" \/>\n<\/div>\n<\/div>\n<p>Далее нам надо скомпилировать проект и установить полученные компоненты.<\/p>\n<p>Нажимаем правой кнопкой на проекте в инспекторе проекта и выбираем пункт <b>«Build»<\/b>, начнётся построение проекта.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-13-23.png\" width=\"1280\" height=\"1024\" alt=\"Выполняем Build\" \/>\n<\/div>\n<p>После завершение построение, опять нажимаем правой кнопкой на проекте в инспекторе и выбираем пункт <b>«Install»<\/b>.<\/p>\n<p>Компоненты готовы к работе. Приступим к созданию проекта.<\/p>\n<p>Я набросал уже небольшой проект с парой кнопок для запуска и остановки проигрывателя и картинкой для привлечения внимания :)<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-24-28.png\" width=\"1280\" height=\"1024\" alt=\"Пробный проект.\" \/>\n<\/div>\n<p>Для работы в библиотекой BASS, нам потребуется в каталог с проектом добавить файл BASSFunctions.pas и указать его в разделе <b>uses<\/b>.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<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.\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-22-52.png\" width=\"1280\" height=\"1024\" alt=\"Добавляем в раздел uses.\" \/>\n<\/div>\n<\/div>\n<p>Теперь собственно сама библиотека <b>libbass.so<\/b>. Нам необходимо добавить данную библиотек в наш проект, иначе ничего не заработает.<\/p>\n<p>Открываем архив bass24-android.zip и видим... Множество папок, нас интересует на данный момент только одна <b>libs<\/b>. Распаковываем её в каталог нашего проекта.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-10.29.21.png\" width=\"1273\" height=\"993\" alt=\"\" \/>\n<\/div>\n<p>В каталоге libs, есть три подкаталога, нас интересуют 2 из них:<\/p>\n<ul>\n<li>armeabi-v7a<\/li>\n<li>armeabi<\/li>\n<\/ul>\n<p>В них находятся два разных файла libbass.so.<\/p>\n<p>После того, как мы скопировали данный каталог в каталог проекта, снова возвращаемся к среде программирования и открываем раздел <b>Deployment<\/b>, для добавления наших библиотек в программу.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-36-12.png\" width=\"1280\" height=\"1024\" alt=\"Deployment\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-37-49.png\" width=\"1280\" height=\"1024\" alt=\"Добавляем библиотеки\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-38-56.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-39-15.png\" width=\"1280\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<\/div>\n<p>После того, как мы добавили библиотеки в наш проект, надо поменять параметр «Remote Path» для каждой библиотеки соответственно на «<b>library\\lib\\armeabi<\/b>» и на «<b>library\\lib\\armeabi-v7a<\/b>». Данную процедуру надо проделать для обеих конфигураций «Debug» и «Release».<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1280\" data-ratio=\"1.25\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-43-47.png\" width=\"1280\" height=\"1024\" alt=\"Библиотеки\" \/>\n<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\"\" \/>\n<\/div>\n<\/div>\n<p>Ну что, вот всё и готово к началу написания кода, а код на самом деле достаточно простой.<\/p>\n<p>Объявляем глобальную переменную.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">var\n  uStream:HSTREAM;<\/code><\/pre><p>В момент создания формы инициализируем библиотеку.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">procedure TmainForm.FormCreate(Sender: TObject);\nbegin\n  \/\/ Загружаем и инициализируем библиотеку\n  Loadbass;\n  BASS_Init(-1,44100,0,Handle,nil);\nend;<\/code><\/pre><p>На кнопку «Играть» вещаем обработчик:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">procedure TmainForm.mainToolbarBarItems1Click(Sender: TObject);\nvar\n  otStream : TStringStream;\n  Result : integer;\nbegin\n  try\n\n    \/\/ Включаем индикатор загрузки контента\n    ind1.Enabled := True;\n    ind1.Visible := True;\n\n    \/\/ Код проигрывателя\n    Result := 0;\n\n    \/\/ Закрываем старый поток\n    BASS_StreamFree(uStream);\n\n    \/\/ Создаём новый поток\n    uStream :=\n      BASS_StreamCreateURL(PChar('http:\/\/motochelyabinsk.ru:8000\/play'),0,BASS_STREAM_STATUS or BASS_UNICODE,nil,nil);\n\n    \/\/ Включаем проигрывание\n    BASS_ChannelPlay(uStream, True);\n\n    \/\/ Получаем и выводим название текущего трека из скрипта на сайте\n    \/\/ Создаём поток UTF8\n    otStream := TStringStream.Create('', CP_UTF8);\n    \/\/ Делаем запрос к скрипту сайта\n    IdHTTP1.Get('motochelyabinsk.ru\/current-track.php', otStream);\n    IdHTTP1.Disconnect;\n    \/\/ Записываем название трека в Label\n    Label1.Text := otStream.DataString;\n    \/\/ Очищаем переменную потока\n    otStream.Free;\n\n    \/\/ Запустить таймер отслеживания изменений названия трека\n    Timer1.Enabled := True;\n\n    \/\/ Включаем и отключаем кнопки\n    btn1.Enabled := False;\n    btn2.Enabled := True;\n\n  except on E: Exception do\n    begin\n      ShowMessage('Ошибка доступа к сети!');\n    end;\n  end;\n\nend;<\/code><\/pre><p>Ну вот в общем самый простой и работающий пример создания проигрывателя интернет радиостанций.<br \/>\nP.S. Чуть позже, выложу готовый пример данного приложения.<\/p>\n",
            "date_published": "2015-03-24T09:48:04+05:00",
            "date_modified": "2021-01-22T23:57:04+05:00",
            "tags": [
                "Android",
                "BASS",
                "Delphi",
                "KTeam",
                "KTeam Radio",
                "libbass",
                "код",
                "Олнайн",
                "программирование",
                "программы",
                "Радио"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-09.25.46.png",
            "_date_published_rfc2822": "Tue, 24 Mar 2015 09:48:04 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "316",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js",
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-09.25.46.png",
                    "https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-09.29.03.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-09-55-10.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-09-58-33.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-00-13.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-06.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-04-55.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-06-17.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-06-31.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-13-23.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-24-28.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-21-50.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-22-52.png",
                    "https:\/\/alexbirukov.ru\/pictures\/-2015-03-24-10.29.21.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-36-12.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-37-49.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-38-56.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-39-15.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-43-47.png",
                    "https:\/\/alexbirukov.ru\/pictures\/Windows-7-x64-Delphi-XE7-2015-03-24-10-42-46.png"
                ]
            }
        }
    ],
    "_e2_version": 4134,
    "_e2_ua_string": "Aegea 11.3 (v4134)"
}