Serverless приложения с облачными функциями Firebase
() translation by (you can also view the original English article)
Цель Firebase - помочь разработчикам создавать самые лучшие приложения и превращать их в успешные предприятия. Позаботившись о поддержке вашего приложения или инфраструктуры, Firebase позволяет сосредоточиться на решении проблем для ваших пользователей. Одной из новых интересных функций, анонсированных на конференции Google Cloud Next '17 в марте для Firebase, были облачные функции. В этом уроке вы узнаете об этой новой функции, создав простое приложение для Android с ней.
Что такое облачные функции Firebase?
Облачные функции Firebase запускаются в гостевой, приватной и масштабируемой среде Node.js, где вы можете выполнять JavaScript-код. Вы просто создаете реагирующие функции, которые запускаются всякий раз, когда происходит событие. Облачные функции доступны как для Google Cloud Platform, так и для Firebase (они были созданы поверх облачных функций Google).
На данный момент функции поддерживают следующие триггеры, которые вы можете прослушивать и реагировать на них:
- Триггеры базы данных реального времени: запускать функцию, когда происходит событие записи в базу данных по определенному пути.
- Триггеры аутентификации: запускать функцию при создании нового пользователя или при удалении пользователя.
- Триггеры Google Analytics: запускать функцию, когда регистрируется новое событие преобразования.
- Триггеры облачного хранения: функция может быть запущена, когда есть какие-либо изменения в хранилище, такие как загрузка или обновление файла или папки или удаление их.
- Cloud Pub / Sub Triggers: функция срабатывает при получении нового сообщения в топике Google Cloud Pub/Sub.
- HTTPS Triggers: срабатывает, когда запрос делается на определенный ендпоинт.
Итак, зачем использовать облачные функции?
Итак, теперь вы видели ряд возможностей, которые могут предложить функции Cloud. Но зачем их использовать?
Запуск и настройка бэкенд части и серверов может быть настоящей головной болью - вам приходится обрабатывать такие проблемы, как масштабируемость и написание кода на серверных языках, но с облачными функциями эта сложность уменьшается. Кроме того, вычислительные интенсивные задачи могут выполняться в облаке, а не на клиентском устройстве (например, изменение размера изображения для загрузки или записи по нескольким путям вашей базы данных). Ваш код также будет более безопасным в облаке, чем на клиентском устройстве, чтобы вы могли безопасно хранить такие данные, как секретные ключи.
В этом уроке вы узнаете, как использовать триггеры базы данных реального времени, которые будут срабатывать при возникновении события записи базы данных. Затем мы увидим, как использовать службу Firebase Cloud Messaging для отправки уведомлений устройствам, подписанным на определенный топик. Мы создадим простое приложение под названием Tutsplus Alerts, которое будет отправлять уведомления подписчикам темы «android» всякий раз, когда доступна новая статья.
Предпосылки
Чтобы следовать этому руководству, вы должны быть знакомы с:
И вы должны иметь Node.js, установленный на вашем компьютере.
Ознакомьтесь с приведенными ниже учебными пособиями на Envato Tuts +, если вам нужна помощь в работе с Firebase:
- Android SDKНачинаем работать с Firebase на AndroidАшраф Хатибелагал
- FirebaseFirebase для Android: уведомления и приложенияПол Требилкокс-Руис
- Android SDKНачинаем работать с Firebase AndroidАшраф Хатибелагал
1. Создаем облачную функцию Firebase
Установка командной строки Firebase
Теперь, давайте загрузим Cloud Functions.
Чтобы начать использовать Cloud-функции, нам нужен Firebase CLI (интерфейс командной строки), установленный с npm. Если у вас уже установлен node на вашем компьютере, вы можете установить Cloud Functions с помощью следующей команды:
1 |
npm install -g firebase-tools |
Эта команда установит CLI Firebase глобально вместе со всеми необходимыми зависимостями Node.js.
Инициализация проекта
Для инициализации вашего проекта нужно:
- Выполнить
firebase login
для входа в Firebase через браузер и проверки подлинности инструмента CLI. - Создать новый каталог проекта с именем tutsplus-alerts.
- Наконец, запустите
firebase init functions
из этого нового каталога. Этот инструмент дает вам возможность устанавливать зависимости с NPM. Можно и отказаться, если вы хотите управлять зависимостями по-другому.
После успешного завершения этих команд структура вашего проекта будет выглядеть следующим образом:
- .firebaserc: скрытый файл, который поможет вам быстро переключаться между проектами с помощью команды
firebase use
. - firebase.json: описывает свойства вашего проекта.
- functions/: эта папка содержит весь код для ваших функций.
- functions/package.json: файл пакета NPM, описывающий ваши облачные функции.
- functions/index.js: основной источник для вашего кода облачных функций.
- functions/node_modules/: папка, в которой установлены все ваши зависимости NPM.
Импорт необходимых модулей и инициализация приложения
Чтобы разработать наше простое приложение Tutsplus Alerts, нам нужны только два модуля node: Cloud Functions и Admin SDK modules (эти модули уже установлены для нас). Поэтому перейдите в index.js и добавьте эти модули, а затем инициализируйте экземпляр приложения администратора.
1 |
var functions = require('firebase-functions'); |
2 |
var admin = require('firebase-admin'); |
3 |
|
4 |
admin.initializeApp(functions.config().firebase); |
Код облачной функции
Теперь, когда необходимые модули для нашего проекта были импортированы и инициализированы, давайте напишем нашу облачную функцию в файле index.js. Как уже говорилось ранее, мы собираемся написать функцию, которая будет запущена, всякий раз когда событие onWrite()
произойдет в нашей базе данных реального времени Firebase, а затем в ответ отправит уведомление на устройство.
1 |
// ...
|
2 |
exports.sendNotification = functions.database.ref('/articles/{articleId}') |
3 |
.onWrite(event => { |
4 |
|
5 |
// Grab the current value of what was written to the Realtime Database.
|
6 |
var eventSnapshot = event.data; |
7 |
var str1 = "Author is "; |
8 |
var str = str1.concat(eventSnapshot.child("author").val()); |
9 |
console.log(str); |
10 |
|
11 |
var topic = "android"; |
12 |
var payload = { |
13 |
data: { |
14 |
title: eventSnapshot.child("title").val(), |
15 |
author: eventSnapshot.child("author").val() |
16 |
}
|
17 |
};
|
18 |
|
19 |
// Send a message to devices subscribed to the provided topic.
|
20 |
return admin.messaging().sendToTopic(topic, payload) |
21 |
.then(function (response) { |
22 |
// See the MessagingTopicResponse reference documentation for the
|
23 |
// contents of response.
|
24 |
console.log("Successfully sent message:", response); |
25 |
})
|
26 |
.catch(function (error) { |
27 |
console.log("Error sending message:", error); |
28 |
});
|
29 |
});
|
В приведенном выше коде мы слушаем путь базы данных /articles/{articleId}
, где {articleId}
представляет идентификатор статьи, которая была успешно записана. Теперь мы знаем о данных, которые были написаны. Чтобы получить их, мы используем event.data
, который является статическим интерфейсом DeltaSnapshot.
Затем добавьте данные из этого snapshot в payload сообщения и отправьте его в тему «android». Асинхронный код упрощается обещаниями JavaScript.
Обратите внимание, что в приведенном выше коде мы записали данные на консоль с помощью функции console.log()
, которая поможет нам в отладке и мониторинге. Мы можем просмотреть этот лог либо в нашей панели Firebase, либо через командную строку с помощью:
1 |
firebase functions:log |
Имейте в виду, что, поскольку это выполняется на Node.js, вы можете установить другие модули из NPM. Вы можете также писать на JavaScript ES6 или TypeScript вместо обычного JavaScript.
Развертывание облачной функции
Развернем нашу Cloud Function. Запустите эту команду для развертывания:
1 |
$ firebase deploy --only functions |
Теперь мы можем написать Android-приложение, которое будет подписаться на эту тему, записать в базу данных в реальном времени и получить уведомление, когда данные будут записаны в нашу базу данных, то есть когда наша облачная функция будет выполнена!
2. Создайте приложение TutsplusAlerts
Создание проекта Android Studio
Сначала запустите Android Studio и создайте новый проект «TutsplusAlerts» с пустым действием MainActivity
.
Чтобы следовать дальше, убедитесь, что вы включили Firebase в свое приложение.
Добавить зависимость базы данных в реальном времени
Добавьте следующую зависимость в файл build.gradle:
1 |
compile 'com.google.firebase:firebase-database:10.2.1' |
2 |
Убедитесь, что вы синхронизировали свой проект после его добавления.
Создаем модель
Давайте смоделируем объект статьи, который будет сохраняться в нашей базе данных в реальном времени.
1 |
public class Article { |
2 |
|
3 |
public String title; |
4 |
public String author; |
5 |
|
6 |
public Article() { |
7 |
// Default constructor required for calls to DataSnapshot.getValue(Article.class)
|
8 |
}
|
9 |
|
10 |
public Article(String title, String author) { |
11 |
this.title = title; |
12 |
this.author = author; |
13 |
}
|
14 |
}
|
Создание макета XML
Наш XML-макет для основной Activity будет иметь только два EditTexts
и кнопку, которая отправит новую статью.
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<LinearLayout
|
3 |
xmlns:android="https://schemas.android.com/apk/res/android" |
4 |
xmlns:tools="http://schemas.android.com/tools" |
5 |
xmlns:app="http://schemas.android.com/apk/res-auto" |
6 |
android:layout_width="match_parent" |
7 |
android:layout_height="match_parent" |
8 |
tools:context="com.chikeandroid.tutsplusalerts.MainActivity" |
9 |
android:orientation="vertical"> |
10 |
|
11 |
<EditText
|
12 |
android:id="@+id/et_title" |
13 |
android:layout_width="match_parent" |
14 |
android:layout_height="wrap_content" |
15 |
android:hint="Title"/> |
16 |
|
17 |
<EditText
|
18 |
android:id="@+id/et_author" |
19 |
android:layout_width="match_parent" |
20 |
android:layout_height="wrap_content" |
21 |
android:hint="Author"/> |
22 |
|
23 |
<Button
|
24 |
android:id="@+id/btn_submit" |
25 |
android:layout_width="match_parent" |
26 |
android:layout_height="wrap_content" |
27 |
android:hint="Submit"/> |
28 |
</LinearLayout>
|
Запись в базу данных реального времени
Теперь мы собираемся сделать запись в базу по адресу /articles/
.
1 |
// ...
|
2 |
@Override
|
3 |
protected void onCreate(Bundle savedInstanceState) { |
4 |
super.onCreate(savedInstanceState); |
5 |
setContentView(R.layout.activity_main); |
6 |
|
7 |
final FirebaseDatabase database = FirebaseDatabase.getInstance(); |
8 |
|
9 |
final EditText titleEditText = (EditText)findViewById(R.id.et_title); |
10 |
final EditText authorEditText = (EditText)findViewById(R.id.et_author); |
11 |
Button submitButton = (Button)findViewById(R.id.btn_submit); |
12 |
submitButton.setOnClickListener(new View.OnClickListener() { |
13 |
@Override
|
14 |
public void onClick(View view) { |
15 |
DatabaseReference myRef = database.getReference("articles").push(); |
16 |
Article article = new Article(titleEditText.getText().toString(), |
17 |
authorEditText.getText().toString()); |
18 |
myRef.setValue(article); |
19 |
}
|
20 |
});
|
21 |
}
|
22 |
//...
|
Вашему приложению потребуется доступ на запись в базу данных. Только для демонстрационных целей вы можете установить правила безопасности для всех чтений и записей. В реальном приложении вы никогда не должны использовать такие небезопасные настройки.
1 |
{
|
2 |
"rules": { |
3 |
".read": "true", |
4 |
".write": "true" |
5 |
}
|
6 |
}
|
Вы можете узнать больше о правилах безопасности Firebase в моей статье здесь, в Envato Tuts +.
Запуск приложения
На этом этапе мы можем протестировать приложение и проверить, была ли наша Cloud Function успешно выполнена. Введите название и автора, а затем нажмите кнопку отправки. После этого зайдите на панель инструментов «Функции» и просмотрите логи. Должен появится наш новый лог.



Из логов, приведенных выше, мы видим, что мы успешно выполнили нашу облачную функцию и отправили сообщение с полезной payload на устройства, подписанные на тему «android». В следующем разделе мы будем использовать Firebase Cloud Messaging, чтобы устройства могли подписаться на тему, а затем обработать входящее сообщение с сервера, чтобы показать уведомление.
3. Добавляем поддержку Firebase Cloud Messaging
Включить зависимость
Включите зависимость Firebase Messaging в файл build.gradle и затем выполните синхронизацию вашего проекта:
1 |
compile 'com.google.firebase:firebase-messaging:10.2.1' |
Обработка сообщений
Нам нужно создать службу, которая наследуется от FirebaseMessagingService и переопределяет обратные вызовы onMessageReceived
.
1 |
package com.chikeandroid.tutsplusalerts; |
2 |
|
3 |
import com.google.firebase.messaging.FirebaseMessagingService; |
4 |
import com.google.firebase.messaging.RemoteMessage; |
5 |
|
6 |
import android.app.NotificationManager; |
7 |
import android.app.PendingIntent; |
8 |
import android.content.Context; |
9 |
import android.content.Intent; |
10 |
import android.media.RingtoneManager; |
11 |
import android.net.Uri; |
12 |
import android.support.v4.app.NotificationCompat; |
13 |
|
14 |
public class MyFirebaseMessagingService extends FirebaseMessagingService { |
15 |
|
16 |
@Override
|
17 |
public void onMessageReceived(RemoteMessage remoteMessage) { |
18 |
|
19 |
// Check if message contains a data payload.
|
20 |
if (remoteMessage.getData().size() > 0) { |
21 |
showNotification(remoteMessage.getData().get("title"), remoteMessage.getData().get("author")); |
22 |
}
|
23 |
|
24 |
// Check if message contains a notification payload.
|
25 |
if (remoteMessage.getNotification() != null) { |
26 |
|
27 |
}
|
28 |
}
|
29 |
|
30 |
private void showNotification(String title, String author) { |
31 |
Intent intent = new Intent(this, MainActivity.class); |
32 |
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); |
33 |
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, |
34 |
PendingIntent.FLAG_ONE_SHOT); |
35 |
|
36 |
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); |
37 |
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) |
38 |
.setContentTitle("New Article: " + title) |
39 |
.setSmallIcon(R.mipmap.ic_launcher) |
40 |
.setContentText("By " + author) |
41 |
.setAutoCancel(true) |
42 |
.setSound(defaultSoundUri) |
43 |
.setContentIntent(pendingIntent); |
44 |
|
45 |
NotificationManager notificationManager = |
46 |
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); |
47 |
|
48 |
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); |
49 |
}
|
50 |
}
|
В приведенном выше коде мы также получаем данные payload и показываем их в уведомлении независимо от того, находится ли приложение на переднем плане или в фоновом состоянии.
Обновление файла манифеста
Обновите файл манифеста, включая службу, созданную ранее в теге <application>
.
1 |
//.. |
2 |
<service
|
3 |
android:name=".MyFirebaseMessagingService"> |
4 |
<intent-filter>
|
5 |
<action android:name="com.google.firebase.MESSAGING_EVENT"/> |
6 |
</intent-filter>
|
7 |
</service>
|
8 |
//... |
Подписываемся на топик
Наконец, нам нужно подписаться на тему «android», чтобы устройство могло получать и обрабатывать сообщения, отправленные на эту тему.
1 |
/...
|
2 |
@Override
|
3 |
protected void onCreate(Bundle savedInstanceState) { |
4 |
// ...
|
5 |
FirebaseMessaging.getInstance().subscribeToTopic("android"); |
6 |
// ...
|
7 |
}
|
8 |
//...
|
Запуск приложения
Запустите приложение во второй раз и введите название и автора статьи, а затем нажмите кнопку отправки. На этот раз уведомление будет отображаться всякий раз, когда новая статья будет отправлена в базу данных любым пользователем приложения.



Для этого перед облачными функциями вам понадобился бы HTTP или XMPP-сервер, что означало бы больше кода, а также сервер для настройки и поддержки.
Вывод
В этом уроке вы узнали об облачных функциях Firebase: что это такое, зачем они вам нужны, и как начать пользоваться облачными функциями в вашем приложении. Имейте в виду, что на момент написания этой статьи облачные функции для Firebase все еще находятся в открытом бета-версии.
Чтобы узнать больше о облачных функциях Firebase, обратитесь к официальной документации. А пока ознакомьтесь с некоторыми нашими другими курсами и учебными пособиями по разработке приложений для Android!
- Android SDKAndroid-датчики: близость и гироскопАшраф Хатибелагал
- Android SDKAndroid Things: ваш первый проектПол Требилкокс-Руис
- Android SDK6 Вещей которые нужно и не нужно делать для отличного пользовательского опыта AndroidДжессика Торнсби
- Android SDKНачало работы с RxJava 2 на AndroidДжессика Торнсби