Статьи

Бессерверные приложения с облачными функциями Firebase

Цель Firebase — помочь разработчикам создавать лучшие приложения и развивать их в успешном бизнесе. Заботясь о бэкэнде или инфраструктуре вашего приложения, Firebase позволяет вам сосредоточиться на решении проблем ваших пользователей. Одна из новых интересных функций, анонсированных на конференции Google Cloud Next ’17 в марте этого года для Firebase, была Cloud Functions . В этом руководстве вы узнаете об этой новой функции, создав с ее помощью простое приложение для Android.

Облачные функции Firebase работают в размещенной, частной и масштабируемой среде Node.js, где вы можете запускать код JavaScript. Вы просто создаете реактивные функции, которые запускаются всякий раз, когда происходит событие. Облачные функции доступны как для Google Cloud Platform, так и для Firebase (они были созданы поверх облачных функций Google).

На данный момент облачные функции поддерживают следующие триггеры, которые вы можете прослушивать и реагировать на них:

Итак, теперь вы увидели ряд возможностей, которые могут предложить облачные функции. Но зачем их использовать?

Запуск и настройка серверной части и серверов могут быть настоящей проблемой — вам приходится решать такие проблемы, как масштабируемость и написание кода на серверных языках, — но с помощью облачных функций эта сложность уменьшается. Кроме того, вычислительные задачи могут выполняться в облаке, а не на клиентском устройстве (например, изменение размера изображения для загрузки или записи в несколько путей вашей базы данных). Ваш код также будет более безопасным в облаке, чем на клиентском устройстве, поэтому вы можете безопасно хранить такие данные, как секретные ключи на вашем сервере.

В этом руководстве вы узнаете, как использовать триггеры базы данных реального времени, которые срабатывают при возникновении события записи в базу данных. Затем мы увидим, как использовать службу Firebase Cloud Messaging для отправки уведомлений на устройства, которые подписались на тему. Мы создадим простое приложение под названием Tutsplus Alerts , которое будет отправлять уведомление подписчикам темы «android» всякий раз, когда будет доступна новая статья.

Чтобы следовать этому уроку, вы должны быть знакомы с:

И у вас должен быть установлен Node.js на вашем компьютере.

Посмотрите следующие уроки здесь на Envato Tuts +, если вам нужна помощь для начала работы с Firebase:

  • Android SDK
    Начните с Firebase для Android
    Ашраф Хатхибелагал
  • Firebase
    Firebase для Android: уведомления и приглашения приложений
    Пол Требилкокс-Руис
  • Android SDK
    Начните с Firebase для Android
    Ашраф Хатхибелагал

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

Чтобы начать использовать облачные функции, нам нужен Firebase CLI ( интерфейс командной строки), установленный с npm . Если на вашем компьютере уже настроен Node, вы можете установить Cloud Functions с помощью:

1
npm install -g firebase-tools

Эта команда установит интерфейс командной строки Firebase вместе со всеми необходимыми зависимостями Node.js.

Чтобы инициализировать ваш проект:

  1. Запустите firebase login чтобы войти в Firebase через браузер и аутентифицировать инструмент CLI.
  2. Создайте новый каталог проекта с именем tutsplus -alerts .
  3. Наконец, запустите firebase init functions из этого нового каталога. Этот инструмент дает вам возможность установить зависимости с помощью NPM. Отказаться безопасно, если вы хотите управлять зависимостями другим способом.

После успешного выполнения этих команд структура вашего проекта выглядит следующим образом:

  • .firebaserc : скрытый файл, который помогает вам быстро переключаться между проектами с firebase use .
  • firebase.json : описывает свойства для вашего проекта.
  • functions / : эта папка содержит весь код для ваших функций.
  • functions / package.json : файл пакета NPM, описывающий ваши облачные функции.
  • functions / index.js : основной источник кода вашего Cloud Functions.
  • functions / node_modules / : папка, в которой установлены все ваши зависимости NPM.

Для разработки нашего простого приложения Tutsplus Alerts нам просто нужны два модуля узлов: модули облачных функций и Admin SDK (эти модули уже установлены для нас). Поэтому перейдите в index.js и потребуйте эти модули, а затем инициализируйте экземпляр приложения администратора.

1
2
3
4
var functions = require(‘firebase-functions’);
var admin = require(‘firebase-admin’);
 
admin.initializeApp(functions.config().firebase);

Теперь, когда необходимые модули для нашего проекта были импортированы и инициализированы, давайте закодируем нашу облачную функцию в файле index.js . Как указывалось ранее, мы напишем функцию, которая будет onWrite() при возникновении onWrite() в нашей базе данных реального времени Firebase, а затем в ответ отправит уведомление (нисходящее сообщение) подписчикам устройства.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// …
exports.sendNotification = functions.database.ref(‘/articles/{articleId}’)
        .onWrite(event => {
 
        // Grab the current value of what was written to the Realtime Database.
        var eventSnapshot = event.data;
        var str1 = «Author is «;
        var str = str1.concat(eventSnapshot.child(«author»).val());
        console.log(str);
 
        var topic = «android»;
        var payload = {
            data: {
                title: eventSnapshot.child(«title»).val(),
                author: eventSnapshot.child(«author»).val()
            }
        };
 
        // Send a message to devices subscribed to the provided topic.
        return admin.messaging().sendToTopic(topic, payload)
            .then(function (response) {
                // See the MessagingTopicResponse reference documentation for the
                // contents of response.
                console.log(«Successfully sent message:», response);
            })
            .catch(function (error) {
                console.log(«Error sending message:», error);
            });
        });

В приведенном выше коде мы слушаем путь к базе данных /articles/{articleId} , где {articleId} представляет идентификатор статьи, которая была успешно написана. Теперь, что нас действительно беспокоит, так это данные, которые были написаны. Чтобы получить это, мы используем event.data , который является статическим интерфейсом DeltaSnapshot .

Затем добавьте данные из этого снимка в полезную нагрузку сообщения и отправьте их в раздел «Android». Асинхронный код упрощается обещаниями JavaScript .

Обратите внимание, что в приведенном выше коде мы написали в консоль с помощью console.log() , который поможет нам в отладке и мониторинге. Мы можем просмотреть этот журнал либо на нашей панели инструментов Firebase, либо через командную строку:

1
firebase functions:log

Имейте в виду, что, поскольку это выполняется на Node.js, вы можете установить другие модули, доступные из NPM. Вы также можете кодировать в JavaScript ES6 или TypeScript вместо обычного JavaScript.

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

1
$ firebase deploy —only functions

Теперь мы можем кодировать приложение для Android, которое будет подписываться на эту тему, записывать в базу данных в реальном времени и получать уведомление, когда данные записываются в нашу базу данных в реальном времени, то есть когда будет выполняться наша облачная функция!

Сначала запустите Android Studio и создайте новый проект TutsplusAlerts с пустым действием MainActivity .

Android Studio создает новый проект

Чтобы следовать этому, убедитесь, что вы интегрировали Firebase в свое приложение .

Добавьте следующую зависимость в ваш файл build.gradle :

1
compile ‘com.google.firebase:firebase-database:10.2.1’

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

Давайте смоделируем объект статьи для сохранения в нашей базе данных в реальном времени.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class Article {
 
    public String title;
    public String author;
 
    public Article() {
        // Default constructor required for calls to DataSnapshot.getValue(Article.class)
    }
 
    public Article(String title, String author) {
        this.title = title;
        this.author = author;
    }
}

Наш XML-макет для основного Activity будет иметь только два EditTexts и просто кнопку, которая представит новую статью.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout
        xmlns:android=»https://schemas.android.com/apk/res/android»
        xmlns:tools=»http://schemas.android.com/tools»
        xmlns:app=»http://schemas.android.com/apk/res-auto»
        android:layout_width=»match_parent»
        android:layout_height=»match_parent»
        tools:context=»com.chikeandroid.tutsplusalerts.MainActivity»
        android:orientation=»vertical»>
 
    <EditText
            android:id=»@+id/et_title»
            android:layout_width=»match_parent»
            android:layout_height=»wrap_content»
            android:hint=»Title»/>
 
    <EditText
            android:id=»@+id/et_author»
            android:layout_width=»match_parent»
            android:layout_height=»wrap_content»
            android:hint=»Author»/>
 
    <Button
            android:id=»@+id/btn_submit»
            android:layout_width=»match_parent»
            android:layout_height=»wrap_content»
            android:hint=»Submit»/>
</LinearLayout>

Теперь мы собираемся написать путь к базе данных в реальном времени /articles/ .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
// …
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    final FirebaseDatabase database = FirebaseDatabase.getInstance();
 
    final EditText titleEditText = (EditText)findViewById(R.id.et_title);
    final EditText authorEditText = (EditText)findViewById(R.id.et_author);
    Button submitButton = (Button)findViewById(R.id.btn_submit);
    submitButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            DatabaseReference myRef = database.getReference(«articles»).push();
            Article article = new Article(titleEditText.getText().toString(),
                    authorEditText.getText().toString());
            myRef.setValue(article);
        }
    });
}
//…

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

1
2
3
4
5
6
{
  «rules»: {
    «.read»: «true»,
    «.write»: «true»
  }
}

Вы можете узнать больше о Правилах безопасности Firebase в моем посте здесь на Envato Tuts +.

  • Мобильная разработка
    Правила безопасности Firebase

На этом этапе мы можем протестировать приложение и посмотреть, была ли наша облачная функция выполнена успешно. Введите название и автора, а затем нажмите кнопку «Отправить». После этого посетите панель инструментов « Функции» и просмотрите журналы. Наш пользовательский журнал должен появиться.

Панель инструментов облачных функций

Из журналов выше мы видим, что мы успешно выполнили нашу облачную функцию и отправили сообщение с полезной нагрузкой на устройства, подписанные на тему « android », но ни одно устройство еще не подписалось на эту тему. В следующем разделе мы будем использовать Firebase Cloud Messaging, чтобы устройства могли подписаться на тему, а затем обработать входящее сообщение с сервера, чтобы отобразить уведомление.

Включите зависимость Firebase Messaging в файл build.gradle и синхронизируйте ваш проект после этого:

1
compile ‘com.google.firebase:firebase-messaging:10.2.1’

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.chikeandroid.tutsplusalerts;
 
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
 
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
 
public class MyFirebaseMessagingService extends FirebaseMessagingService {
 
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
 
        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            showNotification(remoteMessage.getData().get(«title»), remoteMessage.getData().get(«author»));
        }
 
        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
 
        }
    }
 
    private void showNotification(String title, String author) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
 
        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setContentTitle(«New Article: » + title)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentText(«By » + author)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);
 
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
}

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

Обновите файл манифеста, включая службу, созданную ранее внутри <application> .

1
2
3
4
5
6
7
8
//..
<service
    android:name=».MyFirebaseMessagingService»>
    <intent-filter>
        <action android:name=»com.google.firebase.MESSAGING_EVENT»/>
    </intent-filter>
</service>
//…

Наконец, нам нужно подписаться на тему « android », чтобы устройство могло получать и обрабатывать сообщения, отправленные в эту тему.

1
2
3
4
5
6
7
8
/…
@Override
protected void onCreate(Bundle savedInstanceState) {
    // …
    FirebaseMessaging.getInstance().subscribeToTopic(«android»);
    // …
}
//…

Запустите приложение во второй раз и введите название и автора, а затем нажмите кнопку «Отправить». На этот раз уведомление будет отображаться всякий раз, когда какой-либо пользователь приложения публикует в базе данных новую статью.

финальные скриншоты приложения

Чтобы сделать это до Cloud Functions, вам понадобится сервер HTTP или XMPP, который будет означать больше кода для записи, а также сервер для настройки и поддержки.

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

Чтобы узнать больше об облачных функциях для Firebase, обратитесь к официальной документации . А пока, ознакомьтесь с некоторыми другими нашими курсами и учебными пособиями по разработке приложений для Android!

  • Android SDK
    Датчики Android в глубине: приближение и гироскоп
    Ашраф Хатхибелагал
  • Android SDK
    Android Things: ваш первый проект
    Пол Требилкокс-Руис
  • Android SDK
    6 Что нужно и чего не нужно для отличного пользовательского опыта на Android
    Джессика Торнсби
  • Android SDK
    Начните с RxJava 2 для Android
    Джессика Торнсби