{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "В наушниках по жизни: заметки с тегом Android",
    "_rss_description": "Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/alexbirukov.ru\/?go=tags\/android\/",
    "feed_url": "https:\/\/alexbirukov.ru\/?go=tags%2Fandroid%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": "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": "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"
                ]
            }
        },
        {
            "id": "310",
            "url": "https:\/\/alexbirukov.ru\/?go=all\/motosoobschestvo-i-novye-proekty\/",
            "title": "Мотосообщество и новые проекты",
            "content_html": "<p>Как-то давно я не писал ничего в блог, видимо потому, что стало значительно меньше свободного времени и меньше времени для размышлений. Но тем не менее жизнь идёт своим чередом и за период времени с середины прошедшей зимы мы с группой единомышленников создали проект взамипомомощи среди мотоциклистов и назвали проект KTeam (сокращение от <a href=\"http:\/\/vk.com\/motochel74\">Кировка Тим<\/a>).<\/p>\n<p>Сначала мы занялись проектированием платформы и <a href=\"http:\/\/motochelyabinsk.ru\/\">сайтом<\/a> для работы всей системы. Для начала мы сделали простенький сайт, целью которого на начальном этапе было — отображение заявок. Так же параллельно сайту появилась платформа для работы с поступающими заявками от различных мобильных платформ и СМС операторов. Изначально мы расчитывали на входящие СМС сообщения, но затем решили расширить проект и написать приложения для платформ iOS и Android. И хочется заметить, у нас всё получилось.<\/p>\n<p>И так 17 мая 2014 на открытии мотосезона состоялась презентация нашего небольшого, но крайне полезного проекта.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/4ld350kahse.jpg\" width=\"573\" height=\"807\" alt=\"Приложение KTeam\" \/>\n<\/div>\n<p>Суть приложения и всей платформы проста — создать автоматизированную систему оповещения о происходящих происшествиях с участием мотоциклистов. Приложение примечательно тем, что может автоматически определять координаты местоположения аварии и создавать на их основании заявку. После чего все пользователи зарегистрированные в системе получают СМС уведомления с типом и адресом места происшествия.<\/p>\n<p>С момента запуска проекта прошло чуть больше месяца, но система оповещение уже успела зарекомендовать себя, как очень действенный инструмент моментального оповещения участников мотодвижения в городе Челябинске.<\/p>\n<p>Так же, с приходом тепла мы стали заниматься не только разработкой приложения и сайта, но и продумывать и организовывать различные социальные мероприятия. Недавно состоялась поездка в детский приют в пос. Солнечный. Хотелось бы сказать огромное СПАСИБО всем тем, кто откликнулся и помог финансово, морально и физически организовать столь замечательное мероприятие.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/alexbirukov.ru\/pictures\/logo_KT.png\" width=\"869\" height=\"870\" alt=\"KTeam. Кировка. Челябинск. Мотосообщество.\" \/>\n<\/div>\n<p>P.S. Ждите новых мероприятий и принимайте активное участие!<\/p>\n",
            "date_published": "2014-06-22T20:20:29+05:00",
            "date_modified": "2017-03-01T23:01:15+05:00",
            "tags": [
                "Android",
                "iOS",
                "KTeam",
                "Байкеры",
                "мотосообщество",
                "челябинск"
            ],
            "image": "https:\/\/alexbirukov.ru\/pictures\/4ld350kahse.jpg",
            "_date_published_rfc2822": "Sun, 22 Jun 2014 20:20:29 +0500",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "310",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/alexbirukov.ru\/pictures\/4ld350kahse.jpg",
                    "https:\/\/alexbirukov.ru\/pictures\/logo_KT.png"
                ]
            }
        }
    ],
    "_e2_version": 4134,
    "_e2_ua_string": "Aegea 11.3 (v4134)"
}