Using Firebase in place of own hosting, database and what not!

Leave a comment

Firebase benefits
Key/Value document (NoSQL)
Real time database
Hosted
URL based
Integrated Authentication

Firebase NoSQL data design principles:
– Don’t treat firebase like a relational database
– User Root branches as your primary container
– Avoid deep nesting
– Duplicating Data (More art than science)
– Design around data access
– Data design is driver by data access nodes
– Iterative Design

Understand Data
– Arrays
– Null locations
– Reference

The whole project is in this github link

Here’s the breakdown how it works:
First need to add dependencies for an Android project in build.gradle file:

    compile 'com.google.firebase:firebase-core:16.0.1'
    compile 'com.google.firebase:firebase-database:16.0.6'
    compile 'com.google.firebase:firebase-auth:16.1.0'
    compile 'com.firebaseui:firebase-ui-auth:4.3.0'

Declare Firebase variables

    private FirebaseDatabase mFirebaseDatabase;
    private DatabaseReference mMessagesDatabaseReference;
    private ChildEventListener mChildEventListener;

    private FirebaseAuth mFirebaseAuth;
    private FirebaseAuth.AuthStateListener mFirebaseAuthStateListener;

Initialize declared variables in onCreate()

        mFirebaseDatabase = FirebaseDatabase.getInstance();
        mFirebaseAuth = FirebaseAuth.getInstance();
        mMessagesDatabaseReference = mFirebaseDatabase.getReference().child("messages");

Send button will do the mapping of a POJO object with the database and push it there:

        // Send button sends a message and clears the EditText
        mSendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // TODO: Send messages on click

                FriendlyMessage friendlyMessage = new FriendlyMessage(mMessageEditText.getText().toString(), mUsername, null);
                mMessagesDatabaseReference.push().setValue(friendlyMessage);

                // Clear input box
                mMessageEditText.setText("");
            }
        });

We then create the database event change listener method in MainActivity,

private void attachDabaseReadListener() {

        if(mChildEventListener == null) {
            mChildEventListener = new ChildEventListener() {
                @Override
                public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                    FriendlyMessage friendlyMessage = dataSnapshot.getValue(FriendlyMessage.class);
                    mMessageAdapter.add(friendlyMessage);
                }

                @Override
                public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

                }

                @Override
                public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            };

            mMessagesDatabaseReference.addChildEventListener(mChildEventListener);
        }
    }

The flow goes like this from here:
onResume() : AddAuthStateChangeListener()
-> OnAuthStateChange() : if there’s user it will call attachDabaseReadListener()
otherwise, it will start the Firebase Auth SignIn procedure

Similarly in onPause() we will need to remove the Firebase Auth and Database listeners, as we no longer intend to listen to these when activity is not visible.

This is how authentication listeners works:

mFirebaseAuthStateListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();

                if(user != null){
                    Toast.makeText(MainActivity.this, "You have succesfully signed in!", Toast.LENGTH_SHORT).show();
                    onSignedInInitilize(user.getDisplayName());
                }else {
                    
                    onSignedOutCleanup();
                    
                    // Choose authentication providers
                    List<AuthUI.IdpConfig> providers = Arrays.asList(
                            new AuthUI.IdpConfig.EmailBuilder().build(),
                            new AuthUI.IdpConfig.GoogleBuilder().build());

                    // Create and launch sign-in intent
                    startActivityForResult(
                            AuthUI.getInstance()
                                    .createSignInIntentBuilder()
                                    .setIsSmartLockEnabled(false) //to remember credentials
                                    .setAvailableProviders(providers)
                                    .build(),
                            RC_SIGN_IN);


                }
            }
        };

However, it returns from the auth activity after sign in or sign out, we check in this method:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == RC_SIGN_IN){
            Toast.makeText(this, "Signed In!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "Signed Out!", Toast.LENGTH_SHORT).show();
            finish();
        }
    }

Leave a Reply