{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "В наушниках по жизни: заметки с тегом iOS",
    "_rss_description": "Здесь я пишу свои идеи, мысли, описываю события своей жизни и просто делаю личные и рабочие заметки. «А Вы что, собираетесь жить вечно?»",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/alexbirukov.ru\/?go=tags\/ios\/",
    "feed_url": "https:\/\/alexbirukov.ru\/?go=tags%2Fios%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": "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": "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)"
}