In a previous tutorial we learnt about Firebase Storage. But I didn’t cover retrieval of the uploaded files from Firebase Storage. So here is another Firebase Storage Example. In this tutorial we will learn Uploading Files to Firebase Storage and Retrieving Uploaded Files from Firebase Storage. So lets start this Firebase Storage Example.
Firebase Storage Upload and Download PDF Files
Table of Contents
- 1 Firebase Storage Example Video Demo
- 2 Firebase Storage Example
- 2.1 Creating a New Project
- 2.2 Setting Up Firebase Storage and Firebase Database
- 2.3 Creating Layout
- 2.4 Defining Firebase Constants
- 2.5 Defining View Objects and Constants
- 2.6 Adding File Chooser
- 2.7 Uploading File to Firebase Storage and Saving URL to Firebase Database
- 2.8 Uploading the File to Firebase Storage
- 2.9 Retrieving Files from Firebase Storage
Firebase Storage Example Video Demo
- You can watch this video to know what we are going to build in this tutorial.
Firebase Storage Example
- As always the first step is creating a new Android Studio Project.
Creating a New Project
- I have just created a project named FirebaseUpload.
- In the project we will be uploading images to Firebase Storage and then we will fetch back the uploaded images to display them into RecyclerView.
- So now we will setup firebase storage to our project.
Setting Up Firebase Storage and Firebase Database
- We will upload the images to Firebase Storage and in the Firebase Database we will store the image URL. For this we need to setup both in our project.
- Go to tools -> firebase
- Now you will see an Assistant Window, you can setup Firebase Database from here.
- The same way you can setup Firebase Storage.
- If you are confused about this step go through the last Firebase Storage Tutorial where I explained it in detail.
Creating Layout
- Now we need to build the following layout for activity_main.xml.
- We have the following components in the above layout.
Choose Button: We will tap this button to choose an image from the gallery.
EditText Enter Name: In this EditText we will put the label for the chosen image.
ImageView: The middle area (you cann’t see it in the layout because it is blank ImageView) contains an ImageView where we will display the chosen image.
Upload Button: Tapping this button will upload the selected image to Firebase Storage.
TextView Uploads: Tapping this TextView will open another activity where we will display the uploaded images with labels. - You can use the following xml code to build the above layout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebaseupload.MainActivity"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/buttonChoose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Choose" /> <EditText android:id="@+id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="4" android:hint="Enter name for Image" /> </LinearLayout> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/linearLayout" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical"> <Button android:id="@+id/buttonUpload" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Upload" /> <TextView android:id="@+id/textViewShow" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="View Uploads" android:textAlignment="center" android:textColor="@color/colorPrimary" android:textStyle="bold" /> </LinearLayout> </RelativeLayout> |
Defining Firebase Constants
- Create a java class named Constants.java and define the following.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package net.simplifiedcoding.firebaseupload; /** * Created by Belal on 2/23/2017. */ public class Constants { public static final String STORAGE_PATH_UPLOADS = "uploads/"; public static final String DATABASE_PATH_UPLOADS = "uploads"; } |
Defining View Objects and Constants
- Come inside MainActivity.java and define the following objects and constants.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ //constant to track image chooser intent private static final int PICK_IMAGE_REQUEST = 234; //view objects private Button buttonChoose; private Button buttonUpload; private EditText editTextName; private TextView textViewShow; private ImageView imageView; //uri to store file private Uri filePath; //firebase objects private StorageReference storageReference; private DatabaseReference mDatabase; |
- Now inside onCreate() we will initialize the the objects and attach click listeners.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); buttonChoose = (Button) findViewById(R.id.buttonChoose); buttonUpload = (Button) findViewById(R.id.buttonUpload); imageView = (ImageView) findViewById(R.id.imageView); editTextName = (EditText) findViewById(R.id.editText); textViewShow = (TextView) findViewById(R.id.textViewShow); storageReference = FirebaseStorage.getInstance().getReference(); mDatabase = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS); buttonChoose.setOnClickListener(this); buttonUpload.setOnClickListener(this); textViewShow.setOnClickListener(this); } |
Adding File Chooser
- Define a new method showFileChooser().
1 2 3 4 5 6 7 8 |
private void showFileChooser() { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST); } |
- Now we need to handle the Intent result. For this we will override the method onActivityResult().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) { filePath = data.getData(); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath); imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } } |
- Now we will call the method showFileChooser() when the choose image button is clicked. For this come inside the overriden method onClick()Â and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public void onClick(View view) { if (view == buttonChoose) { showFileChooser(); } else if (view == buttonUpload) { } else if (view == textViewShow) { } } |
- Now try running the application and you will see that choose image is working fine.
- Now we will code the upload functionality.
Uploading File to Firebase Storage and Saving URL to Firebase Database
Building Database Model
- First we will create a class to store the Image data to Firebase Database. So create a class named Upload.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package net.simplifiedcoding.firebaseupload; import com.google.firebase.database.IgnoreExtraProperties; /** * Created by Belal on 2/23/2017. */ @IgnoreExtraProperties public class Upload{ public String name; public String url; // Default constructor required for calls to // DataSnapshot.getValue(User.class) public Upload() { } public Upload(String name, String url) { this.name = name; this.url= url; } public String getName() { return name; } public String getUrl() { return url; } } |
Getting Selected File Extension
- We will rename the file to a unique name as if we upload the file with same name then files would be overwritten. So after renaming the file the extension should remain the same. So inside MainActivity.java create a method getFileExtension() and it will return as the extension of the selected file by taking Uri object.
1 2 3 4 5 6 7 |
public String getFileExtension(Uri uri) { ContentResolver cR = getContentResolver(); MimeTypeMap mime = MimeTypeMap.getSingleton(); return mime.getExtensionFromMimeType(cR.getType(uri)); } |
Uploading the File to Firebase Storage
- Now we will create a method inside MainActivity.java that will upload the selected file to Firebase Storage. So create a method name uploadFile() and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
private void uploadFile() { //checking if file is available if (filePath != null) { //displaying progress dialog while image is uploading final ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setTitle("Uploading"); progressDialog.show(); //getting the storage reference StorageReference sRef = storageReference.child(Constants.STORAGE_PATH_UPLOADS + System.currentTimeMillis() + "." + getFileExtension(filePath)); //adding the file to reference sRef.putFile(filePath) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { //dismissing the progress dialog progressDialog.dismiss(); //displaying success toast Toast.makeText(getApplicationContext(), "File Uploaded ", Toast.LENGTH_LONG).show(); //creating the upload object to store uploaded image details Upload upload = new Upload(editTextName.getText().toString().trim(), taskSnapshot.getDownloadUrl().toString()); //adding an upload to firebase database String uploadId = mDatabase.push().getKey(); mDatabase.child(uploadId).setValue(upload); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { progressDialog.dismiss(); Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show(); } }) .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { //displaying the upload progress double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); progressDialog.setMessage("Uploaded " + ((int) progress) + "%..."); } }); } else { //display an error if no file is selected } } |
- Now we need to call this method on Upload Button Click. So modify onClick() method as below.
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public void onClick(View view) { if (view == buttonChoose) { showFileChooser(); } else if (view == buttonUpload) { uploadFile(); } else if (view == textViewShow) { } } |
- Now try running your application and upload will work.
Retrieving Files from Firebase Storage
- Now we will create a new activity where we display all the uploaded images with labels.
- So create a new activity named ShowImagesActivity and inside the layout file of this activity we will create a RecyclerView.
Adding RecyclerView and CardView
- First we need to add dependencies for RecyclerView and CardView.
- Go to File -> Project Structure and go to dependencies tab. Here click on plus icon and select Library dependency.
- Now here you need to find and add RecyclerView and CardView.
- Now sync your project.
Adding Glide
- We also need to add Glide Library. As we need to fetch images from the URL and for this I will be using Glide Library.
- So just modify  dependencies block of your app level build.gradle file as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.2.0' compile 'com.google.firebase:firebase-storage:10.2.0' compile 'com.google.firebase:firebase-auth:10.2.0' compile 'com.google.firebase:firebase-database:10.2.0' testCompile 'junit:junit:4.12' compile 'com.android.support:recyclerview-v7:25.2.0' compile 'com.android.support:cardview-v7:25.2.0' //adding glid library compile 'com.github.bumptech.glide:glide:3.7.0' } |
- Now sync the project with gradle.
Creating RecyclerView Layout
- Now we will design the layout for our RecyclerView. It will contain an ImageView and a TextView inside a CardView. So create a new layout resource file named layout_images.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:padding="8dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="100dp"> <TextView android:id="@+id/textViewName" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Name" android:textAlignment="center" /> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/textViewName" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout> |
- So our layout for RecyclerView is ready. Now we will create an Adapter.
Creating RecyclerView Adapter
- Create a class named MyAdapter.java and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
package net.simplifiedcoding.firebaseupload; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import java.util.List; /** * Created by Belal on 2/23/2017. */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private Context context; private List<Upload> uploads; public MyAdapter(Context context, List<Upload> uploads) { this.uploads = uploads; this.context = context; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.layout_images, parent, false); ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Upload upload = uploads.get(position); holder.textViewName.setText(upload.getName()); Glide.with(context).load(upload.getUrl()).into(holder.imageView); } @Override public int getItemCount() { return uploads.size(); } class ViewHolder extends RecyclerView.ViewHolder { public TextView textViewName; public ImageView imageView; public ViewHolder(View itemView) { super(itemView); textViewName = (TextView) itemView.findViewById(R.id.textViewName); imageView = (ImageView) itemView.findViewById(R.id.imageView); } } } |
- Now come inside layout file of this ShowImagesActivity and add a RecyclerView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_show_images" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="net.simplifiedcoding.firebaseupload.ShowImagesActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.RecyclerView> </RelativeLayout> |
- Now write the following code inside ShowImagesActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
package net.simplifiedcoding.firebaseupload; import android.app.ProgressDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.widget.Toast; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.List; public class ShowImagesActivity extends AppCompatActivity { //recyclerview object private RecyclerView recyclerView; //adapter object private RecyclerView.Adapter adapter; //database reference private DatabaseReference mDatabase; //progress dialog private ProgressDialog progressDialog; //list to hold all the uploaded images private List<Upload> uploads; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_images); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); progressDialog = new ProgressDialog(this); uploads = new ArrayList<>(); //displaying progress dialog while fetching images progressDialog.setMessage("Please wait..."); progressDialog.show(); mDatabase = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS); //adding an event listener to fetch values mDatabase.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { //dismissing the progress dialog progressDialog.dismiss(); //iterating through all the values in database for (DataSnapshot postSnapshot : snapshot.getChildren()) { Upload upload = postSnapshot.getValue(Upload.class); uploads.add(upload); } //creating adapter adapter = new MyAdapter(getApplicationContext(), uploads); //adding adapter to recyclerview recyclerView.setAdapter(adapter); } @Override public void onCancelled(DatabaseError databaseError) { progressDialog.dismiss(); } }); } } |
- Thats it now just run your application and you will see all the fetched images in the next activity.
- Bingo! Its working absolutely fine. Â Now if you are having troubles or confusions you can get my source code from the link given below.
[sociallocker id=1372] Firebase Storage Example Source Code Download [/sociallocker]
So thats it for Firebase Storage Example. If you are facing problems then let me know in the comment section and I will try to help you out. Also don’t forget to share this Firebase Storage Example  if you found it useful. Thank You 🙂