 Hello everyone. In this video we're going to talk about a strategy for dealing with images in your application, specifically dealing with images that you want to add and delete as users are using your app. So today you have used images in your apps. You had them in your Seahawk Tours app, the beer advisor, the bits and pizzas app. So images are pretty central to many apps, right? And you know some of them are built exclusively around images like Snapchat, Instagram, that sort of thing. So today images in your app are referred, they are resources, right? You copy the image file into your Android project, and then whenever you want to display the image in an activity, you have to refer to the image resource. And there's a lot of downsides to that, as you have no doubt experienced. It can be difficult working with resources and those references. That r.id.stuff. What is that stuff really? It can be challenging to deal with, and you probably really experienced this pain in the Seahawk Tours app, where I asked you to store images or image information for each building in the building object. Another challenging aspect is those resource IDs, that r.id, they're not permanent. Every time you build your app, or potentially every time you build your app, and every time you add resources, those values can change, so you can't store them in some sort of permanent database. Also, if you were, you know, deploying your app to the world, any time you wanted to change the images in your app, you would have to redeploy the app, and that can take, you know, up to 24 hours. So working with images as resources is a little painful. Right now, when you hit the run, it redeploys your app, and all the new images are kind of placed, packaged up with your app, and put onto the emulator or put onto your phone. But whenever you are deploying a real app in production, that process can take up to 24 hours to reach all the users, right? If you are an Android user and you have automatic updates turned on, which you should for security reasons, it updates at most every 24 hours, right? So that's just not viable for an app like Instagram, right? If you want people to see your hot new plate of tacos right now, you can't wait 24 hours, that's unacceptable to redeploy the app. And how would you manage that anyway? There's millions and millions of users. Not everybody's pictures are in the app at once, obviously, right? So these pictures must live somewhere, and of course that place they lived is in the cloud. Right. So images need to be a part of your app's dynamic data. How are we going to do this? Well, we can put them in a database, but images really don't work well in databases, right? Databases are meant to search and query data. There really aren't image databases that you can search and query easily. Usually they exist with metadata tags. Could we put them in the fire store that we learned about last time? Well, unfortunately, the fire store doesn't let you store images there. However, there is a place that you can put them. There are many places you can keep them. The solution that everybody has for distributing dynamic resources like images, but also videos and also sound files, is to keep the file itself somewhere in the cloud, like a Google Drive or a OneDrive or something like that. But keep a reference to their location in the database, right? We've already seen with the fire store how that when you make a change to the fire store database, it can propagate out very easily to all of your app users. So in the database we can keep a reference to where the image lives somewhere on this planet. We can then tell all of our users, hey, there's this new cool picture out there, and it's located on so-and-so's Google Drive. Go grab it, then the app can go out and kind of fetch and download that image. That's the approach that we're going to have. Now a problem though, if you're interested in serving files to your app, there's a problem there. It's very challenging, right? Think about Instagram, right? I don't know what the most popular person on Instagram is. It's probably some celebrity I don't really care about. But look, they take a picture of their cute kids' latest $5,000 onesie, and they want to show it to everybody, right? And they've got 3 million followers, 30 million followers. I don't know. How are you going to send out 30 million copies of an image at once? Challenging, right? You need to be able to scale up quickly. Also, not everybody's connection is reliable or good to begin with. You're sending out 2 megabyte files, a nice picture, but it's not trivial, right? Think about 2 megabytes times 30 million users. That's a lot of bandwidth you consume, just for one picture to get it distributed to everybody, right? So, the other issue is files, especially images, can be large, right? And asking, this is a problem that faces you, the developer, telling your app to, hey, every time I open Instagram, I want you to go download all of Kim Kardashian's images. If your app downloads all of her images every time, you're going to be wasting a lot of your data, right? So, the solution to this is caching, right? So, you download the images once, and then you only re-download them if they have changed. This is called caching, where you just kind of store something and repeatedly read from it and only update it when it changes. Unfortunately, it turns out if you try to implement this logic yourself, it's not so easy. It is non-trivial to implement good caching logic. And there are whole companies, in fact, who deal with optimizing caching at a large scale. So, what are we going to do? Let me talk about a solution for you to use in your apps for your term project. We're going to use Firebase Storage. Firebase Storage is file hosting up in the cloud. You get five gigabytes for free. You can download a gigabyte a day, 20,000 uploads a day, 50,000 downloads a day. That's a fair amount at the free tier, right? Especially if your images are short. So, you're not going to run into any image limits or usage limits for this class. But what is it? It's just a file host in the cloud where you can put stuff. Nothing more complicated or more simple than that. All right? So, how are we going to put images in our cloud storage and have them dynamically update and push out to our app? So, here's the strategy we're going to follow. We've got the Firebase Storage, the Firebase Cloud Storage Service. In it, you have this concept of buckets. And a bucket is a directory, right? In the free tier, you get one free bucket, kind of the home root directory for your app. Now, you can have subdirectories within your bucket. It's fine. And here is where you're going to put your files, right? Again, you can store up to five gigabytes of files. On the other hand, on the other side, we've got the Google Cloud Firestore, excuse me, the Firebase Cloud Firestore. As we talked about last time, you can have different collections in there. So, we're going to have a collection in there. And this one in our example project, it's a collection of plants. And each plant has a name. And each plant has an image file associated with it. And the image file, these are both just strings. This image file, though, is going to map to a path over here in the Firebase Storage bucket to the appropriate image, right? So, this is just data stored in the Firestore. But when we are using this in the context of our app, the first thing our app will do, we're going to have an activity. Let me kind of paint the picture for you. We're going to have an activity that shows pictures of plants. You can click on a plant and get a new picture from a different plant. That's all it does. So, the way our activity works is, first, we're going to get the collection of plants, get the data from the Cloud Firestore. It's going to send it back. And then, our app logic says, okay, the first plan I want to show is the Venus Flytrap. So, we're going to use a library called Glide. Glide is a very popular library, been around a long time. It does image cap downloading and caching for you. So, you don't have to handle that logic of downloading and caching the thing. So, we're going to tell Glide, hey, go to the Firebase Cloud Storage, get this image file, images.flitrap.png, and return it. Now, you will actually have that file on your device, and you can tell the image view to display the file. So, let me show you what this will look like very briefly. Let me get my code up, and let me get my emulator up. So, here's my Firebase project. The first thing you want to do, if you haven't already, make sure that you have a user in here, and sign in with that user. The Cloud Firestore does not like you talking to it with anonymous users. You will get warnings and errors. I think it will still allow you to communicate, but you want a user to be authenticated. So, I'm going to create a new account. Oh, I already have it, so let me log in. All right, now I'm logged in. Okay, now in my emulator over here, I'm going to click on Launch Firebase Storage and Picture button. Okay. So, I don't know if you noticed, if you didn't, rewind it a little bit and watch. There was a very slight delay before it showed this picture of the picture plan. Okay, and that slight delay was the activity going out to the Firestore, getting the data for all the plants that I can show. I can show a couple here by clicking on them. They rotate around. Getting the data for the picture plan and then glide calling up to the Firebase Cloud Storage and downloading that image. Once the image was finally there, it popped up on the screen. There was a slight delay. Now you'll notice as I click through this, they show up instantly, and that's because Glide, our library, is caching these images. It's not re-downloading them. It's just pulling them off the disk. Okay. Let's go over to the Firebase project for a second. Here's the project overview. We're going to click on Storage. Okay. So, in storage, this is my storage bucket. This is the default bucket. I'm going to click on bucket per app. That's fine. That's all we need. I've created an images directory here. Okay. Inside this images directory, I have the names here of the images. And if you click on them, it'll actually show you a little preview of them. So, uploading files is pretty easy. You just do this and pick the image. Okay. That's it. That's all that's in my bucket. It's more magical than that. I've got a directory and I've got some pictures. Let me go back over to the fire store by clicking on the database on the left. You can see I have two collections here. I have the people collection from last time when we were manipulating the fire store. And then I have plants. And inside the plants, I had to add documents corresponding to all the plants I wanted to display with their name. And then the directory, the location in the storage where this thing is found. Let's switch over to the code for a second. So I'm inside the storage activity. If we scroll down, here I'm getting my references using the firebase libraries to the firebase storage and the firestore itself. Here in my oncreate, I'm setting up some views, but here I make the call to the firestore to get all the plants, all the documents that are in the plants collection. Once this is successful, oncomplete, if it's successful, I convert each plant document into a plant java object, which I have defined over here. Plant java object is plain. It doesn't do anything. It just holds the name and a string that's the location of the plant in cloud storage. And I'm adding it to a list. All done. And then I have this update UI that's actually going to say, oh, I got something. Now let's draw it. Let's take a look at this. Update UI. I've got some checking here to make sure I've actually downloaded it. I'm keeping my plants in the plant list, but I've got to make sure that there's actually data in there before I display the image of it over here. Because there is going to be a little bit of lag when I first load this activity, where it goes out to the firestore, downloads the data, and then goes up to the cloud and downloads that data. But down here, I'm updating my view. Here the storage reference. Okay, so I'm creating this new thing using the Firebase library called a storage reference or excuse me, the cloud storage library. I get a storage reference and it's based off the plant image file location. So get image file returns to me this string. I get the storage reference and then I say hey, glide, go load the image and put it into plant image view, which is a part of the layout. And that's it. Glide kind of handles it all the magic in the background. So it's actually quite easy to deal with. There's some other stuff going on in here that I have to do to work with that glide appropriately. I don't want it to keep like trying to download stuff from the internet whenever my app goes in the background. That would not be good. You'd get some errors if it didn't do that. But anyway, it's actually not all that complicated. So these images are being pulled from the internet. So in your term project, I know a lot of you want to have pictures of the items you want to sell. Whether you're pulling the image down or putting the image up, the process is, you know, it's not so bad. It's not horribly, horribly complicated. And certainly, once you get it for one item, all the rest will fall. All right. So I want you to do then, that's your introduction to the Firebase Cloud Storage. There's a lab associated with this kind of talks you through the code a little bit more that I just showed you and shows you how to use it. So go ahead and work on this lab, work on the previous lab on the cloud fire store. And as a reminder, your milestone two that incorporates Firebase authentication is due this week. If you have any questions, you know how to get in touch with me. Have a great rest of your day.