Firebase for Android: File Storage

During the 2016 Google I/O conference, Firebase was reintroduced to the developer community as a major tool for providing quick back-end support for web pages and mobile applications. This tutorial will introduce you to the file storage and retrieval functionality available for your Android apps. 

To learn more about Firebase's real-time database, analytics, crash reporting and authentication, check out some of our other tutorials here on Envato Tuts+.

Authentication Setup

For the sake of brevity, we'll skip over the general setup process for Firebase in your Android app and the Firebase console. If this is your first time trying Firebase in an app, I suggest first checking out Ashraff Hathibelagal's article Getting Started With Firebase for Android

Before you can begin using Firebase Storage, you'll need to either make sure your user is authenticated, or change the authentication requirement rules in the Firebase Console to allow unauthenticated users to access and upload files. To keep things simple, we'll do the latter. Let's start by going into the Storage section of Firebase by selecting Storage in the left navigation column.

Firebase storage section navigation

Next, you'll notice there are two tabs at the top of the Storage screen: Files and Rules

Rules tab in Firebase storage

Select the Rules tab, and on the line allow read, write: if request.auth != null;, change != to == and click the PUBLISH button.  

Authentication rules for Firebase storage access

Now any user of your app should be able to upload or download files from your Firebase back-end. While this is not ideal for a production environment, it will make learning about Firebase Storage a lot easier without having to dig into authentication code.

Manually Uploading Files

While being able to upload files from an app is great, sometimes you'll simply want to store files somewhere that can be easily accessed and pulled down into your app. This is where being able to manually upload files from the Firebase Console comes into play. Under the Files tab, you'll see a blue button titled Upload File

Button for manually uploading files to Firebase storage

Click that and select the file you want to upload, and it will appear in your Firebase Storage.

An uploaded file

Selecting that file in the console will bring up a detail view, allowing you to inspect files that have previously been uploaded.

An uploaded file details

Downloading Files From an Android App

Now that you've got a file stored in Firebase, let's go ahead and pull it down into an app. We'll use a simple layout in our MainActivity that contains an ImageView with an id of image.

In order to access your Firebase Storage files, you'll need to first get a reference to the FirebaseStorage object, and then create a StorageReference to your project's URL and the file that you want to download. You can find your project's URL at the top of the Files section of Storage in the Firebase Console.

Next, you can create a File object and attempt to load the file you want by calling getFile on your StorageReference with the new File object passed as a parameter. Since this operation happens asynchronously, you can add an OnSuccessListener and OnFailureListener to your call in order to handle either contingency. 

In onSuccess() from OnSuccessListener, you can take the FileDownloadTask.TaskSnapshot object and retrieve the file, which is where we will set the image to our ImageView.

Image downloaded from Firebase storage displayed in app

Downloading Files as a Byte Array

If you only need to download the file as a byte[] and don't need it as a file, which is the more likely case when loading an image into an ImageView, then you can retrieve the bytes in a similar fashion.

Getting a File's URL

There may be situations where you don't need the actual data for a stored file, but rather will want the URL. You can do this in a similar fashion as the last two examples by using the getDownloadUrl() method on your StorageReference, which will give you a Uri pointing to the file's location.

The above method will print out the URL for the image we manually uploaded earlier in the Android Monitor.

Uploading From an Android App

Now that you know how to download files from Firebase, it's time to work on uploads. As you saw when downloading from Firebase Storage, the processes for each form of your data are fairly similar. Uploading is no different, so we'll simply dive in to how you can move files from your app into Firebase Storage.

Uploading a Byte Array

As with downloading, you will need to get a reference to the FirebaseStorage object and create a reference to your new file's storage location as a StorageReference. For this example, we will show ic_launcher.png in our ImageView, and then we'll upload that as an array of bytes.

Next, we will need to get a byte array from the image stored in memory via the ImageView. This is done by retrieving it as a Bitmap, compressing it into a ByteArrayOutputStream, and then turning that into a byte[].

Finally, you can create an UploadTask by calling putBytes(byte[]) to upload your image to Firebase. This UploadTask can also have an OnSuccessListener and OnFailureListener associated with it.

When you check the Firebase Console storage page, you should see ic_launcher.png in your list of files.

Details from a programmatically uploaded image

Uploading From an InputStream or File

Now that you know how to upload a byte array, the other two types of uploads should be fairly intuitive. Let's say we have a text file named test.txt in our raw resources folder. We can read this into an InputStream and then upload it by using the putStream(InputStream) method of StorageReference.

List of uploaded images including text file from InputStream

Uploading an existing file is just as easy: simply get a reference to the file and call putFile(Uri) with a URI pointing to your file. For this example, we'll just create an empty temp file in our code.

Raw file upload shown in Firebase storage

Controlling Uploads and Using Callbacks

While the files we've uploaded so far have been small, there may be times where you have larger uploads that will take a fair amount of time. Firebase provides a few methods with UploadTask that will allow you to control the flow of an upload and listen to progress and state changes. These methods include pause(), resume(), and cancel(). pause() and resume() will let you pause and resume an UploadTask, whereas cancel() will completely stop it. In addition, you can use an OnPauseListener and OnProgressListener to keep track of upload progress and pause states.

The above code will allow you to control the upload process for a somewhat large (1MB, in this case) image and see its states changing in the Android log when the pause and resume buttons are pressed.

Handling the Android Activity Lifecycle

As any Android developer can attest, sometimes the Android activity lifecycle can cause unexpected issues. One of the common sources of problems is listeners that last longer than their parent Activity, which may be the case for success/failure listeners attached to a Firebase storage task. 

If an Activity is destroyed and recreated (such as on screen rotation) while a task is occurring, you may end up with a NullPointerException when the task has completed. To avoid this, you will want to save your StorageReference as a String in your out state Bundle in the onSaveInstanceState(Bundle) method, and then retrieve it and add success listeners to each FileDownloadTask or FileUploadTask associated with that StorageReference.

Conclusion

In this tutorial you've learned a great deal about Firebase and its available options for file storage. You should now be able to upload and download files, control data transfers, and handle changes in your app's activity lifecycle while a transaction is occurring. 

While we've just scratched the surface of what you can do in Firebase, understanding this tool will hopefully enable you to expand the capabilities of your own apps and provide great experiences for your users.

And in the meantime, check out some of our other articles on Android development!

Tags:

Comments

Related Articles