Firebase UI isn’t the most prominent thing about Firebase. Needless to say, it’s really undervalued. It makes use of pre-made design flows by Google so that we developers don’t have to reinvent the wheel for what we don’t need to. It makes developing apps ridiculously easy and quick.
First, let’s get some confusion out of the way. FirebaseUI doesn’t actually add any UI components except for AuthUI. Rather, it’s a quick-to-implement cookie-cutter way to connect Firebase services and their data to your existing UI components. (As well put by Reddit user Najubhai)
This tutorial will be very simple introductions to the 4 modules of Firebase UI:
Each one has a different use. StorageUI makes loading images from Storage into ImageViews cake-easy. AuthUI gives you an intent to run a pre-provided authentication flow. FirestoreUI and DatabaseUI make the connection between lists of documents/nodes to RecyclerView much easier to implement.
Of course, once you’re done implementing the basics and want to find out more, you can visit the main documentation for it to find out more. Many of the examples here were taken from that documentation too.
If you’ve read and already fully understand FirebaseUI from those docs, then you’ll find nothing new here. This is just a simplified introduction to FirebaseUI’s 4 components.
One thing to note: you need to configure Firebase with your app. If you haven’t done that yet, read the thing.
FirebaseUI Storage
FirebaseUI Storage makes use of the well-known Glide library to make downloading images as easy as possible by handling all the intermediary stuff like decoding, placeholder images, listView recycling, and all that. In short, “get me this image and stick it into this imageView”.
1. Import the Dependency
implementation 'com.firebaseui:firebase-ui-storage:3.3.1' // Find the latest Glide releases here: https://goo.gl/LpksbR implementation 'com.github.bumptech.glide:glide:4.x' annotationProcessor 'com.github.bumptech.glide:compiler:4.x'
Import the main FirebaseUI Storage dependency, and if you’re not already using Glide, import that too.
2. Register an AppGlideModule
@GlideModule public class MyAppGlideModule extends AppGlideModule { @Override public void registerComponents(Context context, Glide glide, Registry registry) { // Register FirebaseImageLoader to handle StorageReference registry.append(StorageReference.class, InputStream.class, new FirebaseImageLoader.Factory()); } }
Anywhere you decide to put this class, as long as it’s within your app’s source directory, Gradle will find it. Gradle will process it, so that Gradle can GlideApp class. Good boy Gradle.
3. Download and Apply the Image
GlideApp.with(context) .load(storageReference) .centerCrop() .placeholder(R.drawable.loading_spinner) .into(myImageView);
Dead simple. I have no words for this. This just completely astonishes me.
FirebaseUI Auth

FirebaseUI Auth allows you to build a SignInIntent where you pass in your authentication providers and Firebase runs a whole authentication flow of its own login/sign up activities. You’ll receive a callback once the user goes back to your app so you can set the UID and make the necessary changes.
1. Import the Dependencies
dependencies { // ... implementation 'com.firebaseui:firebase-ui-auth:3.3.1' // Required only if Facebook login support is required // Find the latest Facebook SDK releases here: https://goo.gl/Ce5L94 implementation 'com.facebook.android:facebook-login:4.x' // Required only if Twitter login support is required // Find the latest Twitter SDK releases here: https://goo.gl/E5wZvQ implementation("com.twitter.sdk.android:twitter-core:3.x@aar") { transitive = true } }
Add these dependencies in your app/build.gradle file depending on what authentication providers you’ll be using. The first dependency can handle most providers you’ll see in the Firebase Console, but if you need Facebook or Twitter, those other two dependencies are there.
android { // ... defaultConfig { // ... resConfigs "en" // And any other languages you support } }
Firebase UI also provides translations for the string resources in the authentication flow. To allow that to happen, add this line in your module-level build.gradle file and add any other languages you’re supporting.
1.5. Extra Facebook and Twitter Setup
<resources> <!-- ... --> <string name="facebook_application_id" translatable="false">APP_ID</string> <!-- Facebook Application ID, prefixed by 'fb'. Enables Chrome Custom tabs. --> <string name="facebook_login_protocol_scheme" translatable="false">fbAPP_ID</string> </resources>
If you’re including Facebook as a provider, you’ll need to add this in your strings.xml file. You can get your APP_ID in the Facebook Developer Dashboard (you will need to set up an app there as well). The other string is the same APP_ID but it’s prefixed with “fb”.
<resources> <string name="twitter_consumer_key" translatable="false">YOURCONSUMERKEY</string> <string name="twitter_consumer_secret" translatable="false">YOURCONSUMERSECRET</string> </resources>
If you’re including Twitter as a provider, you’ll need to add this in your strings.xml file. You can get your Consumer Key and Secret from the Twitter Application Manager (you’ll need to set up an app there as well).
2. Enable Providers in the Firebase Console
In the Firebase Console, go to Authentication > Sign-in Method and enable all your desired providers
3. Launch the Sign-in Intent
private static final int RC_SIGN_IN = 123; List<AuthUI.IdpConfig> providers = Arrays.asList( new AuthUI.IdpConfig.EmailBuilder().build(), new AuthUI.IdpConfig.PhoneBuilder().build(), new AuthUI.IdpConfig.GoogleBuilder().build(), new AuthUI.IdpConfig.FacebookBuilder().build(), new AuthUI.IdpConfig.TwitterBuilder().build())); // ... String uid = FirebaseAuth.getInstance().getUid(); if (uid == null) startActivityForResult( AuthUI.getInstance() .createSignInIntentBuilder() .setAvailableProviders(providers) .build(), RC_SIGN_IN);
First check if the user is already logged in. You don’t want to launch the sign-in intent when the user is already logged in. If not authenticated, create a request code and a list of the providers you enabled in the console.
Where you want to launch the intent, call startActivityForResult, get an instance of AuthUI and call createSignInIntentBuilder. Pass in your list of providers, build the intent, pass the request code, and that’s the intent launched right there.
4. Respond to the Callback
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Respond to Authentication Callback if (requestCode == RC_SIGN_IN && resultCode == RESULT_OK) { uid = FirebaseAuth.getInstance().getUid(); doOtherStuff(); } }
After the sign-in flow, you’ll receive a callback to let you know that the user has signed in. Use this to set the UID again and make the appropriate changes in your app.
FirebaseUI Firestore
FirebaseUI Firestore (or FirestoreUI as I like calling it) makes use of a JavaBean-style data model to make applying data to RecyclerViews easier. If you’re using a ListView with say, android.R.layout.simple_list_item_1, you don’t need this at all.
1. Import the Dependency
implementation 'com.firebaseui:firebase-ui-firestore:3.3.1'
No extra schmuck here. Just import this one dependency in your app/build.gradle file.
2. Create your Data Model Class
public class Person { private String mName; private String mDescription; public Person() { } public Person(String name, String description) { mName = name; mDescription = description; } public String getName() { return mName; } public void setName(String name) { mName = name; } public String getDescription() { return mDescription; } public void setDescription(String description) { mDescription = description; } }
FirestoreUI makes use of a data model that follows the JavaBean naming pattern which allows Firestore to automatically map values when getting and setting data. The rules that the pattern follows are as follows:
- Getter and Setter methods are defined which are strictly named to what variable they correspond to (for example: getName() provides the name field).
- An extra empty constructor is also defined which lets Firestore do some fancy shinenigans with the automatic data mapping.
3. Create your Query and FirestoreRecyclerOptions
Query query = FirebaseFirestore.getInstance() .collection("demos") .document("firebaseui") .collection("people") .orderBy("name"); FirestoreRecyclerOptions<Person> options = new FirestoreRecyclerOptions.Builder<Person>() .setQuery(query, Person.class) .build();
This time when querying, instead of adding an OnSnapshotListener like you normally would, you pass your query to a FirestoreRecyclerOptions object along with your data model class.
4. Create the RecyclerViewAdapter
FirestoreRecyclerAdapter adapter; adapter = new FirestoreRecyclerAdapter<Person, PersonHolder>(options) { @NonNull @Override public PersonHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_item_name_and_description, parent, false); return new PersonHolder(view); } @Override protected void onBindViewHolder(@NonNull PersonHolder holder, int position, @NonNull Person model) { holder.nameView.setText(model.getName()); holder.descriptionView.setText(model.getDescription()); } }; listFirestore.setAdapter(adapter); listFirestore.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
Note that this example uses a ViewHolder class called ChatHolder. You’ll have to create your own ViewHolder class (nothing out of the ordinary).
Create the adapter passing in the options, then in onBindViewHolder, you’ll have access to your model object which contains all your data, and you ViewHolder that contains the views in your list item (or whatever it is, grid item or something).
Finally, set the adapter to your RecyclerView, and don’t forget your LayoutManager!
5. Start and Stop Listening
@Override protected void onStart() { super.onStart(); adapter.startListening(); }
Start listening in onStart, and stop listening in OnStop. Make sure you’re properly authenticated to receive the data first before you start listening.
FirebaseUI Database
Almost exactly like Firestore (even in steps and syntax). This makes use of a JavaBeans-style data model to automatically get and set data, and apply it to your RecyclerView’s items. If you’re using a simple list item that’s got only one view where data is set, you really don’t need this.
1. Import the Dependency
implementation 'com.firebaseui:firebase-ui-database:3.3.1'
Simple and easy.
2-5. Just as FirestoreUI but with a couple changes
So you make your JavaBeans-style data model for the node (instead of the document) containing the data objects per list item, create a FirebaseRecyclerOptions (instead of FirestoreRecyclerOptions), create a FirebaseRecyclerAdapter (instead of FirestoreRecyclerAdapter), you apply the data to your list items in onBindViewHolder, set your adapter, and add your listeners.
In short, follow the steps for FirestoreUI and replace every document and collection with nodes, and “Firestore” with “Firebase”. That’s it. That’s literally it.
Get the Demo App
What better reference would there be when you’re having trouble than a demo app that displays each one in seperate activities and simply as they could be? I care about you guys so I spend the extra effort to make several more cups of coffee to bring you this demo app. I hope you like it.
https://github.com/ericdecanini/FirebaseUIDemo
Conclusion
It’s a real kick in the gut after you’ve been doing things the normal way for so long then you come across these simplified ways of doing things and realise you could’ve saved so much time. Well you had to learn about this at some point. AuthUI and StorageUI are my personal favourites.
I absolutely love ya’ll on Reddit. You guys push me far enough to make a good topic even greater. Thank you sincerely.
So what are your favourites? Let me know in the comments! Honestly, Reddit is fine but these comments feel lonely.