Содержание статьи
Сказать, что по нашей улице прошел инкассатор, — это ничего не сказать. Займемся изучением инструмента вплотную!
Farewell VK, hello Firebase
В своих предыдущих статьях я рассматривал VK API как бесплатный бэкенд мобильных приложений. У него есть ряд преимуществ. Хостинг безлимитный, типов контента много, управлять им может даже школьник, достаточно объяснить ему структуру наполнения приложения...
Но один недостаток фатален — негибкость сервера. Запись на стене нельзя редактировать через какое-то время, и не получится отправить в приложение сообщение об ее обновлении. Нужно каждый раз выкачивать все объекты со стены и отслеживать все изменения, строго перебирая записи. Серьезные проекты так не работают, и «хватит это терпеть!» ©.
На наше счастье, Google выкупила компанию Firebase и открыла ее для использования всем желающим.
Подробнее, что там есть интересного

В нашем распоряжении имеются:
- Analytics — аналитика по приложению: размер аудитории, информация о пользователях, события в приложении и прочее.
- Authentication — пользователи могут привязать свои учетные записи к приложению, а к ним мы можем привязать любые данные. Из коробки поддерживаются следующие провайдеры авторизации: Google, Facebook, Twitter, GitHub, анонимный вход и имейл-пароль для своей регистрации. Не хватает только VK-авторизации.

- Realtime Database — самая настоящая база данных, работает с живыми изменениями в реальном времени.
- Storage — хранилище для файлов пользователей, можно легко сделать персональное хранилище, а можно и делиться файлами.
- Hosting — тут просто моментальное развертывание веб-приложений и мобильных приложений с помощью безопасной глобальной сети доставки контента.
- Test Lab for Android — тестируй приложения Android на самых разных устройствах.
- App Indexing — свяжи информацию с веб-сайта с внутренними страницами приложения, также есть возможность индексировать данные приложения и отображать их в результатах поиска на устройстве.
- Crash Reporting — сбор информации о сбоях в приложении (на ранних версиях и сам был источником крашей, но вроде починили).
- Notifications — уведомления, замена старым Google Cloud Messaging.
- Remote Config — способ менять поведение приложения прямо со своего сервера, изменяя нужные параметры.
- Dynamic Links — полезный способ прокинуть контекст в приложение (например, пользователь читал про аспирин на твоем сайте, перешел в маркет, установил приложение, и ему открылась страница с аспирином).
- AdMob — рекламный сервис с множеством форматов, по праву занимает лидирующие позиции в мобильной рекламе. У этой сети рекламы всегда много, и она модерируется.
А за что попросят деньги?
Деньги с нас справедливо попросят, если наш бизнес действительно разрастется. Когда он упрется в бесплатные лимиты, платить нам уже будет с чего.
Бесплатно нам доступно:
- Realtime Database:
- 100 единовременных подключений
- 1 Гбайт хранилища
- 10 Гбайт в месяц трафика
- Storage:
- 5 Гбайт хранилища
- 1 Гбайт в день трафика
- 20 000 операций загрузок в день
- 50 000 операций скачивания в день
- Hosting:
- 1 Гбайт хранилища
- 10 Гбайт в месяц трафика
- Custom domain hosting & SSL
- Test Lab:
- запуск не более пятнадцати тестов в день (десять на виртуальных и пять на физических устройствах)
Более подробно читай здесь.

Аутентификация в приложении
Чтобы пользователь мог сохранять настройки приложения на сервере, нужно создать учетную запись. Firebase позволяет это делать при помощи создания собственной учетной записи, как на любом сайте с имейлом-паролем. Также можно привязаться к учетным записям Google, Facebook, Twitter, GitHub. В своих приложениях я использую аккаунты Firebase и Google.

Хороший пример кода для вдохновения ты найдешь здесь. А как сделать свою регистрацию, внятно описано тут.
Для связки Google-аккаунта с приложением я делаю следующее. В методе OnCreate нужной Activity создаю объекты GoogleApiClient, FirebaseAuth и слушателя аутентификации FirebaseAuth.AuthStateListener.
// [START config_signin]
// Configure Google Sign In
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
// [END config_signin]
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [START initialize_auth]
mAuth = FirebaseAuth.getInstance();
// [END initialize_auth]
// [START auth_state_listener]
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// [START_EXCLUDE]
updateUI(user);
// [END_EXCLUDE]
}
};
// [END auth_state_listener]
Чтобы запустить аутентификацию, используем простой метод:
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
Запущенная активити предложит нам выбрать учетную запись Google из хранящихся на устройстве. После выбора нужно обработать результат в методе onActivityResult
:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(account);
} else {
// Google Sign In failed, update UI appropriately
// [START_EXCLUDE]
Toast.makeText(SettingsActivity.this, R.string.auth_failed,
Toast.LENGTH_SHORT).show();
flipCard();
updateUI(null);
// [END_EXCLUDE]
}
}
}
После выполнения функции firebaseAuthWithGoogle сработает наш слушатель аутентификации mAuthListener.
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
// [START_EXCLUDE silent]
showProgressDialog();
// [END_EXCLUDE]
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user.
// If sign in succeeds the auth state listener
// will be notified and logic to handle the signed in
// user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(SettingsActivity.this, R.string.auth_failed,
Toast.LENGTH_SHORT).show();
}
// [START_EXCLUDE]
hideProgressDialog();
flipCard();
// [END_EXCLUDE]
}
});
}
Отключить приложение от учетной записи поможет метод revokeAccess()
: в его колбэке обновляем интерфейс приложения.
private void revokeAccess() {
// Firebase sign out
mAuth.signOut();
if (mGoogleApiClient.isConnected())
// Google revoke access
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(new ResultCallback<Status>(){
@Override
public void onResult(@NonNull Status status) {
updateUI(null);
}
});
}
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»