Как построить и запустить релиз-приложение iOS в Cordova

Будем исходить из того, что вы написали свое первое приложение под Android на Windows, используя, к примеру, редактор Visual Code и теперь хотите на основе уже написанного кода построить приложение под iOS, перекинув все исходник на ваш Mac — машину, где мы будет подготавливать, построить и подписывать приложение под iOS, прибегнув к помощи XCode.

Здесь представлен текст описания одного из вариантов построения приложения Cordova для платформы iOS. Перед началом работы условимся, что у  нас в инструментарии есть следующие необходимые условия:

  • у нас есть Mac OS High Sierra(или неважно какая версия, но чтобы работала стабильно);
  • на нашем Mac OS установлен XCode последней версии(или неважно какой версии, но чтобы работало стабильно);
  • на нашем Mac OS установлен Node.js v8 и выше(или неважно какой версии, но чтобы работало стабильно);
  • на нашем Node.js установлен Cordova;
  • у нас есть годовая подписка на возможность разрабатывать приложения под продукты Apple. Стоит это удовольствие $99, без этого ваш проект так и будет на стадии дебагинга, без возможности устанавливать на сторонние устройства или загружать на App Store.

Это все элементарные элементы, которые понятны для настройки любому разработчику, принявшегося серьезно разработать под iOS и останавливаться, подробно описывая каждый шаг, я не буду.

Подписка на Apple Developer

Особо следует остановиться на покупку лицензии разработки в виде подписки, потому что без этого никак, если вы хотите подписать приложение и распространять его. У Apple распространители делятся на 4 категории:

  1. Sign in with Apple ID — распространители, которые имеют возможность использовать разработку только в режиме тестирования. Т.е., вы не можете распространять ваши приложения за пределы эмулятора на вашем Mac или вашего личного устройства, но весь функционал разработки вам все равно доступен. Стоит $0;
  2. Individual — распространитель в виде индивидуального разработчика. Apple выдает вам сертификат, в котором прописаны ваши личные данные, как физического лица. Стоит $99;
  3. Organization — распространитель от имени организации. Apple выдает вам сертификат, в котором прописаны вашей организации. Стоит $99;
  4. Enterprise Program — распространитель корпоративного ПО. Стоит $299.

Подробно про фичи разработки под тем или иной подпиской можно почитать по ссылке.

Настройка проекта Cordova

Добавляем платформу iOS и подготавливаем проект для XCode

cordova platform add ios
cordova prepare              # или "cordova build"

Развертывание проекта в Cordova

Примечание. Этап развертывания средствами Cordova можно пропустить, так как дальнейщую работу с проектом мы будем производить в XCode.

Дополнительно будет полезно установить вспомогательные утилиты, которые пригодятся в работе c эмуляторами

npm install -g ios-sim
npm install -g ios-deploy

В данной статье мы не будем работать через эти утилиты, а будем работать через XCode. Также через командную строку мы можем задеплоить приложение.

Для развертывания приложения на подключенном iOS устройстве:

cordova run ios --device

Для развертывания приложения на iOS эмуляторе по умолчанию:

cordova emulate ios

Можно использовать cordova run android —list чтобы увидеть все доступные цели и cordova run android —target=имя_устройства для запуска приложения на конкретном устройстве или эмуляторе (например, cordova run android --target="Nexus4_emulator").

Чтобы увидеть дополнительные параметры построения и запуска также можно использовать cordova run —help.

Работа с проектом в XCode iOS SDK

Первым делом открываем сгенерированный проект XCode в директории проекта Cordova по пути ProjectName/platforms/ios/PrjectName.xcpdeproj

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

Первым делом выбираем модуль Cordova в списке и при его контексте нажимаем на вкладку General, где устанавливаем галочку на автоуправление подпиской и в выпадающем нижнем списке выбираем команду разработки. В данном случае там указываем вашу купленную подписку разработчика у Apple

Первым делом выбираем конечное устройство в виде физического устройства

Далее заходим в настройку схемы проекты и там должен быть выбран название проекта,а  не библиотека Cordova

Если он не установлен, то заходим в Edit Scheme и во всех вкладках устанавливаем конфигурацию Build Configuration в режим Release, кроме вкладки Test

Теперь, нам нужно сначала почистить проект нажав на Clean, построить, нажав на Build и архивировать, нажав на Archive

Если мы все правильно настроили в проекте, то проект должен удачно архивировать в формат *.xcarchive по пути проекта ProjectName/platforms/ios/PrjectName.xcarchive

Чтобы увидеть все сгенерированные архивы проектов необходимо найти в верхнем меню Window > Organizer

В данном диалоге мы увидим список всех архивов. Это не полноценное приложение, которое можно уже установить на iOS — устройство и его нельзя разместить в маркет. Для этого нам нужно его экспортировать в один из вариантов и для этого сначала выбираем проект, далее нужный архив из проекта и нажав на кнопку Export вызываем окно выбора типа распространения нашего приложения в формате *.ipa

В способе распространения *.ipa выбираем нужный вариант. Если хотим распространить через App Store, о выбираем первый пункт. Второй пунтк — это распространение подписанного приложения с возможность индивидуальной установки без App Store. Другие можно понять по их кратким описаниям, но основные — это 2 первых, если вы новоиспеченный разработчик iOS.

К примеру выберем тип распространения Ad Hoc и жмем на Next и в следующем диалоге у нас будет возможность выбрать какое-то специфическое устройство или все поддерживающие данной разработкой устройства все сразу, также есть возможность добавить файл манифеста, который даст возможность установить приложение только из определенной ссылки скачивания и жмем на Next

В данном шаге необходимо выбрать режим подписи. Оставим автоподпись средой XCode и жмем на Next

Дальше среда будет генерировать подписанные дистрибутивы под разные устройства iOS

По окончании процесса среда выдаст подробную информацию о сборке

Жмем на кнопку Export и среда нас запросит выбрать место хранения сгенерированных подписанных дистрибутивов *.ipa

После сохранения создастся отдельная папка, в которой будут все наши подписанные дистрибутивы iOS

 

Использование Google Firebase Cloud Messages (FCM) в проектах

Firebase Cloud Messaging (FCM) — это межплатформенное решение для обмена сообщениями, которое позволяет надежно доставлять сообщения без каких-либо затрат. Используя FCM, вы можете уведомить клиентское приложение о том, что для синхронизации доступны новые электронные или другие данные.

Статья состоит из 2 частей. В первой рассматривается введение и начальная настройка, а далее подробно раскрывается принцип отправки и обработки уведомлений FCM.

Часть 2. Принцип работы отправки и приемки уведомлений в Firebase Cloud Messages (FCM)

Это перевод и дополнение официальной статьи по плагину cordova-plugin-fcm.

Установка

Процесс установки мы уже рассматривали в первой части статьи. Перед началом, убедитесь, что у вас есть google-services.json для Android или GoogleService-Info.plist для iOS в корневой папке вашего проекта Cordova. Вам не нужно настраивать что-либо еще, чтобы иметь push-уведомление, работающее для обеих платформ, все это волшебство. Установка плагина FCM занимает не много времени

cordova plugin add cordova-plugin-fcm

Файлы конфигурации Firebase

Получите необходимые файлы конфигурации для Android или iOS из Firebase Console (см. документацию: https://firebase.google.com/docs/).

Детали компиляции под Android

Поместите загруженный файл «google-services.json» в корневую папку проекта Кордовы. Вам нужно будет убедиться, что вы установили соответствующие библиотеки Android SDK.

Если хотите добавить значок уведомления в Android> 5.0, то вы должны поместить картинку со значком с именем «fcm_push_icon.png» в папку «res» так же, как вы добавляете другие значки приложений. Если вы не установите этот ресурс, SDK будет использовать значок по умолчанию для вашего приложения, который может не соответствовать стандартам для Android> 5.0.

Детали компиляции под iOS

Поместите загруженный файл «GoogleService-Info.plist» в корневую папку проекта Cordova.

Использование FCM в Cordova

Пример заполнения JSON данных для отправки на сервер FCM по REST API представлен в ниже в подразделе Отправить уведомление. Пример из песочницы (REST API).

Настоятельно рекомендуется использовать REST API для отправки push-уведомлений, потому что консоль Firebase не имеет всех функций. Обратите внимание на пример в песочнице, чтобы научиться правильно использовать плагин. Вы также можете протестировать свои уведомления на бесплатном сервере тестирования: https://cordova-plugin-fcm.appspot.com.

Получение обновления токена

Токен — это идентификатор, выданный серверами соединения FCM, в клиентское приложение, который позволяет приложению получать сообщения. Обратите внимание, что регистрационные токены должны храниться в секрете.

//FCMPlugin.onTokenRefresh( onTokenRefreshCallback(token) );
/**
 * Обратите внимание, что этот Callback будет срабатывать каждый раз, 
 * когда будет сгенерироваться новый токен, в том числе и первый раз.
 */
FCMPlugin.onTokenRefresh(function(token){
    alert( token );
});

При первом запуске вашего приложения FCM SDK генерирует регистрационный токен для экземпляра клиентского приложения. Если вы хотите настроить таргетинг на отдельные устройства или создать группы устройств, вам необходимо получить доступ к этому токену или токенам.

Получение токена

Функция getToken возвращает токен текущего устройства или нулевое значение, если токен еще не установлен для устройства.

//FCMPlugin.getToken( successCallback(token), errorCallback(err) );
/**
 * Имейте в виду, то функция возвращает нулевое значение, 
 * если токен не был установлен еще.
 */
FCMPlugin.getToken(function(token){
    alert(token);
});
Подписаться на тему(топик)
//FCMPlugin.subscribeToTopic( topic, successCallback(msg), errorCallback(err) );
/**
 * Все устройства подписаны автоматически, 
 * ко 'всем' - и 'ios' и 'android' темам соответственно.
 * Должен соответствовать следующему регулярному выражению: "[a-zA-Z0-9-_.~%]{1,900}"
 */
 FCMPlugin.subscribeToTopic('topicExample');
Отписаться от темы(топика)
//FCMPlugin.unsubscribeFromTopic( topic, successCallback(msg), errorCallback(err) );
FCMPlugin.unsubscribeFromTopic('topicExample');
Получение данных push-уведомлений

Функция FCMPlugin.onNotification(…) принимает все уведомления, по токену или по топику, на который подписаны пользователи

//FCMPlugin.onNotification( onNotificationCallback(data), successCallback(msg), errorCallback(err) )
/**
 * Здесь Вы можете определить свое поведение приложения на основе данных уведомления.
 */
 FCMPlugin.onNotification(function(data){
    if(data.wasTapped){
      //Уведомление было получено в трей устройства и постучал пользователю.
      alert( JSON.stringify(data) );
    }else{
      //Уведомление было получено на переднем плане. Возможно, пользователя нужно уведомить.
      alert( JSON.stringify(data) );
    }
});

Следует отметить, что если вы используете Vue.js, как программную архитектуру или jQuery, то необходимо дождаться, пока ресурсы устройства подгрузятся, иначе можно получить ошибку, что плагин FCMPlugin не определен. Один из вариантов — размещение обработчика в setTimeout

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupApp();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
    },
    setupApp: function() {
        //Программная логика на какой-то библиотеке
        setTimeout(function(){
            FCMPlugin.onNotification(function(data) {
                console.log(data);
            });
        },2000);
    }
}

app.initialize();

или разместить весь код в обработчике события deviceready

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupApp();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        FCMPlugin.onNotification(function(data) {
            console.log(data);
        });
    },
    setupApp: function() {
        //Программная логика на какой-то библиотеке
    }
}

app.initialize();
Отправить уведомление. Пример из песочницы (REST API)

Чтобы отправлять FCM — уведомления тому или иному устройству нам необходимо знать токен этого устройства и тему (топик), на который подписано устройство.

Как получить токен, подписаться устройство на тему(топик) и как отписаться мы выше уже привели примеры с кодом. Теперь нам осталось уметь отправлять уведомления и как мы уже говорили выше, для этого нужно отправлять JSON — с заполненными данными методом POST на адрес https://fcm.googleapis.com/fcm/send и потребуется указать еще 2 заголовка отправки, как Content-Type: application/json и Authorization: key=AIzaSy*******************. Первый заголовок указывает, что мы передаем JSON — данные и второй — что, запрос содержит учетные данные для аутентификации пользовательского агента с сервером. Второй заголовок принимает параметр ключа API для веб-приложения, который можно узнать в консоли FCM

 

Пример этой JSON приведен ниже и еще ниже описаны параметры, которые входят в эту строку.

Дополнительно:

{
  "notification":{
    "title":"Notification title",
    "body":"Notification body",
    "sound":"default",
    "click_action":"FCM_PLUGIN_ACTIVITY",
    "icon":"fcm_push_icon"
  },
  "data":{
    "param1":"value1",
    "param2":"value2"
  },
    "to":"/topics/topicExample",
    "priority":"high",
    "restricted_package_name":""
}

Метод передачи и заголовки с параметрами:

  • POST: https://fcm.googleapis.com/fcm/send
  • HEADER: Content-Type: application/json
  • HEADER: Authorization: key=AIzaSy*******************

Передаваемые параметры в JSON методом POST:

  • sound — необязательный параметр для указания своего звука уведомления
  • click_action — должен присутствовать с указанным значением для Android
  • icon — значок — имя ресурса для Android >5.0
  • data — положите любые «param»:»value» и получите их в JavaScript callback — уведомлениях
  • to — токен устройства или /topic/topicExample
  • priority — должен быть установлен в «high» для доставки уведомлений закрытым iOS — приложениям
  • restricted_package_name — Необязательное поле, если вы хотите отправить только на ограниченный пакет приложений (т.е.: com.myapp.test)
Пример отправки POST — запроса FCM — уведомления при помощи jQuery

В коде представлен пример AJAX запроса методом POST с указанием необходимых заголовков и их параметров

var fcm_server_key = "AIzaSy*******************";

$.ajax({
  method: "POST",
  dataType: 'json',
  headers: {'Content-Type': 'application/json', 'Authorization': 'key=' + fcm_server_key},
  url: "https://fcm.googleapis.com/fcm/send",
  data: JSON.stringify(
      {
        "notification":{
          "title":"Title",  //Любое значение
          "body": "Body",  //Любое значение
          "sound": "default", //Если вы хотите звучание в уведомление
          "click_action": "FCM_PLUGIN_ACTIVITY",  //Должен присутствовать для Android
          "icon": "fcm_push_icon"  //Белая иконка ресурса Android
        },
        "data":{
          "param1":"value1",  //Любые данные, получаемые в callback - уведомлении
          "param2": "Prueba"
        },
        "to":"/topics/all", //Тема(топик) или какое-то одно устройство
        "priority":"high", //Если не установлен, то уведомления не могут быть доставлены для закрытых приложений iOS
        "restricted_package_name":"" //Необязательно. Устанавливается для фильтрации приложений
      }
    )
}).success(function(data){
  alert("Success: " + JSON.stringify(data));
}).error(function(data){
  alert("Error: " + JSON.stringify(data));
});
Пример отправки POST — запроса FCM — уведомления при помощи cURL с сервера

Вот пример cURL. Не забудьте заменить авторизацию заголовка собственной учетной записью службы Firebase

curl -X POST \
  https://fcm.googleapis.com/fcm/send \
  -H 'authorization: key=YOUR-FIREBASE-SERVER-KEY' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{
	"to": "/topics/all",
	"notification": {
	    "title": "Hello World!",
	    "body": "Proin rutrum, nunc vitae porta volutpat, mi nibh.",
        "icon": "fcm_push_icon",
    	"color": "#F79838",
        "sound":"default"
	},
	"priority": "high",
        "click_action":"FCM_PLUGIN_ACTIVITY"
}'

 

Пример отправки POST — запроса FCM — уведомления при помощи Axios из устройства

Axios — это отличная клиентская библиотека, которая использует промисы по умолчанию, а так же работает как на сервере(что делает его подходящим для получения данных при рендеринге на сервере), так и на клиенте. Axios очень легко начать использовать с Vue.js. Поэтому, если у вас приложение написано с использованием Vue.js или Ionic, то отправку уведомлений нам придется реализовать через Axios

var fcm_server_key = "AIzaSy*******************";

axios({
  method: 'POST', //Метод отправки
  url: 'https://fcm.googleapis.com/fcm/send',
  data: JSON.stringify(
      {
        "notification":{
          "title":"Title",  //Любое значение
          "body": "Body",  //Любое значение
          "sound": "default", //Если вы хотите звучание в уведомление
          "click_action": "FCM_PLUGIN_ACTIVITY",  //Должен присутствовать для Android
          "icon": "fcm_push_icon"  //Белая иконка ресурса Android
        },
        "data":{
          "param1":"value1",  //Любые данные, получаемые в callback - уведомлении
          "param2": "Prueba"
        },
        "to":"/topics/all", //Тема(топик) или какое-то одно устройство
        "priority":"high", //Если не установлен, то уведомления не могут быть доставлены для закрытых приложений iOS
        "restricted_package_name":"" //Необязательно. Устанавливается для фильтрации приложений
      }
    ),
  headers: {
    'Content-Type': 'application/json', 'Authorization': 'key=' + fcm_server_key
  }
}).then((response) => {
    console.log(response)
})
.catch((error) => {
    console.log(error)
});
    
Пример отправки POST — запроса FCM — уведомления при помощи Axios из Node.js

Для начала нам потребуется установить Axios в систему при помощи простой команды через менеджер модулей npm

npm install axios

Теперь создаем index.js в корневом каталоге вашего проекта и заполняем его следующим образом

var axios = require('axios');
const fcmKey = 'YOUR_FCM_SERVER_KEY'
const fcmUrl = 'https://fcm.googleapis.com/fcm/send'
const phoneToken = 'MY_PHONE_TOKEN'

Здесь мы просто импортируем модуль axios, устанавливаем ключ сервера api и указываем адрес сервера взаимодействия, на который мы отправляем POST наши уведомления. Константа phoneToken является идентификатором вашего телефона, который раздается клиентам сервером FCM для регистрации в системе обмена.

Чтобы наше уведомление отвечало на событие, мы заставим его прослушивать конечную точку тестирования в базе данных Firebase

ref.child('test').on('child_added', (snapshot) => {
  const notification = buildNotification(snapshot.val())
  sendNotification(notification)
})

Как вы можете видеть, это просто наблюдает за конечной точкой/тестом(endpoint /test) для нового потомка. Потомок — это просто ключ/значение(key/value) с ключом «name». Перейдем к нашей функции buildNotification()

function buildNotification (data) {
  const { name } = data
  return {
    "notification": {
      "title":"New name",
      "text":`${name} is awesome`,
      "sound":"default"
    },
    "to":phoneToken,
    "priority":"high"
  }
}

Не забудьте установить приоритет на высокий уровень при разработке, иначе может потребоваться некоторое время, прежде чем ваше уведомление поступит

function buildRequest (notification) {
  return {
    url: fcmURL,
    method: 'post',
    headers: {
      "Content-Type":"application/json",
      "Authorization":`key=${fcmKey}`
    },
    data: notification
  }
}
function sendNotification(notification) {
  const request = buildRequest(notification)
axios(request).then((r) => {
    console.log(r)
  }).catch((error) => {
    console.log(error)
  })
}

Сначала мы создаем запрос с нашим уведомлением и токеном FCM в заголовках запросов. Затем мы передаем этот запрос в Axios и слушаем ответ или ошибку. Теперь вы должны увидеть уведомление, появившееся на вашем устройстве.

Если у вас не получилось, то есть несколько вещей, на которые стоит обратить внимание:

  • Убедитесь, что приоритет установлен на высокий
  • Убедитесь, что у вас есть сертификат push-уведомления, загруженный в консоль Firebase (В iOS 10 могут быть изменения на использование)

Как это работает

К примеру, мы отправляем push-уведомление на одно устройство или в тему(топик). При этом возможны 2 случая:

a. Приложение находится на переднем плане:

  • Данные уведомления принимаются в Callback — вызове JavaScript без сообщения в панели уведомлений (это обычное поведение push — уведомлений в мобильных ).

b. Приложение находится в фоновом режиме или закрыто:

  • Устройство отображает сообщение уведомления на панели уведомлений устройства.
  • Если пользователь удаляет уведомление, приложение выходит на передний план и данные уведомления принимаются в Callback —  вызове JavaScript.
  • Если пользователь не обращается к уведомлению, но открывает приложение, то ничего не происходит до тех пор, пока уведомление не будет обработано.

Реальный пример отправки из Axios

Код отправки уведомления

/**
 * to - кому и куда отправляется уведомление и может быть:
 * 1. токеном
 * 2. топиком
 * 3. или можем отправить всем сразу
 * title - заголовок уведомления
 * message - тело уведомления
 * apiKey - секретный ключ из облачного приложения Android Google FCM
 */
var to =  "cicx9RtKXdk:APA91bGsk16she-DPkwjSrM5_9ZfJ4v189k53ETUF081DXtIH6vl6MwsSy8ky6Orn5MUzZJqzUoCNHOZ3BxWquTvIJis2X5zzFtJQSY6ozQFUsMb6157lKS27HTDN4vuMcF4_CuTpEJH";          
//var to = "/topics/topicExample";
//var to = "/topics/all";

var title = "Новое сообщение";
var message = "Мое сообщение!";
var apiKey = "AIzaSyDqYOMoJ1jVoIfLTErYboDOtuqfCHcnWfE";

axios({
method: 'POST', //Метод отправки
url: 'https://fcm.googleapis.com/fcm/send', 
data:{
    "notification":{
      "title":title,  //Любое значение
      "body": message,  //Любое значение
      "sound": "default", //Если вы хотите звучание в уведомление
      "click_action": "FCM_PLUGIN_ACTIVITY",  //Должен присутствовать для Android
      "icon": "fcm_push_icon"  //Белая иконка ресурса Android
    },
    "data":{
      "param1":"value1",  //Любые данные, получаемые в callback - уведомлении
      "param2": "Prueba"
    },
    "to":to,
    "priority":"high" //Если не установлен, то уведомления не могут быть доставлены для закрытых приложений iOS
    //"restricted_package_name":"" //Необязательно. Можно закомментить
},
headers: {
    'Content-Type': 'application/json', 'Authorization': 'key=' + apiKey
}
}).then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
});

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

setTimeout(function(){
    if(data.wasTapped){
      //Уведомление было получено в трей устройства и постучал пользователю.
      alert( JSON.stringify(data) );
    }else{
      //Уведомление было получено на переднем плане. Возможно, пользователя нужно уведомить.
      alert( JSON.stringify(data) );
    }
},2000);

или можно закинуть в обработчик Cordova ‘deviceready’

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupApp();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        FCMPlugin.onNotification(function(data) {
            console.log(data);
        });
    },
    setupApp: function() {
        //Программная логика на какой-то библиотеке
    }
}

app.initialize();

 

Авторизация в мобильном устройстве на Cordova через Facebook

Вход в Cordova — приложение с помощью Facebook является одной из наиболее востребованных статей, и здесь мы рассмотрим один из способов реализовать данную настройку.

Для реализации входа будет использован сторонний плагин cordova-plugin-facebook4, который является форком из репозитория phonegap-facebook-plugin.

Данный плагин использует последний SDK SDK для Facebook, позволяя реализовать получение данных из профиля Facebook в проектах Cordova.

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

Нам нужно будет создать новое приложение для Facebook через свой профиль и подключить наше Facebook — приложение к приложению Cordova и результат этого будет похож следующим образом:

  • если пользователь не авторизирован в Facebook, то вывести формы авторизации;
  • подтверждение, что вы даете разрешение на доступ к своим данным через приложение Facebook приложению Cordova;
  • передача данных нашего профиля приложению на Cordova и использование для регистрации или для входа в систему.

Создаем новое приложение Facebook

Заходим в свой аккаунт на Facebook и в левом списке ищем пункт Приложения

Жмем на пункт "Управление приложениями"
Жмем на пункт «Управление приложениями»

 

Создаем новое приложение

Тут мы создаем новое приложение или используем существующее. У меня оно уже есть
Тут мы создаем новое приложение или используем существующее. У меня оно уже есть

Выбираем для приложения продукты авторизации

Тут добавляем новый продукт для приложения. Для авторизации достаточно добавить продукт "Вход через Facebook"
Тут добавляем новый продукт для приложения. Для авторизации достаточно добавить продукт «Вход через Facebook»

Обращаем внимание на ID приложения. Он нам нужен будет на этапе настройки плагина cordova-plugin-facebook4 .

Далее настраиваем наше приложение, заполняя основную информацию

Заполняем основную информацию в настройках приложения
Заполняем основную информацию в настройках приложения

И далее основное — добавление платформ к приложению. В данном примере добавим только платформу Android, но вам никто не мешает добавить и остальные

Тут добавляем необходимые для нас платформы, к которым наше приложение Facebook будет комуницировать с этими платформами
Тут добавляем необходимые для нас платформы, к которым наше приложение Facebook будет комуницировать с этими платформами

 

На этапе добавления, в данном случает добавления платформы Android, достаточно прописать идентификатор приложения в Google Play. Чтобы приложение работало оно может быть и не опубликовано в Google Play — это необязательно, но прописать индентификатор необходимо для работоспособности.

Настройка клиентского приложения на Cordova

После создания приложения Cordova необходимо добавить вышеупомянутый плагин командой с параметрами приложения Facebook

cordova plugin add cordova-plugin-facebook4 --save --variable APP_ID="123456789" --variable APP_NAME="myApplication"
  • APP_ID — это ИД приложения Facebook;
  • APP_NAME — имя приложения Facebook.

Теперь код SDK Facebook для авторизации через приложение доступно через код приложения Cordova и сначала нужно инициализировать

        window.fbAsyncInit = function() {
            FB.init({
                appId      : '1971003386550161',
                xfbml      : true,
                version    : 'v2.4'
            });
        };

Далее выполняем код авторизации

                    try {
                        var fbLoginSuccess = function (userData) {
                             if (userData.status=='connected'){
                                  facebookConnectPlugin.api("me/?fields=id,last_name,first_name,birthday,email, picture.width(200).height(200)", ['public_profile', 'user_friends', 'email'],
                                       function onSuccess (result) {
                                            alert("Result: "+JSON.stringify(result));
                                       }, function onError (error) {
                                            alert("Failed: "+JSON.stringify(error));
                                       }
                                  );
                             }
                        };
                        facebookConnectPlugin.login(["public_profile"], fbLoginSuccess,
                             function loginError (error) {
                                  alert('error='+JSON.stringify(error))
                             }
                        );
                   }
                   catch (e) {
                        alert('error1='+e.message);
                   }
                }

Результатом будет следующие данные, которые мы уже можем использовать в нашем приложении

Автоматизация подписи гибридных приложений Android

  1. Основные положения электронной подписи приложений
  2. Способы генерации ключей подписи и хранилища ключей
  3. Разница между хранилищами *.jks и *.keystore
  4. Ручная подписка APK
  5. Подписка APK на Google Play
  6. Соображения подписи, безопасности и удаление подписки из сборки APK
  7. Автоматизация процесса подписи на этапе сборки APK
  8. Автоматизация подписи гибридных приложений Android

Допустим, что у вас есть гибридное приложение, которое было спроектировано с использование фреймворка Ionic или Cordova с использованием Crosswalk.

Настроив автоматизацию, вы сможете создать подписанный release вашего APK, готовый для публикации на Google Play Store.

Если вы проектируете гибридные приложения, используя Ionic и вы нацелены на платформу Android, то вы сможете использовать Crosswalk, чтобы иметь хорошую совместимость на различных устройствах.

Использование Crosswalk в вашем проекте Ionic так же просто, как ввести эту команду:

ionic browser add crosswalk

Ionic позаботится о том, чтобы установить для вас Crosswalk.

Когда вы хотите опубликовать свое приложение в Google Play Store, вам нужно построить APK в режиме выпуска т.е. release, подписать его ключом вашего хранилища ключей и сделать zipalign пакет для его оптимизации.

Условимся, что у вас уже есть сгенерированные ключи в хранилище ключей и нам остается настроить, чтобы система автоматически подписывала приложение на этапе построения release, а если хотите подробно подробно почитать про это, относительно кроссплатформенных приложений на Ionic, то можете обратиться к официальному источнику.

Для начала нам необходимо создать файл под именем release-signing.properties в директории проекта project_folder/platforms/android/. В этот файл добавляем пару строк

storeFile=/path/to/keystore/yourname.keystore
keyAlias=youralias

Конечно же, вы можете поменять путь к файлу ваших ключей и алиас ключа. Затем вы должны построить вашу сборку release

ionic build --release android

Появится небольшое окно с запросом пароля хранилища ключей и пароля ключа. Если вы не хотите вводить два пароля каждый раз, вы можете записать их в файлах release-signing.properties, добавив две строки, похожие на следующие

storeFile=/path/to/keystore/yourname.keystore
keyAlias=youralias
storePassword=your_keystore_password
keyPassword=your_key_password

В целях безопасности и сохранности ключей не рекомендуется хранить в сторонних файлах ключи к подпискам ваших приложений.

После построения вы найдете построенный APK в директории проекта project_folder/platforms/android/build/outputs/apk/. Обычно, там будут 2 вида APK под именами android-x86-release.apk и android-armv7-release.apk.

Замечание 1.Помните, что вы должны загружать как x86, так и armv7 apks в Play Store, потому что с помощью Crosswalk ваше приложение содержит собственный код, специфичный для архитектуры.

Замечание 2. Не забудьте активировать «расширенный режим» в консоли разработчика (если вы находитесь в «Простом режиме», можно активировать только один apk за один раз) и загрузить один APK за другим. Google достаточно умен, понимая, что APK нацелены на две разные платформы. дополнительно про это можете почитать на официальном сайте.

 

Часть 1. Push — уведомления для Android и iOS при помощи Firebase Cloud Messages

 

Это простой прямой подход, касающийся того, как реализовать push-уведомление в Android, а также iOS, используя плагин  cordova plugin for fcm для проекта Cordova и Google Firebase FCM в виде облачного сервера обработки сообщений.

Использование FCM в платформе Android

1. Создание проекта Cordova. Сначала необходимо иметь какой-то проект Cordova с добавленной платформой Android:

cordova create pushSample
cd pushSample
cordova platform add android

далее к этому проекту мы добавляем плагин cordova-plugin-fcm командой:

cordova plugin add cordova-plugin-fcm

В процессе установки данного плагина система нам выведет ряд ошибок, к примеру, скажет, что у нас отсутствует файл google-services.json:

Error: cordova-plugin-fcm: You have installed platform android but file 'google-services.json' was not found in your Cordova project root folder.
Note : This is because we have not added the google-services.json file which has to be created in the next following steps.

данный файл мы должны скачать из консоли Google Firebase в процессе создания приложения и находиться он должен в корневой директории проекта Cordova.

2. Создание облачного проекта Firebase. В консоли google firebse console жмем на кнопку «Добавить» и создаем новое облачный проект для Android, iOS и WEB — проектов:

После нажатия на кнопку «Создать проект» следующим шагом является добавление возможности создания облачных уведомлений через Firebase Cloud Messages и для этого необходимо нажать на пункту «Notifications» и далее следующее окно предложит ввести данные приложения для Android или iOS:

На данном этапе нажимаем на Android и заполняем данные и выйдет окно, требующий заполнения уникального идентификатора:

далее жмем на кнопку «Зарегистрировать приложение» и мы попадем на шаг, где нам предлагают скачать вышеупомянутый файл google-services.json:

данный файл скачиваем и кидаем в корень проекта Cordova pushSample/google-service.json.

Далее жмем «Продолжить» и сервис предложит нам добавить некоторый код в файл сборки build.gradle, который находится в корне платформы Android по пути pushSample/platforms/android/build.gradle:

buildscript {
  dependencies {
    // Add this line
    classpath 'com.google.gms:google-services:3.2.0'
  }
}

В скрипте сборки плагина по пути pushSample/platforms/android/cordova-plugin-fcm/pushSample-FCMPlugin.gradle :

dependencies {
  // Add this line
  compile 'com.google.firebase:firebase-core:11.8.0'
}
...
// Add to the bottom of the file
apply plugin: 'com.google.gms.google-services'

В некоторых случаях выше приведенный код может выдавать ошибки и несоответствия и все это выйдет в консоль, как например ниже:

google-services plugin could not detect any version for com.google.android.gms or com.google.firebase, default version: 9.0.0 will be used.
please apply google-services plugin at the bottom of the build file.

Для решения можно написать костыли принудительного исполнения, прописав их в файл pushSample/platforms/android/build.gradle:

...

allprojects {
    repositories {
        ...
        configurations.all {
            resolutionStrategy {
                // Add force (11.4.0 is version you want to use)
                force 'com.google.firebase:firebase-messaging:11.4.0'
                force 'com.google.firebase:firebase-core:11.4.0'
                force 'com.google.android.gms:play-services-gcm:11.4.0'
            }
        }
    }
}

...

3. Пишем первое уведомление. После добавления кода построения сервисов Google облачный проект предложит нам отправить сообщение:

Перед тем, как написать новое сообщение из консоли в клиентские приложения в виде уведомлений необходимо сначала написать клиентский код, который будет их принимать. Для этого в папке скриптов создаем новый файл www/scripts/script.fcm.js, в котором будем писать код, выполняемый после инициализации всех ресурсов Cordova:

var app = {
    initialize: function() {
        this.setup();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    },
    setup: function() {  
        //***********Начало кода FCM
        //Функция обработки всех уведомлений, как в бакграунде, так и при открытом приложении
        FCMPlugin.getToken(function(token) {
            //this is the fcm token which can be used
            //to send notification to specific device 
            console.log(token);
            //FCMPlugin.onNotification( onNotificationCallback(data), successCallback(msg), errorCallback(err) )
            //Here you define your application behaviour based on the notification data.
            FCMPlugin.onNotification(function(data) {
                console.log(data);
                //data.wasTapped == true means in Background :  Notification was received on device tray and tapped by the user.
                //data.wasTapped == false means in foreground :  Notification was received in foreground. Maybe the user needs to be notified.
                if (data.wasTapped) {
                     //Notification was received on device tray and tapped by the user.
                     alert(JSON.stringify(data));
                 } else {
                     //Notification was received in foreground. Maybe the user needs to be notified.
                     alert(JSON.stringify(data));
                 }
            });
        });
        //************Конец кода FCM
    }
};

app.initialize();

Данный файл подключаем ко всем необходимым страницам нашего проекта Cordova. построим приложение и запустим на эмулятор или на реальное устройство:

cordova build android
cordova run android

И далее и консоли отправляем наше первое уведомление:

жмем на «Отправить сообщение» и ждем его в приложении в виде уведомления, причем, приложение может быть закрыто и уведомление все равно придет и будет видно в верхней части экрана устройства или эмулятора:

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

 

Изменение разрешения фотографии для приложения Cordova

Бывает так, что в приложениях, где требуется загрузить фотографию пользователем необходимо уменьшить разрешение фотографии, чтобы интерфейс грузился быстрее, в некоторых случаях это очень необходимо. Для этого есть специальный плагин, который называется cordova-plugin-image-resizer. Ссылка на GitHub проекта.

Для использования необходимо его установить в Cordova через команду:

cordova plugin add https://github.com/protonet/cordova-plugin-image-resizer.git

Далее используем примерно следующим образом:

var userpic = "usrl/to/myimage.jpg";
var options = {
        uri: userpic,
        folderName: "EventApp",
        quality: 90,
        width: 50,
        height: 50,
        base64: true};
try{
  	window.ImageResizer.resize(options,
  	  function(image) {
  	     // success: image is the new resized image
  			userpic = image;
  	  }, function(err) {
  	    // failed: grumpy cat likes this function
  		  console.log(err);
  	  });
}catch(e){
	console.log("Resizer is not work in your browser");
}

 

Стартовый код Cordova и Vue.js

Чтобы программировать для Cordova на современном фреймворке Vue.js необходимо учитывать факторы, которые дают знать коду на Vue.js, что все ресурсы устройства загружены и начался черед исполнения кода на Vue.js. Ниже представлен скелет данного кода. По сути дела, это переделанный код из файла по умолчанию index.js в понятный вид:

var app = {
    initialize: function() {
    	//Делаем инициализацию
        this.bindEvents();
        this.setupVue();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    },
    setupVue: function() {
    	//Начинаем кодить на фреймворке Vue.js
    	var app = new Vue({
    		el: '#app',
    		data: {
    		  message: 'Hello Vue!'
    		}
    	})
    }
}

//Запускаем приложение
app.initialize();

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

Загрузка файла на удаленный сервер в Cordova

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

  • прием файла посредством PHP;
  • прием файла посредством Node.js

 

Плагины и доступы

Для начала нам нужно установить необходимые плагины для работы с загружаемыми файлами:

cordova plugin add cordova-plugin-file
cordova plugin add cordova-plugin-file-transfer
cordova plugin add cordova-plugin-white-list
cordova plugin add cordova-plugin-camera
cordova plugin add cordova-plugin-device

Далее даем доступы на права работы с файлами и с сетями платформе. К примеру. для Android они задаются в файле в папке по пути MyApp\platforms\android\app\src\main\AndroidManifest.xml:

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="io.cordova.hellocordova" xmlns:android="http://schemas.android.com/apk/res/android">
    <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    ...

 

Клиентский код

Кнопка открытия. Обращаем внимание на meta — тег с разрешениями на удаленную передачу:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
    </head>
    <body>
        <button id="getImage">Выбрать картинку</button>
        <script src="cordova.js" ><script>
        <script src="index.js" ><script>
    </body>
</html>

Скрипт:

var app = {
    initialize: function() {
        this.bindEvents();
        this.setupApp();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    },
    setupApp: function(){
                function getImage() {
                    navigator.camera.getPicture(
                        this.uploadPhoto,
                        function (message) { alert('get picture failed'); },
                        {
                            quality: 50,
                            destinationType: navigator.camera.DestinationType.FILE_URI,
                            sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY
                        }
                    );
                }
                function uploadPhoto(imageURI) {
                    alert(imageURI);
                    var options = new FileUploadOptions();
                    options.fileKey = "file";
                    options.fileName = imageURI.substr(imageURI.lastIndexOf('/') + 1);
                    options.mimeType = "image/jpeg";
    
                    var params = {};
                    params.value1 = "test";
                    params.value2 = "param";
    
                    options.params = params;
    
                    var ft = new FileTransfer(); 
                    ft.upload(
                        imageURI, 
                        encodeURI("http://83.220.168.205/upload/upload.php"), 
                        this.win, 
                        this.fail, 
                        options);
                }
                function win(r) {
                    console.log("Code = " + r.responseCode);
                    console.log("Response = " + r.response);
                    console.log("Sent = " + r.bytesSent);
                }
                function fail(error) {
                    alert("An error has occurred: Code = " + error.code);
                    console.log("upload error source " + error.source);
                    console.log("upload error target " + error.target);
                    alert("upload error source " + error.source);
                    alert("upload error target " + error.target);
                }
        document.getElementById("getImage").onclick = function() {
            getImage();
        };
        
    }
    
}

app.initialize();

Серверный код на PHP

Сначала в корне сервера надо создать папку upload и в  ней файл upload.php и подпапку upload, куда будут файлы грузиться и храниться:

<?php
//Задаем заголовки на стороний доступ
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE');
header('Access-Control-Allow-Headers: X-Requested-With,content-type');
header('Access-Control-Allow-Credentials: true');
//
$new_image_name = urldecode($_FILES["file"]["name"]).".jpg";
//Переносим файл в нужную папку
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$new_image_name);
?>

Обращаем внимание на заголовки, которые разрешают доступ со стороны клиента.

Серверный код на JavaScript для Node.js

Если требуется загрузить и заполучить файл со стороны Node.js, то легче все это сделать при помощи стороннего модуля express-formidable, если приложение express. Сначала устанавливаем сам модуль:

npm install express-formidable

Далее дописываем наш app.js на прием. К пример, у нас есть url — адрес http://myhostname:3000/upload, то код для приема и сохранения загруженного с клиента файла будет следующим:

var formidable = require('formidable');

...

app.post('/upload', function(req, res) {
    res.set({
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
        'Access-Control-Allow-Headers': 'X-Requested-With,content-type',
        'Access-Control-Allow-Credentials': 'true'
    });
    //var data = req.body;
    //console.log(data);
    //console.log(req.files);
    var form = new formidable.IncomingForm();

    form.parse(req);

    form.on('fileBegin', function (name, file){
        file.path = __dirname + '/upload/' + file.name + '.jpg';
    });

    form.on('file', function (name, file){
        console.log('Uploaded ' + file.name);
    });
});