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>
This article was a great help, thanks – it’s very concise and it works, well done.
The private Task callCloudFunction() { } method doesn’t work with Android Java.