Firebase is a mobile and web application development platform. It provides services that a web application or mobile application might require. Firebase provides secure file uploads and downloads for Firebase application. This article explains how to build an Android application with the ability to select the image from the mobile gallery and upload images to Firebase Storage.
Note: Firebase Storage now requires a billing plane to use Firebase Storage.
Step by Step Implementation
Step 1: Create a new project
Create a new project on android studio or open an existing project in which you want and add the firebase to that android application.
Step 2: Add the firebase storage dependency
Navigate to Gradle Scripts > build.gradle.kts (Module:app) and add the following dependencies
dependencies {
...
implementation("com.google.firebase:firebase-storage-ktx:21.0.1")
}
Step 3. Setting up the activity_main.xml layout file
Navigate to app > res > layout > activity_main.xml and add the following code
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
android:background="@color/white">
<!--Image View for showing image chosen from gallery-->
<ImageView
android:id="@+id/imgView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="32dp"
app:layout_constraintBottom_toTopOf="@+id/btnChoose"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--Button for choosing image from gallery-->
<Button
android:id="@+id/btnChoose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="Choose"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnUpload"
app:layout_constraintStart_toStartOf="parent" />
<!--Button for uploading image-->
<Button
android:id="@+id/btnUpload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload"
app:layout_constraintBottom_toBottomOf="@+id/btnChoose"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btnChoose"
app:layout_constraintTop_toTopOf="@+id/btnChoose" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4: Working with MainActivity file
Navigate to app > java > {package-name} > MainActivity.kt/.java and add the following code.
Set OnClickListeners on the buttons to handle user interaction. When the Select button is clicked, a image selection bottom sheet is displayed using ActivityResultLauncher with ActivityResultContracts.GetContent. This launches a system image picker letting the user to choose an image from their device's gallery. Once the image is selected, its URI is returned, which is then displayed in the ImageView below the buttons.
When the Upload button is clicked, the uploadImage() method is called. Inside this method, a Firebase Storage reference is initialized and a unique file path is created using a UUID. If an image is selected, it is uploaded to Firebase using the putFile() function. A progress dialog shows the upload progress.
package org.geeksforgeeks.demo;
import android.app.ProgressDialog;
import android.graphics.*;
import android.net.Uri;
import android.os.Bundle;
import android.widget.*;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.ktx.Firebase;
import com.google.firebase.storage.*;
import java.io.InputStream;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
// Declare UI components
private Button btnSelect;
private Button btnUpload;
private ImageView imageView;
// Store the URI of the selected image
private Uri filePath;
// Firebase Storage instance
private FirebaseStorage storage;
// Reference to the Firebase Storage root directory
private StorageReference storageReference;
// Launcher to handle image picking from gallery
private ActivityResultLauncher<String> imagePickerLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind UI elements to layout views
btnSelect = findViewById(R.id.btnChoose);
btnUpload = findViewById(R.id.btnUpload);
imageView = findViewById(R.id.imgView);
// Initialize Firebase Storage
storage = StorageKt.getStorage(Firebase.INSTANCE);
storageReference = storage.getReference();
// Initialize image picker with activity result contract
imagePickerLauncher = registerForActivityResult(
new ActivityResultContracts.GetContent(),
uri -> {
// Handle the result from the image picker
if (uri != null) {
filePath = uri;
try {
// Open input stream from the selected image URI
InputStream inputStream = getContentResolver().openInputStream(uri);
// Decode input stream into a Bitmap and display in ImageView
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(bitmap);
} catch (Exception e) {
// Handle any exceptions during image decoding
e.printStackTrace();
Toast.makeText(MainActivity.this, "Failed to load image", Toast.LENGTH_SHORT).show();
}
}
});
// Set click listener to launch image picker
btnSelect.setOnClickListener(v -> imagePickerLauncher.launch("image/*"));
// Set click listener to upload the selected image
btnUpload.setOnClickListener(v -> uploadImage());
}
// Function to upload selected image to Firebase Storage
private void uploadImage() {
// Check if an image has been selected
if (filePath != null) {
// Create and show a progress dialog during upload
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Uploading...");
progressDialog.show();
// Create a unique path under 'images/' using UUID
StorageReference ref = storageReference.child("images/" + UUID.randomUUID().toString());
// Upload the file to Firebase Storage
ref.putFile(filePath)
.addOnSuccessListener(taskSnapshot -> {
// Dismiss the dialog and show success message
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Image Uploaded!!", Toast.LENGTH_SHORT).show();
})
.addOnFailureListener(e -> {
// Dismiss the dialog and show failure message
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Upload Failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
})
.addOnProgressListener(taskSnapshot -> {
// Calculate and update progress percentage in the dialog
double progress = (100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount());
progressDialog.setMessage("Uploaded " + (int) progress + "%");
});
} else {
// Show message if no image is selected
Toast.makeText(this, "No image selected!", Toast.LENGTH_SHORT).show();
}
}
}
package org.geeksforgeeks.demo
import android.app.ProgressDialog
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.widget.*
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.ktx.storage
import java.io.InputStream
import java.util.UUID
class MainActivity : AppCompatActivity() {
// Declare UI components
private lateinit var btnSelect: Button
private lateinit var btnUpload: Button
private lateinit var imageView: ImageView
// Store the URI of the selected image
private var filePath: Uri? = null
// Firebase Storage instance
private lateinit var storage: FirebaseStorage
// Reference to the Firebase Storage root directory
private val storageReference by lazy { storage.reference }
// Launcher to handle image picking from gallery
private lateinit var imagePickerLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Bind UI elements to layout views
btnSelect = findViewById(R.id.btnChoose)
btnUpload = findViewById(R.id.btnUpload)
imageView = findViewById(R.id.imgView)
// Initialize Firebase Storage
storage = Firebase.storage
// Initialize image picker with activity result contract
imagePickerLauncher = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? ->
// Handle the result from the image picker
if (uri != null) {
filePath = uri
try {
// Open input stream from the selected image URI
val inputStream: InputStream? = contentResolver.openInputStream(uri)
// Decode input stream into a Bitmap and display in ImageView
val bitmap = BitmapFactory.decodeStream(inputStream)
imageView.setImageBitmap(bitmap)
} catch (e: Exception) {
// Handle any exceptions during image decoding
e.printStackTrace()
Toast.makeText(this, "Failed to load image", Toast.LENGTH_SHORT).show()
}
}
}
// Set click listener to launch image picker
btnSelect.setOnClickListener {
imagePickerLauncher.launch("image/*")
}
// Set click listener to upload the selected image
btnUpload.setOnClickListener {
uploadImage()
}
}
// Function to upload selected image to Firebase Storage
private fun uploadImage() {
// Check if an image has been selected
if (filePath != null) {
// Create and show a progress dialog during upload
val progressDialog = ProgressDialog(this)
progressDialog.setTitle("Uploading...")
progressDialog.show()
// Create a unique path under 'images/' using UUID
val ref = storageReference.child("images/${UUID.randomUUID()}")
// Upload the file to Firebase Storage
ref.putFile(filePath!!)
.addOnSuccessListener {
// Dismiss the dialog and show success message
progressDialog.dismiss()
Toast.makeText(this, "Image Uploaded!!", Toast.LENGTH_SHORT).show()
}
.addOnFailureListener { e ->
// Dismiss the dialog and show failure message
progressDialog.dismiss()
Toast.makeText(this, "Upload Failed: ${e.message}", Toast.LENGTH_SHORT).show()
}
.addOnProgressListener { taskSnapshot ->
// Calculate and update progress percentage in the dialog
val progress = (100.0 * taskSnapshot.bytesTransferred / taskSnapshot.totalByteCount)
progressDialog.setMessage("Uploaded ${progress.toInt()}%")
}
} else {
// Show message if no image is selected
Toast.makeText(this, "No image selected!", Toast.LENGTH_SHORT).show()
}
}
}
Output:
In App:

In Firebase console:
