company_banner

По следам Google I/O 2016 — новый Firebase: интеграция с Android

    Привет, Хабр! Мы продолжаем цикл статей по технологиям, представленным на нашем ежегодном мероприятии Google I/O. Сегодня у нас в гостях Александр Денисов, и он расскажет про своё знакомство с базовыми возможностями обновлённого Firebase.



    Привет, Я — Александр Денисов, работают в Netcracker на должности Senior Software Developer и возглавляю GDG Нижнего Новгорода. Я давно слежу за технологиями, которые развивает Google, и в этот раз просто не мог пройти мимо Firebase. Изменений много, сами по себе они концептуальные, и, наконец, превращают сам Firebase в один большой сервис по построению мобильного бэкэнда.

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

    Предыстория


    Совместная история Google и Firebase началась в далеком 2014-м году: тогда команда Firebase в полном составе просто перешла в Google и продолжила работу над своим продуктом, получив доступ к облачным возможностям Google Cloud Platform и другим технологиям Google. В те временасам Firebase представлял собой, по сути, набор REST сервисов для управления облачной NoSQL базой данных, предназначенной для хранения и синхронизации данных между несколькими клиентами, и связанные с ними сервисы аутентификации и хостинга. Выглядело это примерно так:



    В 2016 году проходит юбилейный, десятый Google I/O, и на нём представляют новые возможности Firebase. Он вырос, повзрослел иразросся до набора из 15 продуктов, предназначенных не только для девелопмента, но также и для облегчения продвижения и монетизации приложений. Эти продукты можно использовать как по отдельности, так и в любых сочетаниях — в зависимости от ваших потребностей.



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

    1. Firebase — первые шаги


    Подготовительные работы, регистрация и авторизация


    Создадим простой проект (назовем его com.google.simplefirebasechat) с пустой разметкой. Начало положено, теперь надо связать его с Firebase. Для этого переходим в основной инструмент для управления Firebase — консоль и кликаем «Создать новый проект»:



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



    Система предложит нам указать название нашего приложения и ключ безопасности формата SHA1





    Прим.: Если вы выдруг забыли, какой у вас ключ — откройте консоль Windows (Win+R, CMD, Enter) и извлеките его из debug.keystore. Для этого введите следующие команды:

    keytool -exportcert -alias androiddebugkey -keystore %USERPROFILE%/.android/debug.keystore -list -v
    


    И авторизуйтесь паролем от вашего отладочного репозитория, (по умолчанию «android»)



    После того, как вы предоставите все необходимые данные, браузер автоматически загрузит сгенерированный Firebase конфигурационный json с метаданными, необходимыми для работы. Полученный файл следует положить в каталог app нашего приложения. Теперь в build.gradle уровня проекта необходимо добавить зависимость от соответствующей библиотеки
    classpath 'com.google.gms:google-services:3.0.0'


    Также следует дописать в конец build.gradle в каталоге app следующую строчку
    apply plugin: 'com.google.gms.google-services'


    которая подключает к проекту Google Services плагин, необходимый для процессинга конфигурационного JSONa и подключения основных библиотек com.google.gms:google-services.

    Вуаля! Firebase связан с приложением, которое можно попробовать собрать!

    Проверяем работоспособность Firebase


    Следующий шаг — проверить, что всё в порядке, и мы действительно подключились. Для этого мы добавим в базу пару записей, а затем прочитаем их в приложении.

    Открываем консоль Firebase, ищем вкладкуDatabase, и создадём в ней простой JSON для хранения сообщений. Интерфейс консоли легко позволяет сделать это.



    Теперь прочитаем занесённые данные, запросив их из нашего приложения… Чтобы получить к ним доступ и иметь возможность отображать их в нашем интерфейсе, добавим несколько соответствующих зависимостей в build.gradle
    compile 'com.google.firebase:firebase-database:9.0.0'
    compile 'com.firebaseui:firebase-ui-database:0.4.0'
    compile 'de.hdodenhof:circleimageview:1.3.0'
    compile 'com.github.bumptech.glide:glide:3.6.1'


    Ещё мы добавим новый класс для сообщения в чате и разметку для его отображения. С необходимыми приготовлениями закончено, теперь займёмся отображением контента, полученного из БД.
    Для этого нам потребуется создать основную activity и разместить на ней элементы интерфейса, которые помогут нам проверить работу Firebase. Добавляем поле для ввода сообщения, кнопку Send, ProgressBar на время загрузки данных и RecyclerView для отображения данных из БД, а в сам класс допишем пару строк кода.

    Итак, что у нас получилось:
    package com.google.simplefirechat;
    
    import android.content.SharedPreferences;
    import android.preference.PreferenceManager;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.text.Editable;
    import android.text.InputFilter;
    import android.text.TextWatcher;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.firebase.database.DatabaseReference;
    import com.firebase.ui.database.FirebaseRecyclerAdapter;
    import com.google.firebase.database.FirebaseDatabase;
    
    import de.hdodenhof.circleimageview.CircleImageView;
    import com.bumptech.glide.Glide;
    
    public class MainActivity extends AppCompatActivity {
    
       private DatabaseReference mSimpleFirechatDatabaseReference;
       private FirebaseRecyclerAdapter<ChatMessage, FirechatMsgViewHolder>
               mFirebaseAdapter;
       private RecyclerView mMessageRecyclerView;
       private LinearLayoutManager mLinearLayoutManager;
       private ProgressBar mProgressBar;
    
       public static class FirechatMsgViewHolder extends RecyclerView.ViewHolder {
           public TextView msgTextView;
           public TextView userTextView;
           public CircleImageView userImageView;
    
           public FirechatMsgViewHolder(View v) {
               super(v);
               msgTextView = (TextView) itemView.findViewById(R.id.msgTextView);
               userTextView = (TextView) itemView.findViewById(R.id.userTextView);
             userImageView = (CircleImageView) itemView.findViewById(R.id.userImageView);
           }
       }
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
          
           mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
           mMessageRecyclerView = (RecyclerView) findViewById(R.id.messageRecyclerView);
           mLinearLayoutManager = new LinearLayoutManager(this);
           mLinearLayoutManager.setStackFromEnd(true);
           mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
    
           mSimpleFirechatDatabaseReference = FirebaseDatabase.getInstance().getReference();
           mFirebaseAdapter = new FirebaseRecyclerAdapter<ChatMessage,
                   FirechatMsgViewHolder>(
                   ChatMessage.class,
                   R.layout.chat_message,
                   FirechatMsgViewHolder.class,
                   mSimpleFirechatDatabaseReference.child("messages")) {
    
               @Override
               protected void populateViewHolder(FirechatMsgViewHolder viewHolder, ChatMessage friendlyMessage, int position) {
                   mProgressBar.setVisibility(ProgressBar.INVISIBLE);
                   viewHolder.msgTextView.setText(friendlyMessage.getText());
                   viewHolder.userTextView.setText(friendlyMessage.getName());
                   if (friendlyMessage.getPhotoUrl() == null) {
                       viewHolder.userImageView
                               .setImageDrawable(ContextCompat
                                       .getDrawable(MainActivity.this,
                                               R.drawable.ic_account_circle_black_36dp));
                   } else {
                       Glide.with(MainActivity.this)
                               .load(friendlyMessage.getPhotoUrl())
                               .into(viewHolder.userImageView);
                   }
               }
           };
    
           mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
               @Override
               public void onItemRangeInserted(int positionStart, int itemCount) {
                   super.onItemRangeInserted(positionStart, itemCount);
                   int chatMessageCount = mFirebaseAdapter.getItemCount();
                   int lastVisiblePosition =
                           mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
                   if (lastVisiblePosition == -1 ||
                           (positionStart >= (chatMessageCount - 1) &&
                                   lastVisiblePosition == (positionStart - 1))) {
                       mMessageRecyclerView.scrollToPosition(positionStart);
                   }
               }
           });
    
           mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
           mMessageRecyclerView.setAdapter(mFirebaseAdapter);
       }
    }


    На данном этапе мы не добавляли в приложение инструменты по авторизации, поэтому просто предоставимправа на неавторизованное чтение из БД в консоли Firebase. Для этого заходим на вкладку «Правила» и меняем настройки вот таким образом:



    Ну и настало время проверить, что из всего этого вышло. Запускаем наше приложение и вот что видим: запись из базы данных появилась как ранее отправленное сообщение.



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

    2. Запись в Firebase


    Здесь всё просто. Добавляем в MainActivity обработчик нажатия на кнопку Send:
    mSendButton = (Button) findViewById(R.id.sendButton);
    mSendButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           ChatMessage friendlyMessage = new
                   ChatMessage(mMsgEditText.getText().toString(),
                   mUsername,
                   mPhotoUrl);
           mSimpleFirechatDatabaseReference.child("messages")
                   .push().setValue(friendlyMessage);
           mMsgEditText.setText("");
       }
    });


    И это все! Можно снова запускать приложение и баловаться. Пишете текст, нажимаете на кнопку Send, он отображается в чате, и соответствующая запись моментально появляется в БД, которую мы можем посмотреть через консоль Firebase. Осталось добавить последнюю нужную фичу — авторизацию пользователей.

    3. Авторизация в Firebase


    Первым делом мы забираем доступ к БД у неавторизованных пользователей. Включали-то мы его только для тестов. Переходим в консоль, в раздел «Правила» и выставляем всё как было:



    После этого переходим на вкладку Auth и выбираем способ авторизации — в данном случае через Google:



    Снова обновим build.gradle, дописав зависимости от авторизационных библиотек
    compile 'com.google.firebase:firebase-auth:9.0.0'
    compile 'com.google.android.gms:play-services-auth:9.0.0'


    Ещё нам понадобится дополнительная Activity для входа в чат, с соответствующей разметкой (AuthorizationActivity.class и activiti_auth.xml). Только не забудьте прописать её в манифесте. Также неплохо было бы иметь меню, чтобы нам было куда добавить опцию выхода из своего аккаунта (main_menu.xml). Ну в качестве завершающего штриха мынемного поправим MainActivity.

    Подключаем авторизацию


    Во-первых, надо унаследовать Activity от интерфейса GoogleApiClient.OnConnectionFailedListener, ну и реализовать сам этот интерфейс:
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
       Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
    }
    

    Во-вторых, добавить сущности для работы с авторизацией:
    этот интерфейс:
    private GoogleApiClient mGoogleApiClient;
    private FirebaseAuth mFirebaseAuth;
    private FirebaseUser mFirechatUser;


    И их инициализацию в onCreate:
    mGoogleApiClient = new GoogleApiClient.Builder(this)
           .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
           .addApi(Auth.GOOGLE_SIGN_IN_API)
           .build();
    
    mFirebaseAuth = FirebaseAuth.getInstance();
    mFirechatUser = mFirebaseAuth.getCurrentUser();
    if (mFirechatUser == null) {
       startActivity(new Intent(this, AuthorizationActivity.class));
       finish();
       return;
    } else {
       mUsername = mFirechatUser.getDisplayName();
       if (mFirechatUser.getPhotoUrl() != null) {
           mPhotoUrl = mFirechatUser.getPhotoUrl().toString();
       }
    }


    В-третьих, добавитьвызов из меню для того, чтобы пользователь мог разлогиниться:
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       switch (item.getItemId()) {
           case R.id.sign_out_menu:
               mFirebaseAuth.signOut();
               Auth.GoogleSignInApi.signOut(mGoogleApiClient);
               mUsername = DEFAULT_NAME;
               startActivity(new Intent(this, AuthorizationActivity.class));
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }


    Теперь можно запускать и тестировать приложение с авторизацией через Google-аккаунт.


    Cообщения должны иметь следующий вид:



    А в консоли Firebase, во вкладке Auth, выможете посмотреть пользователей, которые были авторизованы в нашем приложении:



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

    4. Уведомления с помощью Firebase Notifications


    Firebase Notifications позволяет отправлять уведомления на пользовательские устройства прямо из консоли Firebase. Причём вы можете выбрать — отправить всем пользователям, какой-то конкретной группе (здесь также работает интеграция в новый инструмент Firebase Аудитории) или вообще пользователям конкретных устройств. Но для работы с этими уведомлениями нужно научить приложение принимать их, а для этого надо сконфигурировать соотвествующий сервис.

    Подключаем Firebase Notifications


    Для начала добавим в build.gradle соответствующую … (зависимость, команду, whatever)
    compile 'com.google.firebase:firebase-messaging:9.0.0'


    Далее, создадим сервис SimpleFirechatMessagingService который будем использовать для управления входящими FCM-сообщениями (Firebase Clouds Messages). Нам достаточно переопределить метод onMessageReceived(RemoteMessage remoteMessage), чтобы каким-либо образом обработать входящее уведомление.

    Ещё нам потребуется создать сервис SimpleFirechatInstanceIdService для управления FCM логикой. Обычно он используется для оповещении приложения о том, что сгенерирован новый токен, а также для получения этого токена. Просто переопределим метод onTokenRefresh()

    Всё что нам осталось — зарегистрировать сервисы в манифесте, после этого всё должно заработать.
    <service
       android:name=".SimpleFirechatMessagingService"
       android:exported="false">
       <intent-filter>
           <action android:name="com.google.firebase.MESSAGING_EVENT" />
       </intent-filter>
    </service>
    <service
       android:name=".SimpleFirechatInstanceIdService"
       android:exported="false">
       <intent-filter>
           <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
       </intent-filter>
    </service>
    


    Тестируем уведомления


    Запускаем приложение, после этого заходим в консоль Firebase, во вкладку Notifications, и отправляем долгожданное сообщение. Результат моментально отобразится на дисплее смартфона или в эмуляторе:





    Ознакомится с результатами рассылки уведомлений можно в соответствующем разделе консоли Firebase



    5. Firebase Remote Config — изменяем приложение на лету


    Firebase Remote Config позволяет вам задавать в приложениях ряд параметров, которые вы сможете обновить удалённо, с сервера. Таким образом вы можете меня возможности вашего приложения (оформление, например, или перевод) не обновляя весь .apk и не дожидаясь выгрузки его в магазин приложений, а потом ещё и обновления у пользователя на устройстве. В качестве примера давайте попробуем изменять надпись на кнопке отправки сообщения, используя эту фичу.



    Добавляем функциональность


    Для начала зайдем на вкладку Remote Config и создадим переменную button_name



    Теперь надо сконфигурировать приложение.
    Как и в предыдущие разы, начинаем опять с добавления соответствующей зависимости в build.gradle
    compile 'com.google.firebase:firebase-messaging:9.0.0'
    

    … и добавляем метод fetchconfig, в котором мы будем забирать конфигурацию с сервера и применять ее к имени кнопки.
    public void fetchConfig() {
       long cacheExpiration = 3600; // 1 hour in seconds
       // If developer mode is enabled reduce cacheExpiration to 0 so that
       // each fetch goes to the server. This should not be used in release
       // builds.
       if (mFirebaseRemoteConfig.getInfo().getConfigSettings()
               .isDeveloperModeEnabled()) {
           cacheExpiration = 0;
       }
       mFirebaseRemoteConfig.fetch(cacheExpiration)
               .addOnSuccessListener(new OnSuccessListener<Void>() {
                   @Override
                   public void onSuccess(Void aVoid) {
                       // Make the fetched config available via
                       // FirebaseRemoteConfig get<type> calls.
                       mFirebaseRemoteConfig.activateFetched();
                       mSendButton.setText(mFirebaseRemoteConfig.getString("button_name"));
                   }
               })
               .addOnFailureListener(new OnFailureListener() {
                   @Override
                   public void onFailure(@NonNull Exception e) {
                       mSendButton.setText(mFirebaseRemoteConfig.getString("button_name"));
                   }
               });
    }


    Вызывать этот методы мы будем в onCreate и в созданном для этого пункте меню. Для этого добавляем в main_menu.xml следующие строки:
    <item android:id="@+id/reconfig"
    android:title="Reconfig"
    app:showAsAction="never"/>


    В onCreate:
    mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
    
    FirebaseRemoteConfigSettings firebaseRemoteConfigSettings =
           new FirebaseRemoteConfigSettings.Builder()
                   .setDeveloperModeEnabled(true)
                   .build();
    
    Map<String, Object> defaultConfigMap = new HashMap<>();
    defaultConfigMap.put("button_name", "Send");


    … и в onOptionsItemSelected:
    case R.id.reconfig:
       fetchConfig();
       return true;
    


    Проверяем результат


    Алгоритм испытаний аналогичен прошлым. Запускаем приложение, смотрим на текстна кнопке, идём в консоль Firebase, меняем её значение переменной button_name., и вызываем reconfig из меню.

    Вот так просто за полчаса мы создали чат с авторизацией, облачными уведомлениями и удалённой конфигурацией на базе возможностей Firebase.
    P.S.: скачать проект и поковыряться в нём самому можно вот здесь.
    Думаю, на сегодня достаточно практики, время подвести итоги.

    Что мы получили в результате


    Для хранения сообщений мы использовали Realtime Databaseсервисы для управления облачной NoSQL базой данных. Они позволяют сохранять и синхронизировать данные со всеми подключенными устройствами за считанные миллисекунды. В обновлённой версии данные сохраняются в память или на диск устройства, чтобы приложение оставалось работоспособным при потере соединения с сетью, и, само собой, данные синхронизируются после восстановления соединения.

    Для авторизации мы использовали сервис Authenticationсервис для идентификации и управления пользователями. Поддерживает аутентификацию через пару Е-mail и пароль, социальные сети (Facebook, Twitter, GitHub, Google+) и может быть интегрирован с другими существующими системами авторизации

    Для тестирования уведомлений мы использовали Notificationsсервис, предоставляющий новый UI, доступный через встроенную консоль и основанный на Firebase Cloud Messaging. Он пришел на замену технологии Google Cloud Messaging и даётотправлять уведомления пользователям, не написав ни строки кода. Интеграция с Firebase Analytics позволяетотправлять уведомления заранее настроенным группам пользователей

    Его технологии тесно связаны с проектом Cloud Messaging сервисом, объединяющим Firebase с самым популярным сервисом обмена сообщениями — Google Cloud Messaging. Cloud Messaging кросс-платформенный и работает на iOS, Android и в Web-приложениях.

    И, наконец, для удаленного конфигурирования мы использовали Remote Configсервис, который позволяет изменять и обновлять части приложений, не прибегая к полному обновлению пакета и прохождению сравнительно долгих проверок в магазинах приложений. Для безопасности и простоты работы вам потребуется заранее подумать, что вы хотите обновлять удалённо и задать соответствующие параметры в видепары ключ — значение. Ну а дальше вы сможете вносить изменения в работу и внешний вид приложения путем замены значений данных параметров на стороне сервера. Например, можно обновить оформление приложения к празднику, а потом вернуть всё «как было». И никаких длительных ревью. Как и многие другие элементы Firebase, Notifications интегрируются в Firebase Analytics. То есть вы можете выделять группы различных пользователей (сформированных автоматически по десяткам и сотням параметров) и отправлять обновления именно им…

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

    На сегодня с вас хватит. Но мы обязательно вернёмся к этой теме и рассмотрим оставшиеся возможности нового Firebase: инструменты хранения данных, тестирования приложений, сервисы монетизации и рекламы, а также приятные удобные плюшки типа инвайтов или надёжных ссылок. И, разумеется, самую крутую штуку ever — мощнейшую аналитику и группировку пользователей, которая тесно интегрирована во все остальные возможности.



    Всем спасибо за внимание! Пост получился очень большой, все мы люди, так что если вы нашли опечатку или ошибку — пишите в ЛС, оперативно поправим. А вопросы оставляйте в комментариях. :)
    Google 128,40
    Филин Лаки
    Поделиться публикацией
    Комментарии 17
    • +3
      Зашел посмотреть про обновление Firebase, т.к. это актуально для меня, в результате увидел гайд по чату. Это еще более актуально для меня. Сервис однозначно хорош, достойная замена parse
      • 0
        Не достойная. Фишка parse — облачный код. К сожалению в Firebase этого нет
        • 0

          Облачный код в parse вызывал много боли. В Firebase намного более гибкая концепция.

          • 0
            Облачным кодом парса при этом была возможность заложить определенную логику обработки данных.

            Как Вы при помощи Firebase получите список курьеров в радиусе 500 метров от себя? Всего курьеров в бд 3000000, например.

            P. S. Я не говорю, что Firebase чем то плох. Я говорю только, что это не Parse.com
            • 0
              Как Вы при помощи Firebase получите список курьеров в радиусе 500 метров от себя?

              Приложения курьеров по изменению своих координат обновляют запись в коллекции относящуюся к ним. Ваше приложение… тупо делает запрос "выдай мне документы подпадающие под критерию". Есть еще GeoFire как надстройка над firebase для упрощения подобных выборок но у меня только в планах его поковырять детально. Собственно что еще нужно?


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

              • 0
                Вот я и говорю, что с парсом не нужен был бекенд.
                Про FireGeo почитаю.

                Еще нотификацию не отправить на изменение статуса без back-end сервера
                • 0

                  Справедливости ради, я исхожу из своего опыта работы с parse и на проектах где все вроде бы идет хорошо но вот приходит момент и расширение функционала с parse уже дороже.


                  Причем наличие своего бэкэнда в контексте firebase это как бы… не сильно сложнее чем "облачный" код парса. Просто все crud операции можно делать напрямую через firebase а бизнес логику дополнительную можно реализовывать на своей стороне.


                  Ну а что до парса — есть куча аналогичных решений в плодь до того что вы можете развернуть свой парс.

                  • 0
                    Ну цена parse это отдельная тема для обсуждения.
                    Да, я безусловно согласен, что Firebase открывает кучу возможностей.

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

                    Свой парс не имеет клауд кода, так что это не вариант.

                    А так у нас парс при регистрации сам спокойно дергал апи смс шлюза и юзер получал смс для подтверждения своего номера. Это делалось в 10 строк кода без своего сервака. Жаль, что его закрыли.
      • 0
        Думаю использовать в своей новой Unity игре, благо плагин кажется подвезли.
        • 0
          Очень многое из статьи есть в sample codes.

          Автор, Вы не разбирались как, например, фильтровать данные в запросах по нескольким коллекциям?
          • 0
            Еще я не нашел возможности отправить push по изменению данных в бд. Для того же чата «новое сообщение от ххх».

            Итог, сервис из коробки без back-end не подойдет для многих идей.
            • +1
              Да к сожалению изменение в БД можно хэндлить пока только через дополнительный бэкенд, напрямую не получится. Но это довольно несложно.
            • 0
              А есть ли возможность проверить было ли прочитано уведомление или нет?
              • 0
                Если приложение активно, то получение сообщения можно отследить через метод onMessageReceived… правда если приложение в бэкграунде, то оно отправляется сразу в Notification center, и метод не срабатывает… чтобы сообщение всегда обрабатывалось через onMessageReceived надо отправлять не нотификацию а data месседж, без секции notification. Но через консоль так пока сделать нельзя, и сообщение нужно отправлять через API FCM
                • 0
                  спасибо за ответ! но меня интересует слежка нажатия юзером на уведомление тем, то есть событие при открытии пуша
                  • 0
                    Это тоже настраивается через FCM API. Нужно задать имя экшена в значение ключу click_action в notification payload уведомления, и настроить интент фильтр, чтобы при исполнении этого экшена открывалась определенная активити. Например присвоить click_action значение OPEN_ACTIVITY_1 и в манифесте прописать нужной активити
                    <intent-filter>
                    <action android:name=«OPEN_ACTIVITY_1» />
                    <category android:name=«android.intent.category.DEFAULT» />
                    </intent-filter>
                • 0
                  Начал знакомиться с файрбейзом с аналитики, даже встроил в свое приложение. Самое, чего не хватает — возможности создавать кастомные источники трафика. Не смог найти и, насколько понял, такой возможности нет. Это очень разочаровало, потому что в остальном все очень неплохо. Как, например, наличие событие удаления приложения, которое сам не соберешь, используя другие аналитики.

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

                  Самое читаемое