How to connect Android with Firebase Cloud Functions

In this tutorial we are going to see how we can enable Firebase Cloud functions. Firebase Cloud Functions let us run custom logic code in Google supported backend. Firebase functions can also be configured to run on selected triggers like Firebase Database, Analytics.

We can extend Firebase cloud functions to create backend and expose REST apis. In this example we will see how to create and setup firebase functions and call these functions from our Android application.

Setup Firebase Cloud Functions

firebase login

// or if another account needs to be logged in then 

firebase login --reauth

? Allow Firebase to collect anonymous CLI usage and error reporting information? No

Visit this URL on any device to log in:
https://accounts.google.com/o/oauth2/auth?client_id=…….
Waiting for authentication…

✔ Success! Logged in as …..

Install npm Firebase Tools. Open terminal and run following commands.

npm install -g firebase-tools

firebase init

In your favorite IDE open project.  If you ask me I prefer to work on visual studio code. Open index.js file and initialize firebase app.

const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp();

Let’s create our first cloud function. There are two ways to call Firebase cloud functions. First one let you call cloud functions directly from the app. Second way is to call functions by http requests. The format for both of these methods are different.

Cloud Function call via HTTP Requests

exports.helloWorld = functions.https.onRequest((request, response) => {
    response.send("Hello from Firebase!");
});

Note: The cloud functions are end by calling send()redirect(), or end()functions.

Cloud Function call directly from App

exports.helloWorldCloudFunction = functions.https.onCall((data, context) => {
    return "Hello from firebase onCall";
});

Deploy Firebase Functions

firebase deploy --only functions

Android Firebase Cloud Functions Setup

Callable Firebase Cloud Functions

Open Android Studio and create new Android project. Add firebase functions dependency in build.gradle

    implementation 'com.google.firebase:firebase-functions:16.1.3'

Call cloud function directly by callable firebase function in the code.

   
    private Task<String> callCloudFunction() {
        FirebaseFunctions mFunctions = FirebaseFunctions.getInstance();
        Map<String, Object> data = new HashMap<>();
        data.put("data", true); // pass any data in map

        return mFunctions
                .getHttpsCallable("helloWorldCloudFunction")
                .call(data)
                .continueWith(new Continuation<HttpsCallableResult, String>() {
                    @Override
                    public String then(@NonNull Task<HttpsCallableResult> task) {
                        // This continuation runs on either success or failure, but if the task
                        // has failed then getResult() will throw an Exception which will be
                        // propagated down.
                        return (String) task.getResult().getData();
                    }
                });

    }

Firebase Functions via HTTP request

We will be using volley library to create http requests. Add volley dependency in build.gradle file

    implementation 'com.android.volley:volley:1.1.0'

Call cloud function via http request

   private void callHttpCloudFunction() {
        mRequestQueue = Volley.newRequestQueue(this);
        StringRequest mCloudRequest = new StringRequest(Request.Method.GET, CLOUD_URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.e("TAG", "Response received:"+ response);
                mTextView.setText(String.format(Locale.getDefault(),"%s", response));
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("TAG", "Call failed:"+ error.getMessage());
                mTextView.setText(String.format(Locale.getDefault(),"%s", error.getMessage()));
            }
        });
        mRequestQueue.add(mCloudRequest);
    }

Full Source Code:

Activity Code

public class CloudActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String CLOUD_URL = "https://us-central1-fir-databaseexample-3fe36.cloudfunctions.net/helloWorld";
    private TextView mTextView;
    private RequestQueue mRequestQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cloud);
        mTextView = findViewById(R.id.cloudResponseTextView);
        findViewById(R.id.button).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.button){
            Task<String> taskData = callCloudFunction();
            taskData.addOnCompleteListener(task -> {
                mTextView.setText(String.format(Locale.getDefault(),"%s", taskData.getResult()));
            });
        }else if(v.getId() == R.id.button2){
            callHttpCloudFunction();
        }
    }


    private Task<String> callCloudFunction() {
        FirebaseFunctions mFunctions = FirebaseFunctions.getInstance();
        Map<String, Object> data = new HashMap<>();
        data.put("push", true);

        return mFunctions
                .getHttpsCallable("helloWorldCloudFunction")
                .call(data)
                .continueWith(new Continuation<HttpsCallableResult, String>() {
                    @Override
                    public String then(@NonNull Task<HttpsCallableResult> task) {
                        // This continuation runs on either success or failure, but if the task
                        // has failed then getResult() will throw an Exception which will be
                        // propagated down.
                        return (String) task.getResult().getData();
                    }
                });

    }

    private void callHttpCloudFunction() {
        mRequestQueue = Volley.newRequestQueue(this);

        //String Request initialized
        StringRequest mCloudRequest = new StringRequest(Request.Method.GET, CLOUD_URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.e("TAG", "Response received:"+ response);
                mTextView.setText(String.format(Locale.getDefault(),"%s", response));

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("TAG", "Call failed:"+ error.getMessage());
                mTextView.setText(String.format(Locale.getDefault(),"%s", error.getMessage()));

            }
        });

        mRequestQueue.add(mCloudRequest);
    }

}

activity_cloud.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".cloud.CloudActivity">


    <TextView
        android:id="@+id/cloudResponseTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="TextView"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        style="@style/Widget.AppCompat.Button.Colored"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="Call Cloud Function"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button2"
        style="@style/Widget.AppCompat.Button.Colored"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="Call Cloud HTTP"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>

 

One Response

  1. Mike Bleahen July 22, 2019

Leave a Reply