I got many messages asking how to store and fetch PDF files in Firebase Storage. So here is the detailed post explaining about Uploading PDF files in Firebase Storage and Fetching those uploaded files from Firbase Storage. I already posted a tutorial about the same thing but with image files. You can check that post from the below link.
Firebase Storage – Uploading and Retrieving Images
Important: If you have no idea about Firebase Database and Firebase Storage, then it is highly recommended that go through the previous post from the link given above first. As I will not be explaining here about setting ab Firebase Storage and Database in the project. These things are well explained in the post given above. So please go through that first.Â
Table of Contents
Creating a New Project
- So again we will start by creating a new project. I just created a project named FirebaseStorage.
- After creating the project add Firebase Storage and Firebase Database to your project (Go to tools->firebase).
Creating UI
- We have only two screens for this application. The first is the activity_main.xml which is created by default. And create one more Activity named ViewUploadsActivity.java.
- In the first activity we will upload files to firebase storage and in the second activity we will display a list of all the uploaded files.
MainActivity
- Open your activity_main.xml and write the following xml 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 |
<?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:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context="net.simplifiedlearning.firebasestorage.MainActivity"> <EditText android:id="@+id/editTextFileName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:hint="Enter a name for your file" android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" /> <Button android:id="@+id/buttonUploadFile" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/editTextFileName" android:text="Upload PDF" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical"> <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:visibility="gone" /> <TextView android:id="@+id/textViewStatus" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="No file selected" android:textAlignment="center" android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" /> <TextView android:id="@+id/textViewUploads" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="View Uploads" android:textAlignment="center" android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" android:textColor="@color/colorPrimaryDark" /> </LinearLayout> </RelativeLayout> |
- The above code will generate the following screen.
- You can see the layout is pretty simple, we have an EditText to get the file name, A button to upload the file and a TextView to go to the View Upload screen.
View Uploads Screen
- As I told you that we have two screens in this app so create one more empty activity and name it ViewUploadsActivity.
- Now come inside the layout file for this activity and write the following xml code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?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="net.simplifiedlearning.firebasestorage.ViewUploadsActivity"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> |
Creating Helper Classes
- For this we need some helper classes for modeling the data and storing the constants. So first create a class named Constants.java and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 |
package net.simplifiedlearning.firebasestorage; /** * Created by Belal on 8/25/2017. */ public class Constants { public static final String STORAGE_PATH_UPLOADS = "uploads/"; public static final String DATABASE_PATH_UPLOADS = "uploads"; } |
- Now to save the uploads data in Firebase database we need a model class. So create a new class named Upload.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 |
package net.simplifiedlearning.firebasestorage; /** * Created by Belal on 8/25/2017. */ 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; } } |
- Now lets upload the files.
Uploading PDF in Firebase Storage
- Now here comes the main task of this post which is uploading PDF files to the storage. The uploading is done on the MainActivity so come inside MainActivity.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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
package net.simplifiedlearning.firebasestorage; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.storage.FirebaseStorage; import com.google.firebase.storage.OnProgressListener; import com.google.firebase.storage.StorageReference; import com.google.firebase.storage.UploadTask; public class MainActivity extends AppCompatActivity implements View.OnClickListener { //this is the pic pdf code used in file chooser final static int PICK_PDF_CODE = 2342; //these are the views TextView textViewStatus; EditText editTextFilename; ProgressBar progressBar; //the firebase objects for storage and database StorageReference mStorageReference; DatabaseReference mDatabaseReference; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //getting firebase objects mStorageReference = FirebaseStorage.getInstance().getReference(); mDatabaseReference = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS); //getting the views textViewStatus = (TextView) findViewById(R.id.textViewStatus); editTextFilename = (EditText) findViewById(R.id.editTextFileName); progressBar = (ProgressBar) findViewById(R.id.progressbar); //attaching listeners to views findViewById(R.id.buttonUploadFile).setOnClickListener(this); findViewById(R.id.textViewUploads).setOnClickListener(this); } //this function will get the pdf from the storage private void getPDF() { //for greater than lolipop versions we need the permissions asked on runtime //so if the permission is not available user will go to the screen to allow storage permission if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())); startActivity(intent); return; } //creating an intent for file chooser Intent intent = new Intent(); intent.setType("application/pdf"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_PDF_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //when the user choses the file if (requestCode == PICK_PDF_CODE && resultCode == RESULT_OK && data != null && data.getData() != null) { //if a file is selected if (data.getData() != null) { //uploading the file uploadFile(data.getData()); }else{ Toast.makeText(this, "No file chosen", Toast.LENGTH_SHORT).show(); } } } //this method is uploading the file //the code is same as the previous tutorial //so we are not explaining it private void uploadFile(Uri data) { progressBar.setVisibility(View.VISIBLE); StorageReference sRef = mStorageReference.child(Constants.STORAGE_PATH_UPLOADS + System.currentTimeMillis() + ".pdf"); sRef.putFile(data) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @SuppressWarnings("VisibleForTests") @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { progressBar.setVisibility(View.GONE); textViewStatus.setText("File Uploaded Successfully"); Upload upload = new Upload(editTextFilename.getText().toString(), taskSnapshot.getDownloadUrl().toString()); mDatabaseReference.child(mDatabaseReference.push().getKey()).setValue(upload); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show(); } }) .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @SuppressWarnings("VisibleForTests") @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); textViewStatus.setText((int) progress + "% Uploading..."); } }); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.buttonUploadFile: getPDF(); break; case R.id.textViewUploads: startActivity(new Intent(this, ViewUploadsActivity.class)); break; } } } |
- Now you can test uploading a File. But before we need to change the Storage Rules and Database Rules on Firebase Console. As the default rules allows only authenticated users to upload the file and write to the database. So either you need to make an authentication on the app or change the rules to public. So for this example we will make the rules as public.
Changing Firebase Storage and Database Rules
Firebase Storage Rules
- Go to Firebase Storage and in Firebase Console and change the rules as below.
1 2 3 4 5 6 7 8 9 |
service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write; } } } |
Firebase Database Rules
- Now for the Database Rules use the following.
1 2 3 4 5 6 7 8 |
{ "rules": { ".read": true, ".write": true } } |
Testing the Upload
- Now lets test the application by uploading a file.
Retrieving Files from Firebase Storage
- Now come to the ViewUploadsActivity.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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
package net.simplifiedlearning.firebasestorage; import android.content.Intent; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; 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 ViewUploadsActivity extends AppCompatActivity { //the listview ListView listView; //database reference to get uploads data DatabaseReference mDatabaseReference; //list to store uploads data List<Upload> uploadList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_uploads); uploadList = new ArrayList<>(); listView = (ListView) findViewById(R.id.listView); //adding a clicklistener on listview listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { //getting the upload Upload upload = uploadList.get(i); //Opening the upload file in browser using the upload url Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(upload.getUrl())); startActivity(intent); } }); //getting the database reference mDatabaseReference = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS); //retrieving upload data from firebase database mDatabaseReference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) { Upload upload = postSnapshot.getValue(Upload.class); uploadList.add(upload); } String[] uploads = new String[uploadList.size()]; for (int i = 0; i < uploads.length; i++) { uploads[i] = uploadList.get(i).getName(); } //displaying it to list ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, uploads); listView.setAdapter(adapter); } @Override public void onCancelled(DatabaseError databaseError) { } }); } } |
- Now test this screen as well.
- Bingo! it is working as well. When you will click on an Item it will download the uploaded file from the storage.
Download Source Code
- If you are facing any troubles you can get my source code from here.
[sociallocker id=1372] Firebase Storage – Upload and Download PDFs Source Code [/sociallocker]
So thats all for this tutorial friends. If you are having any queries regarding Firebase Storage or Android Development don’t hesitate to comment. And if you want some help if you are stuck in your app then also comment here and I will try to post a tutorial to help you.
If you liked this Firebase Storage tutorial, I request you to please SHARE this post among your friends. If you don’t like it please comment the reason so that I can improve the website. So thats all for now. Thank You 🙂