Inject Firebase into your Android project

This article will explain how to integrate Firebase using Dagger for easy access include fallback if you don’t have Play services in your device. All examples related to my open source project “Nasa planetary” you can find the project code at Github.

Nasa planetary

Firebase is a great platform for supporting your client, you can read more about in my pervious post, and the integration is very simple into the project. I always love to talk about scale and abstraction, one of tools that you can use to achieve this is Dagger (you can read more on the official website) it make the life more simple, It is dependency injection library that come to solve the problem like what I will described next, Imagine a situation that you want to support your application on all kind of devices and you don’t want to depend only on Google play supported devices (Firebase officially not supported on thous devices). Dagger can easily solve this problem by returning different implementation of interface when it injected to your class, I will explain further how it works.

Integration of Dagger and Firebase you can do in couple of simple steps, first step is to integrate the libraries in your Gradle configuration. Let start from the main Gradle file.

dependencies {
...
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
classpath 'com.google.gms:google-services:3.0.0'
}

Next step is adding dependency in your application Gradle file.

apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'com.google.gms.google-services'
...
dependencies {
...
compile "com.google.dagger:dagger:2.5"
apt "com.google.dagger:dagger-compiler:2.5"
compile "com.google.firebase:firebase-core:9.0.2"
...
}

After successful Gradle configuration we need to configure Dagger to support different modules injection, we will add the logic for switch on and off inside the module. Before we creating a module we need to define Interface that will be the “contract” of the component functionality, in my project I want to store images comments and retrieve comments for them, we will need two methods for this.

public interface IComments {
Observable getComments(String photoId);

Observable sendComment(String photoId, String message);
}

In my example I am using RxJava Observable abilities but you can easily convert it to interfaces callbacks (Listeners).

Next step is to create the repository that will wrap the Firebase DatabaseReference by implementing the interface that we had defined earlier.

public class CommentsRepository implements IComments {
private DatabaseReference databaseReference;
    public CommentsRepository(DatabaseReference databaseReference) {
this.databaseReference = databaseReference;
}
    @Override public Observable getComments(...) {
Query query = databaseReference.child(...
return observe(query);
}
    @Override public Observable sendComment(...) {
databaseReference.child(...
.push()
}
...
}

Now we will use Dagger to define module that will create reference to the repository, remember that we want to support devices that don’t have Google play services support. We will add the check inside the module and if device don’t have google support we will return an error that Firebase not supported, you can change it by implementing another repository that use different data provider (or your own server api) and youse it us fallback instead.

@Module
public class DataModule {
...
@Provides IComments provideComments(...) {
int playServicesStatus =
GoogleApiAvailability
.getInstance()
.isGooglePlayServicesAvailable(context);
         if (playServicesStatus == ConnectionResult.SUCCESS) {
DatabaseReference databaseReference =
FirebaseDatabase
.getInstance()
.getReference();
            return new CommentsRepository(databaseReference);
}else{
return new IComments() {
@Override public Observable getComments(...) {
return Observable.error(
new RuntimeException(
"FireBase not supported"));
}
                @Override public Observable sendComment(...) {
return Observable.error(
new RuntimeException(
"FireBase not supported"));
}
};
}
}
...
}

Final step that we need to do is to finalize configuring Dagger and inject the IComments interface wherever you want to access you data. You will need to create Application Component that include all your modules, we will need to connect our DataModule to be part of it.

@Singleton
@Component(
modules = {
...
DataModule.class,
...
}
)
public interface ApplicationComponent {
...
void inject(MainActivity mainActivity);
...
}

Initiate Dagger in your Main Application class and you ready to go.

public class MainApplication extends Application {
    private ApplicationComponent component;
    @Override public void onCreate() {
super.onCreate();
inject();
}
    private void inject(){
component = DaggerApplicationComponent
.builder()
...
.dataModule(new DataModule(this))
...
.build();

component.inject(this);
}
    public ApplicationComponent getApplicationComponent(){
return component;
}
...
}

Now you are ready to use your component anywhere in your project simply inject the interface and dagger will do the magic for you. You need to define your class that you want to use injection in ApplicationComponent interface and you ready to go.

public class MainActivity extends Activity {
@Inject IComments comments;

...
    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MainApplication) getApplication())
.getApplicationComponent()
.inject(this);
...
        comments.getComments(...);
}
...
}

This approach is good for every type of fallback, you can implement same solution for FirebaseAnalytics and other providers. The good thing about this solution is that we can easily change dependency without rewriting all your code.

Don’t forget to download the Nasa planetary application (Will glad to get your rate) and check the source code in Github.