Cara Menampilkan Gambar dari Firebase Storage pada RecyclerView


Assalamualaikum Warahmatullahi Wabarakatuh.

Untuk menampilkan gambar yang tersimpan pada Storage, kita memerlukan URL download dari file yang telah di upload, untuk itu setelah user menupload gambar pada Storage, kita perlu menyimpan URL dari file tersebut, disini kita akan menyimpan URLnya pada meyimpanan Realtime Database, setelah itu program akan menampilkan semua gambar yang tersimpan pada RecyclerView melalui URL dari gambar yang tersimpan.


Untuk pembuatan program berikut ini, kita memerlukan 2 library tambahan dari Firebase, yaitu : Realtime Database dan FirebaseUI Realtime Database
  • Firebase Realtime Database : Library yang akan digunakan untuk menyimpan URL download dari  file yang telah di upload pada Storage.
  • FirebaseUI Realtime Database : Sebuah library yang memudahkan kita untuk menghubungkan data dari Database pada RecyclerView menggunakan FirebaseRecyclerAdapter.

Selain itu kita juga memerlukan library pendukung lainnya seperti RecyclerView dan Glide untuk mengatur setelan gambar yang akan ditampilkan pada ImageView didalam RecyclerView.

Materi lainnya yang direkomendasikan:

Materi ini adalah kelanjutan dari tutorial Belajar Cara Mengupload File pada Firebase Storage jadi saya sarankan kalian telah mengikuti tutorial yang saya berikan sebelumnya, tapi jika sudah paham, kalian boleh melewati tutorial tersebut.

Cara Menampilkan Gambar dari Firebase Storage pada RecyclerView

1) Pertama kalian tambahkan beberapa library berikut ini kedalam dependencies pada file build.gradle (app module).
implementation 'com.android.support:design:27.1.1'
implementation 'com.google.firebase:firebase-database:16.0.1'
implementation 'com.firebaseui:firebase-ui-database:3.2.2'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
2) Disini kita menggunakan Firebase Realtime Database, secara default aturan keamanan dari Realtime Database tersebut diharuskan user untuk terautentikasi agar dapat membaca atau menulis data, seperti berikut ini.


Karena aplikasi yang akan kita buat tidak akan menggunakan fitur autentikasi didalamnya, untuk itu kita perlu merubahnya ke aturan public seperti ini.
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
3) Berikutnya buat layout item untuk RecyclerView, karena hanya gambar saja yang akan ditampilkan, jadi kita hanya perlu menambahkan ImageView kedalamnya. Klik kanan pada direktori layout, buat layout baru, berinama misalnya "recycler_layout".
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="wrap_content"
    android:layout_margin="8dp">

    <ImageView
        android:id="@+id/gambar"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        tools:ignore="ContentDescription" />
    
</RelativeLayout>
4) Buat kelas modelnya, class ini digunakan untuk menentukan jenis data dan data apa saja yang akan dimasukan, buat class baru, berinama "DataModels".
package cianjur.developer.net.firebaseexample;

public class DataModels {

    private String image_url;

    //Konstruktor kosong, untuk data snapshot pada Firebase Realtime Database
    public DataModels() {}

    public DataModels(String image_url) {
        this.image_url = image_url;
    }

    public String getImage_url() {
        return image_url;
    }
}
Pada class tersebut kita membuat sebuah variable untuk menetukan nama dan jenis data yang akan dimasukan pada Database, lalu konstuktor kosong untuk data snapshot pada Database dan terakhir yaitu metod getter untuk mendapatkan value dari variable image_url.

5) Buat Activity baru, berimana misalnya "ImageStorage", activity ini akan gunakan untuk menampilkan semua gambar yang tersimpan pada Storage, disini kita cukup menambahkan RecyclerView dan ProgressBar.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="cianjur.developer.net.firebaseexample.ImageStorage">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_margin="8dp" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>
6) Buka kembali pada activity_main.xml yang sudah kalian buat pada tutorial sebelumnya, disini kita cukup manambahkan sebuah Button untuk berpindah activity.


7) Pada MainActivity.java, kita akan mengambil download URL dari child yang telah ditentukan pada uploadTask,  didalam method addOnSuccessListener(), kita tambahkan referensi Database untuk menentukan lokasi penyimpanan URL file  lalu menyimpannya.
DatabaseReference databaseReference;
private Button ShowImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Upload = findViewById(R.id.upload);
        Upload.setOnClickListener(this);
        UnggahGambar = findViewById(R.id.select_Image);
        UnggahGambar.setOnClickListener(this);
        ImageContainer = findViewById(R.id.imageContainer);
        progressBar = findViewById(R.id.progressBar);
        ShowImage = findViewById(R.id.image_storage);

        //Mendapatkan Referensi dari Firebase Storage
        reference = FirebaseStorage.getInstance().getReference();

        //Mendapatkan Referensi dari Firebase Realtime Database
        databaseReference = FirebaseDatabase.getInstance().getReference();

        ShowImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, ImageStorage.class));
            }
        });
    }

    //Method ini digunakan untuk mengupload gambar pada Storage
    private void uploadImage(){
        //Mendapatkan data dari ImageView sebagai Bytes
        ImageContainer.setDrawingCacheEnabled(true);
        ImageContainer.buildDrawingCache();
        Bitmap bitmap = ((BitmapDrawable) ImageContainer.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

        //Mengkompress bitmap menjadi JPG dengan kualitas gambar 100%
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
        byte[] bytes = stream.toByteArray();

        String namaFile = UUID.randomUUID()+".jpg"; //Nama Gambar (Secara Random)
        final String pathImage = "gambar/"+namaFile; //Lokasi lengkap dimana gambar akan disimpan

        UploadTask uploadTask = reference.child(pathImage).putBytes(bytes);
        uploadTask.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                
                if(task.isSuccessful()){
                   //Mendapatkan URL download dari gambar yang telah disimpan pada Storage
                    reference.child(pathImage).getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(Uri uri) {

                            //Menyimpan URL pada Variable String
                            String downloadURL = uri.toString();

                            //Menentukan referensi lokasi data url yang akan disimpan
                            databaseReference.child("gambar").push().setValue(new DataModels(downloadURL));

                            progressBar.setVisibility(View.GONE);
                            Toast.makeText(MainActivity.this, "Uploading Berhasil", Toast.LENGTH_SHORT).show();
                            ImageContainer.setVisibility(View.GONE);
                        }
                    });
                }else{
                    progressBar.setVisibility(View.GONE);
                    Toast.makeText(MainActivity.this, "Uploading Gagal", Toast.LENGTH_SHORT).show();
                }
            }
        }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                //Method ini digunakan untuk menghitung persentase proses uploading file
                progressBar.setVisibility(View.VISIBLE);
                double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                progressBar.setProgress((int) progress);
            }
        });
    }
8) Setelah itu kita buat class ViewHoler, class ini digunakan untuk menentukan View-view yang akan digunakan pada RecyclerView, sebelumnya view tersebut sudah kita buat pada layout bernama "recycler_layout.xml".
package cianjur.developer.net.firebaseexample;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

public class RecyclerAdapter extends RecyclerView.ViewHolder{

    public RecyclerAdapter(View itemView) {
        super(itemView);
    }

    void setDisplayImage(String imageUrl, Context context) {

        ImageView image = itemView.findViewById(R.id.gambar);

        Glide.with(context)
                .load(imageUrl)
                .into(image);
    }
}
Pada class tersebut, kita membuat sebuah method dengan parameter berupa variable yang akan mengisi data/value pada ImageView tersebut, menggunakan library Glide.

9) Selanjutnya buka class ImageStorage,java untuk persiapan, masukan source code seperti berikut ini.
//========= WILDAN TECHNO ART =========//
/*
 * Belajar menggunakan Firebase Storage
 * Bersama Wildan M Athoillah
 */
//======= CIANJUR APPS DEVELOPER ======//

package cianjur.developer.net.firebaseexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class ImageStorage extends AppCompatActivity {

    //Deklarasi Variable
    private DatabaseReference reference;
    private RecyclerView recyclerView;
    private FirebaseRecyclerAdapter<DataModels, RecyclerAdapter> recyclerAdapter;
    private FirebaseRecyclerOptions<DataModels> options;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_storage);
        getSupportActionBar().setTitle("Image Storage");
        recyclerView = findViewById(R.id.recyclerView);
        progressBar = findViewById(R.id.progressBar);

        //Digunakan untuk mengatur dan memposisikan item didalam RecyclerView
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        //Digunakan agar ukuran RecyclerView tidak berubah saat menambahkan item atau menghapusnya
        recyclerView.setHasFixedSize(true);

        //Mendapatkan referensi dari Database
        reference = FirebaseDatabase.getInstance().getReference();

        firebaseReyclerViewAdapter();
    }
Pada FirebaseRecyclerAdapter diperlukan 2 buah parameter yaitu data model yang akan digunakan dan view holder.

10) Selanjutnya pada method firebaseRecyclerViewAdapter(), masukan source code berikut ini beserta penjelasannya.
//========= WILDAN TECHNO ART =========//
/*
 * Belajar menggunakan Firebase Storage
 * Bersama Wildan M Athoillah
 */
//======= CIANJUR APPS DEVELOPER ======//

package cianjur.developer.net.firebaseexample;

import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class ImageStorage extends AppCompatActivity {

    //Deklarasi Variable
    private DatabaseReference reference;
    private RecyclerView recyclerView;
    private FirebaseRecyclerAdapter<DataModels, RecyclerAdapter> recyclerAdapter;
    private FirebaseRecyclerOptions<DataModels> options;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_storage);
        getSupportActionBar().setTitle("Image Storage");
        recyclerView = findViewById(R.id.recyclerView);
        progressBar = findViewById(R.id.progressBar);

        //Digunakan untuk mengatur dan memposisikan item didalam RecyclerView
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        //Digunakan agar ukuran RecyclerView tidak berubah saat menambahkan item atau menghapusnya
        recyclerView.setHasFixedSize(true);

        //Mendapatkan referensi dari Database
        reference = FirebaseDatabase.getInstance().getReference();

        firebaseReyclerViewAdapter();
    }

    //Method ini digunakan untuk mengubungkan data dari Database pada RecyclerView
    private void firebaseReyclerViewAdapter(){

        // Mengatur setelah opsi untuk FirebaseRecyclerAdapter
        options = new FirebaseRecyclerOptions.Builder<DataModels>()
                // Referensi Database yang akan digunakan beserta data Modelnya
                .setQuery(reference.child("gambar"), DataModels.class)
                .setLifecycleOwner(this) //Untuk menangani perubahan siklus hidup pada Activity/Fragment
                .build();

        // Digunakan untuk menghubungkan View dengan data Models
        recyclerAdapter = new FirebaseRecyclerAdapter<DataModels, RecyclerAdapter>(options) {

            @Override
            protected void onBindViewHolder(@NonNull RecyclerAdapter holder, int position, @NonNull DataModels model) {
                //Mendapatkan data dari Database yang akan ditampilkan pada RecyclerView
                holder.setDisplayImage(model.getImage_url(), ImageStorage.this);
                
                progressBar.setVisibility(View.GONE);
            }

            @NonNull
            @Override
            public RecyclerAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                //Mengubungkan adapter dengan Layout yang akan digunakan
                return new RecyclerAdapter(LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.recycler_layout, parent, false));
            }
        };
        recyclerView.setAdapter(recyclerAdapter);
    }
}
Demo aplikasi :



Gambar yang diupload akan tersimpan pada Storage.


Dan URL download dari file tersebut akan tersimpan pada Database.


Terimakasih atas kunjungannya, semoga tutorial yang saya berikan bisa bermanfaat untuk kalian semua, selebihnya, mohon maaf bila ada kesalahan.

Wassalamualaikum Warahmatullahi Wabarakatuh.

Wildan M Athoillah
Wildan M Athoillah Blogger dan spesialis pembuat aplikasi android.