Android App Development For Complete Beginners Part 2 - Building a Weather App | Lee Falin | Skillshare

Android App Development For Complete Beginners Part 2 - Building a Weather App

Lee Falin, Software Developer and Data Scientist

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
10 Lessons (1h 19m)
    • 1. Introduction - About APIs and JSON

      5:05
    • 2. Creating the UI with Constraint Layout

      4:42
    • 3. Retrieving the Weather Data

      10:31
    • 4. Parsing the JSON Response

      6:51
    • 5. Formatting the Temperature

      5:21
    • 6. Fetching Weather Condition Images

      8:26
    • 7. Using an Icon Font for Weather Images

      18:49
    • 8. Getting the Location from the User

      12:02
    • 9. Refining the User Experience

      5:25
    • 10. Conclusion / Next Steps

      1:34

About This Class

df99ca34

This tutorial is the second in my Android App Development series.

While we'll be building a weather app in this tutorial, the skills you learn can be applied to developing any application that needs to access a REST API or work with JSON data. Since there are so many different APIs available, this is a valuable skill that you can use to create an endless variety of apps.

In these lessons you'll learn how to access a REST API, parse JSON data responses, build a user interface using constraint-based layouts, use a scalable icon font, and how to integrate 3rd party libraries into your project.

Note that this class assumes you've already completed the first course in the series, Android App Development for Complete Beginners. If you haven't completed it yet, click below and complete that introductory course, then come back and jump right in to Part 2.

Transcripts

1. Introduction - About APIs and JSON: Hi. My name is Lee Phalen, and this is the second part of my android app development. Siri's where we're going to create an android weather app. Now, as a prerequisite, I'm going to assume throughout this tutorial that you've already completed my first class android app development for complete beginners. If you haven't completed that, there's gonna be a lot of information in this tutorial that won't make sense. So please stop here. Go back, find that class. You can find a link to it in the notes for this glass and go back and go through that class from start to finish and then come back here and you'll be all set to continue. Now, just like for my other class, I'm going to assume that you have access to three things a Windows or Mac computer that's built in the last 4 to 5 years and android phone and a WiFi network. Now, if you don't have access to a phone just like before, that's okay. We can get through this tutorial using just the android emulator. In this tutorial, we're gonna learn how to access an A P I now a p I stands for application programming interface that could mean a lot of different things in different context. But for our purposes, it's a resource that provides structured information. Now that information in our case is gonna be in Jason format. Jason is a structured way to represent data. So, for example, if you had the weather information with the high, low and current condition, you could display that using a Jason file that would look similar to this. That Jason document would have a set of key value pairs. So, for example, the current high in the weather today is 70 degrees. In this entry, high is the key, and 70 is the value. That means if we have this document this Jason Data we can access since information by providing the key high, and then we will get back the value of 70. Now, many websites provide AP eyes to access their information. For example, if you go to some Weather Service website when you access that site with your computer, it provides you with information about the current weather conditions. However, behind the scenes, it might be storing that information in Jason format. Some websites will then provide another entry point, another you, Earl, that you can use to access that Jason information directly. And this is usually called on a P I in point. If we have that a p i n point and we have permission to access it, we can query it and get the information directly in Jason format, which we can then use in our application over this project, we're gonna be using the open weather map, whether a p i. In order to access this data, we're gonna need an A p I key. This is a code that we send to the A p i when we make a request for a Jason Data that authenticates the fact that we have access to that data. Fortunately, this AP I kiis free. So what we'll do is we'll click sign up and here on the create new account page will just enter some information. So our name and our email address and then we'll enter a password and click our agreement buttons and not a robot and create account. And then it just asked Cem survey purposes. And we can just say I'm using this for education or science save. And now if I go to the A p I keys Tab, I will see a key. Now notice I have mine blanked out. That's because you never want to share your a P I key with anyone. A p I key is basically a form of identification that says you are you. So if you're using a service that does cost money and you share your a P I key with someone when they use that a p i key, it will charge you for that usage. There been lots of cases of companies that have accidentally shared their A p I key in the public. And then if I had to pay lots of money for those bills So you want to make sure that you do not ever share your a P I he with anyone. So we're gonna refer back to this a p I key later, when we make our A P, I calls in a few other videos. So just keep that someplace handy, maybe copy and paste it into a document on your desktop, and then we can refer back to that later. So again, while you generally want to keep a p I keys pretty safe in this case since the service were using, It's free. If this a p I he accidentally gets out into the wild as they say, it's not gonna cost you anything. 2. Creating the UI with Constraint Layout: So the first thing you're gonna want to do is open up Android studio. And once that opens up will start a new android studio project. And you can just name it whether or whatever you want. And we're just gonna leave everything else as the default click. Next, Um, just leave. Whatever the default a p I is for your system on their a bunch of different activities like we saw before on will hit next to do an empty activity and just leave that as main and click finish. Now, while we're waiting for that project to build, just a reminder this tutorial assumes you have gone through the android development for complete beginners class that I also have posted on skill share. So some of the basics I'm in a skip over. So if you haven't watched that class, you may want to do so before we get too much further. Ah, I just want to make sure you have something to test your app with either in the virtual device manager that you either have a virtual device set up or connected device. A real phone you're testing with. We don't need it right now, but if you haven't done it yet and you're not sure how, make sure again, you check out the previous tutorial which walks through that. So what we're gonna do first is we're gonna set up the ah user interface so we can see here . We're using constraint layout, and the first thing we're gonna do is just delete the placeholder here this hello world text on. We're going to drag an image view into our lap, and we don't have an image for it yet. So to make it easy to see, we're just gonna set a default color. Now you can see the image you gets really small, because by default it's with and Heidar set to wrap content, which means it automatically resize is based on how big the image inside of it is. Since we don't have an image inside of it right now, we'll just set it to 128 by 128 device pixels, and then we can see it with its default gray background on. Let's set it right here in the center. Now, even though it's in the center watch what happens if I rotate the device to landscape, see how it drops down here to the bottom. In portrait, it looks good, but in landscape, it doesn't now. That's because of the constraint based layout constraint. Layouts allow you to define a set of constraints or conditions that dictate how the different user interface elements will be laid out on the screen. And we can define those constraints relative to the sides of the screen, the top of the screen relative to other components and all kinds of things. And so we'll be doing that today. The constraint, basically out, is really nice, because it works across different orientations and different device types so we can modify these constraints in the main u I or over here in the inspector by adjusting these controls over here. But we're going to do in the main you. Why, by dragging from the top and sides of this image to the top and sides of the container. Once we do that, we can see it automatically set some margins here on Let's go ahead and change this top margin to 16 pixels. Now, if we switch over to landscape mode because of the constraints, doesn't matter foreign portrait or landscape. It stays right in the center and we can even change device types. Let's say we do this, Um, Nexus seven or Nexus nine. You notice how our image stays right in the top center of the screen. And if we jump back to portrait, it still goes there even if we switch to one of these TV models right in the top center. So constraint based layouts of really great for making sure that everything stays where we want, regardless of what kind of device were using. Now let's go ahead and give our image view name that we can refer to. Let's change it from its default. Ah, I d from image view. Let's call it weather image and then just click anywhere and that will be reflected over there. And then let's go ahead and add text. You were going to use this toe, hold our temperature. Let's have it attached to the bottom of the image and also be centered to the left on to the right of its parent. But this is looking a little close here, so let's change this top margin to 32 pixels and let's go ahead and give this a new I d. Call it temperature label. And then let's change the size down here under text size from 14 to 30 just to make that a little easier to see and notice. When we switched the landscape and back to portrait, it always stays right in the center and underneath that image that we created. 3. Retrieving the Weather Data: Okay, so now that we have our user interface all set up, let's go ahead and look at how we're going to get the data. We go to our open weather map ap I page, we can see there are a few different things. We're looking for the current weather AP I documentation. And over here on the right, we can see by zip code. That's the one we're gonna using today. And if you look at this, you'll notice that up here we have the A P I call, and this first part is what's called the a P I in point. This is theory website address where the data is coming from. This is followed by a question mark which separates the in point from the parameters. The first parameter is a zip parameter where we're going to specify our zip code and country code, the location we want the weather for. And here's an example of how that would look in real life. And as we talked about the beginning our, uh, Ap eyes going to return us a big Jason object. And so we'll look at that Jason Here. Ah, in more detail as we go through the tutorial. But one thing I want to point out right here is noticed. The temperature value looks really high. That's because by default the temperature is returned in Kelvin, which is probably not what you want in your weather app. But if we look here on the list of options under units format, we see that we can supply additional AP I parameters for metric and Imperial. So Celsius or Fahrenheit. And the way that works is when we have our A P I in point parameter list with our question mark each parameters separated by an ampersand so we will add ampersand units equals metric for Celsius or Imperial for Fahrenheit. Let's go back up here to the top so we can get back to our ZIP code a p I on. I'm just going to copy this and then jumped back over to Android Studio. We'll switch to our job a file for a main activity, and I'm going to add a new function here called Update Weather, and we will create a string variable. We'll call that a p i u r l. And we'll set that equal to https colon slash, slash and what we copied. And then let's add our units parameter set that to Imperial. And then we also need to add our app i d that we signed up for Ah, in the beginning. So where these three dots are right here, you need to make sure, um, you paste in your app I d Now make sure you don't try to use mine because it is going to be deactivated before this video is live. So now what we want to do is build a download. The weather information from this, a p I. To do that, we're going to use volley, which is a library Google provides in order to make it easy to download things from online . To install 1/3 party library like this, we usually use the greater dependency, the great all dependencies listed here at the bottom. So we'll just copy and paste this and then we will jump back over to Android Studio on expand the Great Ill Scripts folder on there, a couple of different grade all files Graito files or files that help our project to build . So we have the Project Graito file, which controls everything you need for the entire project to build. And then we have a module Great. I'll file which is has a list of dependencies that we're going to include in our app. So down here at the bottom, we'll just add this line and we're gonna change from compile to implementation because that's the newer way to list the dependency. So what this tells Android studio is that we want version 1.1 point one of the volley library. Now, the way these great all dependencies work is that when you build your project, the first thing Android studio will do is make sure that it has the correct version of each of these libraries downloaded. Once it does, it will then resync the libraries and it will begin to build the project. So if you want to add extra third party libraries to your project, all you have to do is add a listing for them in the bill dot grade. I'll file for the module, and once those air there, then every time you build the project, Android studio will check that you have the correct version installed. Now, every time you make a change to your great oh file, you have to re synchronize you. Get a little warning up here. Just click Sink. Now on Android studio will start rebuilding, downloading any dependencies you've added, compiling everything together and making sure everything eyes compatible. Sometimes you'll get 1/3 party library or even a Google library that's incompatible with one of the other libraries you're using. Usually that's because of the version numbers. Some versions of certain libraries aren't compatible with versions of other libraries that you can just change the version number in the Great Hall script to fix that. So next let's jump over two main activity back to our update weather function, and will you start using the volley library? So the first thing we need to do is create a request que something that will use to store the Web requests were making, and again we just all to enter or option enter to automatically import the necessary classes that will create that as a huh request que object and will pass it the current context of the activity that we're in and you'll find this pattern of having to pass the context into an android object pretty frequently. So the next thing we're gonna do is create a Jason Object request. Because, as we mentioned, this is the type of a p I were using uses, Jason, it will create a new Jason object request. Now, this Jason object request uses a lot of different parameters. So to make it easier to know what we should be, including we compress command P or control p on Windows to view the parameter list. Now, with the parameter list there, we can kind of follow along. We see two different versions were going to be using the top version of the Jason Object request constructor. So the first thing we want to supply is the method, and we're gonna be using the get method in order to use a CTB get and will pass in our A P I. You Earl. Now, if we wanted to send any information to the A P, I would specify that here, but we don't so in our case, will just enter null to send no information. And then we have to create a listener just like we do with buttons. But instead of responding to clicks, this is responding to win the A. P. I sends us information back so we will start just like before with new and we'll start typing listener and then hit tab or enter and that will auto create all the scaffolding. And then we have to create one mawr listener here. Uh, so we'll type new again this time for the error listener that will get called if there's a problem with our request. So we've got to listeners here The first the on response method will get called when something is returned from the A P I and on error response. If there's an error return from the A P I. Now this could be a bit confusing because remember, this isn't happening in order. We've created these listeners up here on They are going to be called later. Right now, before anything can happen, we have to take our cue and add our Jason request that we are making to the a p I. So now that we have that all set up Ah, we need to make sure this update weather function is called somewhere cause right now it's never used, So we'll have that called in on create. So as soon as the activity comes on screen are update, weather function will be executed. Unfortunately, that is going to make an error happen because of some things we haven't done yet. But let's see what the air message says by using a toast, a little message that we could make appear on our screen So we'll create a toast that will call error toast on DWI will use theme ache, text function to make a text toast, pass in the context and then pass in the text that we want displayed in this case. What we want displayed is the error message we're getting from the error response, so we'll type error dot get message, and then we'll specify how long we want that toast to appear on the screen. Now. One more thing we have to fix here is the fact that our this keyword for the context doesn't work. That's because our error listener is a separate context from the main activity. So in order to say that we want this toast to appear within the context of our main activity, we have to specify main activity dot This as the context. Now, finally, now that we have our toast set up to display, let's go ahead and show it. Ah, using error, toast dot show And again, this is only gonna happen when the error response occurs. We'll do something similar for the regular response. Just temporarily will call this good response toast. Andi will set it up the same way using our main activity context. And this time we'll just post the entire response as part of the toast on again. This is just temporary. Until we do something better just to make sure our a p I works, one more thing we need to fix here after we display the toast is response is a Jason object . So we're joined to use the two string method to converted into text. So what, that all set up? Let's go ahead and test this out. We'll click, run and select our device and say, OK on. We'll wait for our emulator to load our app. See, the greater build is running and if all goes well, there will be no heirs. Uh, the app will be loaded into the emulator and there you can see an error appear. We are missing our internet permission, so we need to give our app permission to access the Internet. So let's go ahead and do that next 4. Parsing the JSON Response: Okay, So to fix that problem, we're gonna go ahead and open up our APP folder and then the manifest folder and inside will find the android manifest file. This file contains a bunch of meditating about our app. We're gonna add an entry here called Uses Permission and specifically, we're going to request the internet permission. This permission tells our APP or rather tells the operating system that our APP needs to access the Internet. If you've ever downloaded an app from the play store and it has a list of permissions that you need to grant it. Those permissions come from that file. So now we'll rerun are emulator and compile the app. If everything goes according to plan, the APP should compartment and it should load onto the emulator. And then our request should go through and the big blob of Jason text will appear is expected. So now our app is doing everything we told it to do everything we expected. So now let's do something different with that response. So first, let's get rid of this code that's going to show the response as a toast on the screen, because that's not what we want to do, and what we're going to do instead is we want to extract a particular piece of information , and we're going to show that on, um, screen inside one of our text boxes. So we'll put the code for that right here. But first, let's pop back over to our activity and look at our text view. And if you remember, we gave that text view an I. D. Of temperature label. So let's go ahead and try to put the temperature there. So in order to do that, the first thing we need to do is get a reference to that view. So will create a text. Few variable here, and we'll just refer to it as temperature label. And we'll use fine view by i D and give it the I D that we provided in our activity layout , and we now have ah reference to that temperature label. But the problem is, if we now come down here to our update weather function, and we try to access that temperature label variable that we created in the on create will see that it says it cannot result the symbol. The problem with this is that this symbol. This variable has been created inside the scope of the on create function. The scope is delimited by those curly braces. Now, our update weather function has a separate scope. Whenever you have a set of curly braces that's creating a new scope, a new area where those variables can exist. So what we want to do is use this outer scope for our variable variables created here as members of the main activity class can be accessed by any function inside the main activity . And so what we're gonna do is we're gonna copy this variable declaration where we create the temperature label variable, and we're gonna move it up here to be part of the main activity class. So once we've done that, we don't need to re declare it here. So inside, on create, rather than creating the variable, were just assigning it. So we've created it here, and we assign its value there. Since it's a class variable, we can now access the variable in all of its functions inside of our on response call back method. Now, if we took back over to our open weather AP, I we can see that the blob of Jason, we get back. This is actually what we call a Jason object. It's got a set of keys like cord and then a set of values. And here's another key and then a set of values for that key. Now, sometimes the the value for a key could be a string. But sometimes it's an object. So the part of the response we're going to be interested in right now is the main key. And if we look at the main key, we can see that it contains a Jason object as its value. So what we're gonna do is we're gonna see from the response, get the Jason object. That's associate ID with the main key now within the main key response, we have this temperature value that we're going to get back is a string. So we'll just say from that object that we get from Maine, let's go ahead and get the temp value back. So we're gonna reach inside, grab the main object, and then inside of that, we're going to get the temperature value, and we're gonna store that as the text value of our temperature label. Now we can see here that It warns us that there's an exception we're not handling. In other words, there could be something that goes wrong with this, and we need to fix it to fix that. We can tell Android Studio, Let's just surround this with a try catch. And so if something goes wrong, it will catch that exception here, and it will handle the error by default. It prints it to the console. But instead of doing that, let's go ahead and copy what we do with our error response call back. And we will, instead of showing error, will show our exception here. So we replaced that with E. And so now if there's an exception, will display that as a toast on our screen. So before we run this, let's recap and just talk about from the top what we're doing here. So, first of all we have in our main activity, we have our on create function. This is gonna happen when the activity first launches, and when that happens, we're gonna first do this kind of basic set up stuff to lay out our screen that we're gonna grab a reference to our temperature label and store is a class variable. They were gonna call the update weather function. The update weather function accesses this particular a p I. And so then we build a request using the volley, a p I, and we're going to specifically be asking for a Jason object. And when that request goes through, either it will work and it will call this function on response or it will fail and call our on error response call back. So then we add our request to the Q, which causes the request to be made. When the response comes back, we take the Jason that we get, and we grab the main Jason object and then grab the temperature value and stored in our temperature label. If anything goes wrong with that will display the air message as a toast on our screen. Let's run our emulator and see if that works is expected. Hopefully, what we'll see is the value for the current temperature of that zip code that we've hard coded into the A p I. Earl and there it ISS 73.58 degrees. In my case, it will be a different value, probably depending on when you're running this So now that we're communicating with the A P I and getting data back, let's form at this to make it a little bit nicer on the screen. 5. Formatting the Temperature: So now let's format are temperature, so it will look like you would normally see on a weather website. To do that, we're going to create a format string format strings can be created in the resource is folder undervalues and then in the strings file. So we see we've got a string here already for the name of our app, we're going to create another string and will give it a name that we can use to refer to it in our code. And we'll just call it tipped format and the value for the string. Let's pretend that we want it to look just like this. We wanted to show the temperature and then f for Fahrenheit. Or if you are using Celsius, maybe you want to see or if you're using the default of Kelvin you want, okay, But we're gonna be using an f Now. We could make that look. However we want, we could add, Tim Colon. Here we get at whatever string whatever formatting information we want. But for our purposes, we're going to get rid of this and we're just gonna have it display the temperature and then f Now, of course, we don't always wanted to say 86.7. We wanted to show the actual temperature, so we'll replace this value with what's called a format placeholder. And that format placeholder is percent one, which just means we're going to supply one piece of information and the first piece of information will sit right there. And so whatever temperature we have will be displayed right before the F. Now we want to format it to a single decimal place. So we're gonna add a format string here, and the format string is going to be a dollar sign 0.1 f. Now, the way this works is, we're saying Take the first piece of information, apply a format to it. We want the format to be that it contains one decimal place, and that will be a floating point number or a decimal number, and that will be important later. And then the letter F will show up afterwards. So now let's jump back over to our code and see how that would look. So the first thing we're going to do is grab the temperature value just like we did before using get Jason object to get the main object and then reaching inside that main object. But instead of getting a string, we're gonna get it as a number. We're gonna use the get double function to get. It is a double precision number, and we're going to store it in a numeric variable called temp that we create of type double . And then what we're gonna do is will create a string variable called temp formatted, and we'll use the get string function to get our format string use our dot string dot format on that works just like fine view by I D. And then we'll apply our temp variable to that format string and whatever the value of the Tim Variable is, will get put in place where the percent one is, and it will get formatted to one decimal place. So once we have that string, rather than setting our label to the value we get from the Jason object directly, we will tell it to display the result of that formatting operation. So now we'll just add a comment here above this block of code. Just a little note describing what this does would get the current temperature formatted and display it in the label. That just helps us to keep our code organized neatly. Okay, so once we have that all set up, we'll go ahead and rerun our emulator. Make sure that everything is now working according to plan will compile that. Bring her emulator backup on our emulator runs here finishes compiling. And if everything goes according to plan, there is our temperature display and we could see the currently 73.9 degrees. Now that lets us show something else over here if we stop our emulator and jump back over here. And if we change our format to use zero decimal places instead of one decimal place and we rerun that you'll see that what's happening in that format string. When the demeter display pops back up, you see that it displaced 74 degrees, not 73. That's because since the temperature is 73.9, that format string is rounding it to zero decimal places, not just cutting off 20 decimal places, so that's an important point to remember. Okay, now, if we want to make this look even fancier, we can pull up our emotions and symbols tab in back, and we can search for degrees that we could find the degrees symbol. Or we can kind of take a shortcut News degrees Fahrenheit on Windows. You can get this by holding down the altar key and typing 0176 a handy and easy to remember code. And so, if we rerun, are emulator. Now we can see that not only do we get a rounded temperature, um, formatted to zero decimal places, but we also get a nice degrees symbol in the display. So next we're going to look at adding a graphic to represent the current weather condition . 6. Fetching Weather Condition Images: So now let's work on making this a little bit nicer. If we go back to the open weather map, Baby, I we can see that in the weather results, there is an icon, and if we go up here and click on list of condition codes and then scroll up to this link, weather condition codes it with icons. You'll see if you click that that for every different weather condition, the weather AP I returns and icon code and we can use this u R L to retrieve the actual image associated with that icon you can see here. It's not that beautiful, but we'll make do with it for now, and we'll make it look better a little bit later on so you can see there's a different icon for each condition, and we're going to use a library called Glide to retrieve those icons. That makes retrieving the image really easy on Android. So to do that, just like we did with the Volley Library, we're going to go down here to the great ill dependency list and we'll just copy the current grade all dependency that we need and then go back to our project and go into our great ill scripts and find our app, cradle file and right below where we pasted the volley. Implementation will put the one for glide and then we'll click sink. Now we'll wait for that to build. And the great will sink usually takes a long time when you add a new library because it's gonna download the library all of its dependencies, we compile everything. And hopefully you should just see a bunch of little green okay, symbols indicating that there is no problem. It will take, Ah, a minute or two, depending on the speed of your system and the size of the library and its complexity. So while that's downloading, one thing we should probably do is if we go back up to the main activity, just like we had our temperature label. We do need to get a reference to this weather image, our image view, where we're gonna put our icon. So if we go back to main activity just like we did with temperature label, we can add an image you reference here. We'll call it Weather image, Chris Holt, enter or option enter to add that image you reference and then we'll get a reference to it here using fine view by i d r dot I d dot weather image, just like we did with temperature label just so we can refer to it later on in our code. Now, if we look back at the A p I for current weather data, we can see that the result we get back has a weather claws and in that that weather key the value is actually an array. That's what that square bracket represents. That's because there could be multiple weather conditions for a given area. Um, for our purposes, we're just going to grab the first condition for an area. It could be that in a real application, you'd want to do something a little smarter, like maybe grab the most severe weather condition and display that. But in our case, we're just going to display the 1st 1 first. Let's just add a little comment here, just reminding us what we're doing. We're gonna get the icon for the weather condition and display it again. This just keeps our code organized, so to get that icon name will take our response and we'll get the Jason Array and the name of that array was weather. And now we need to get the first item we could use Get here. Um, we could just say get item zero, and that would give us back the thing we want. But it would give its back to us as a generic object. And this is a Jason object. And so to save ourselves some trouble, what we can do is rather than just using, get we can just say we know what this is. It is a Jason object that we're getting out of this. And so we want the zero with Jason object that's inside the weather array. And within that object, we want to get a string whose key is called Icon. And so with a recap again, what we're going to do here is we've got this weather key and it has a value that contains an array. We're going to get a ray item zero from the weather key and that will give us this Jason object. And that Jason object has a bunch of key value pairs. And with the one we want is the string called Icon. Okay, Now we need to build are you, Earl, So we'll create an image. You are l string. If we go back to the list of conditions, codes and weather condition, code link, it tells us the u. R l We need to get that image so we'll just copy that and paste it in. Here is a string, but we don't always want image 10 d. We want whichever icon name we got back from our weather response. So what we're gonna do is use another format string, but will use this one directly in our code so you can see how that works. Using string dot format, we'll replace the 10 D with a format, specify air and notice here that we're using an S instead of an F because what's going to go into this spot is a string rather than afloat. And we're going to replace that format placeholder with our icon name that we retrieved from the response. So this icon name go in place of this percent one s right here, and that will give us the complete you earl that we need for our icon. So then we'll use the glide library in the Clyde library. We're going to first give it a context. We have to give it a contact so it knows where to find different resource is that it needs The context is where in the application the library is making this retrieval now. Usually we would use this as the context and we then tell it to load a u r l. And we'd say toe load it into ace particular image view in this case, our weather image. But you can see that it doesn't like this as a context and the reason for that If you look at this air message, it says that it cannot resolve with using the response listener of a Jason object from volley. What that means is that we're not actually inside the main activity. Technically, we're inside of a custom object we created to listen to volley responses. Do you remember when we created that volley response request? We said that we were going to create a new Jason object request, but what we want is to reference the main activity. If you remember, this is very similar to what we had to do to display our toast and are on error response, or we had to reference the outer context of the main activity. And so we can do that just by saying main activity dot This and again this just tells glide what the activity is that it's running inside off, so it knows where to find different resource is, such as the image you where we want it to below that image. So once we have that there were now all set with volley or with glide rather. So now we'll run our app. And if everything goes according to plan, we should see the great will build complete successfully and there it is. And then we should hopefully see our application pop up with the weather results, including our image, and it appears to be misty. So in our next segment, we're gonna look at making that icon look nicer. Rather than using the default icons provided by the weather. AP, I will use another set of icons that will look nicer and scale better 7. Using an Icon Font for Weather Images: So instead of using just this default image that comes from the weather AP I we're going to use an icon fought for our images. So the icon phenomena use is provided by Eric Flowers, and you can find it just searching for Eric Flowers. And this icon fund is nice, because if you scale an icon fund, you'll see that the icon gets larger without getting any blurrier. This means that you can use it with different screen sizes and resolutions without having to worry about it getting blurry or looking too small or too large. And so it's great. So we'll just download this and we'll just wait for that to download. Here we go on. Once it finishes downloading, just unzip the file, and they're going to be a whole bunch of different files inside here that you need if you're going to use this on a website. But since we're using it in an android app, the only file we need is this TTF file true type font, and we're going to need to store this in our project. So to do that, we're going to create an assets folder with that you can use in a project to hold things like images, sound files or, in our case, a fuck file. So we just right click, appear on the app and say New and go Down to Folder and Select Assets Folder. And once we do that, it will ask us which route we want to use. We'll just leave it set to Maine, and then we'll see our assets folder appear. Now. One of the things that you'll, um you'll notice about this is we can't just take this true type font file and drag it over to the Assets folder. It looks like it'll work, but it doesn't. Instead, we need to either reveal it in Finder or shown Explorer on Windows, go into the Assets folder and then copy that true type font into that folder, and then it will show up in our project. Okay, so now if we go back to our main activity, we see we've got this image view where we're holding our weather image, but we can't use an image. You toe hold a font icon because it's really just a piece of text designed to look like a picture. So we're going to get rid of that, and we'll drag a text view over here. And that's gonna hold our font cliff that we're going to use for the weather, and we'll drag to the left and right to center this on the screen. To put our layout constraints here, add one to the top of the screen that will change our margin to 32 device pixels. And then we'll drag from our text view up to our icon Cliff Holder, that we're gonna make so that that will be centered below it. And then we're going to change it. Instead of using rap content, we're going to change it to use a fixed width and height. So we'll click that and change it to 128 device pixels wide and 100 and 28 device pixels. Tallinn I Square image. Okay, once we've done that, let's replace that text view with an ex placeholder so we can just get a feel for the size and will change the text size to 96 and center it now. Right now, it just shows an X, but what we're going to do is replace that acts with a glitch from our icon font file that will represent the current weather conditions. So now we can go back to our main activity. On first, we need to change our image view referenced back to a text view. Since that that's what it is now and we'll see. Now we've got this reference up here that we had earlier this import statement for image view that turned gray. That means the compilers detected we're no longer using that code. It's always a good idea to delete code that you're not using. So we'll go ahead and delete that. And then if we go down here, we can inside of our UN response call back. We don't need to use Clyde anymore because we're not downloading in the images so we can delete all of this code. We're still going to get a Nikon, but we're going to do it differently, And that means we don't need our glide import anymore. And since we're no longer using glide at all, we can go to our app, Graito file and elite that library reference, and then we'll resync our project and that will re compile everything. Remove all the libraries were no longer using, and that's always a good idea because it just makes your final AP size. Smaller removes any unused dependencies, keeps the code clean, and we always wanted to be as easy to maintain its possible. Then if we get back to me and activity will see one more thing we need to fix now here, in our fine view by I D. It says that there is no view named Weather Image. That's because when we replaced our image view with a text view, we did not give it a ni de, and so will dis change that the weather image and it will ask if we want to change it everywhere. And we said yes. And now, once that's done, if we go back over to our main activity, I can see that air is gone and we can go down here and we can use a new method for getting our icon. So, in order to decide which icon in our icon font to use, we're gonna need one more piece of information from the a p I. So if we go back to the a p I documentation and go to the current weather data stock and the ZIP code where we've been looking before. We'll see that in the Jason response. There is a value called code and that is associated with the current weather condition. And so if we go back up to list of condition codes and then weather condition codes where we got our u. R L for our image before, if we go past that, we'll see that they're a bunch of different condition codes for each condition, and there are just lots and lots of them. But they're grouped in by the hundreds. Place of a group 300 for example, are all the different types of drizzling and group 200 all the different types of thunderstorms. So we're gonna take advantage of that grouping. And so the first thing we're gonna need to do is to grab this condition code. We noticed that this condition code is right in the root of our Jason response. It's not part of ah nested Jason object like our other values where that we've been getting so that will make it easy to retrieve. So if we go back to our code, we can create an integer variable called Weather Code and set that equal to the response, and again it's called C o D. And we'll just say response dot get int And the key name is C O D. And that's all we have to do to get that weather condition code. Okay, now, once we have that weather condition code, we're going to want to translate that into one of these icons. Now, if we look here, we can see that there are, um there's a list of different AP I map ings for different weather ap I sites where you can map between their codes and the correct icon to use. And here's the one for the open weather map. Okay, so each of these codes maps to a condition. But if we look at our font icons, we can see that each of these icons has a code of its own. This is a Unicode character code. So since this is an icon font, every one of the glitz or images in this font is associated with a specific Unicode value. Just like any other font has specific values for each of the letters numbers symbols in the fund icon Foncier no different. So what we're going to do is build a function here. Ah, that will call. Get Icahn for code and this function will take and weather condition code. And it will convert that condition code to the correct Unicode cliff code, the correct Unicode value that we need in order to retrieve the proper image from the font . Okay, so if we go back to our, um, list of different condition codes on this page, we again can see that all the thunderstorms are in group 200. All the drizzles Aaron Group 300 then we have a couple of special things like the fact that clear is 800. But we're gonna take advantage of this 100 police grouping. And to do that, we're going to get the hundreds place out of our code that we passed to this function. And for that to work will create a variable called hundreds and set it equal to code divided by 100. Now, this takes advantage of a property called into your division on what's gonna happen here is since code is an integer and 100 is an integer. When we divide those together, the result is going to be an integer as well So if the number for example, the code that's passed into this function is 735 if we were to divide that by 100 normally that the result would be 7.35 But since we're storing the result in an integer that 0.35 gets dropped and the result is just seven. And so we get just the hundreds place, which is exactly what we want. So then we can use that hundreds place to decide which Cliff to use, and to do that will use a switch statement. A switch statement allows us to look at a value and compare it to a set of pre defined cases and then do something based on which case it falls under. So, for example, if the hundreds place matches, um, the number two So case number two, what we're going to dio is returning cliff for thunderstorm. And so if we look at our list of glitz, we see a bunch of different pictures, and we'll just pick this one, the Daytime Lightning one. It will copy that Unicode value and will return it as a string and notice we prefix it with a slash you, which just indicates that it is a Unicode string. Now this gives us an error because when we created our function, we defined it as avoid return type. But we're trying to return a string, so we just need to change this to be a string function. So once we have that, then we can create another case for hundreds place number three. And if we go back here, we can see that three is our goal. Are different types of drizzling and so we can just find an icon that looks appropriate for drizzling Andi. Maybe we'll choose this one. The daytime Sprinkle icon. You don't have to use the same icons. You can use any icons you want. Just make sure you prefix it with the slash you and then we'll do Case for and case four will be just like we don't have a case for, so we'll go right to case five. Case five is just regular raining so regular raining, we'll grab the daytime rain icon. Change that to case five because 400 seems to be missing in action and then will go on to K six and K six is snow so we'll find a good icon for snow. This looks like a good one. Daytime snow, and so we'll copy that value. And you can kind of see the pattern we're going through here. Andi, Finally, we've got Case seven atmospheric conditions, a wide range of things that can affect the atmospheric visibilities that we'll just grab the fog icon. We use that value. So Case seven. Return the Unicode value for fog. Now, if we go back here, we'll see that we have case Aitken both mean clear and cloudy. So let's find a good icon here, for there is a good one for cloudy. The daytime, cloudy icons that will grab that and what we'll do is we'll return that for all case eights . But since that doesn't work for clear, if you remember, clear is code 800 which doesn't really match the cloudy group. It's just kind of a separate thing, so we'll add that as a a special case. Okay, so any time we have a special case will just handle it separately, and we'll just say if the code is equal to 800 then we specifically want to return and we'll find a nice icon for clear. We'll return this code so special cases will handle here. And let's add one more, um, special case. And if we look back at our atmospheric conditions, for example, Tornado seems like it should have its own icon not just look like fog. So will return, um, that appropriate icon for tornadoes. If we stroll down to the neutral section, there's a tornado icon will grab that one. And you can add as many special cases as you want anytime you feel like it doesn't fit. Is that one more? Um, about volcano? Volcano erupts. You probably want to know. So for Coach 7 62 we will find is an icon here for Volcano, Hopefully not a very common weather condition. And so these are all our special cases. Um, so if it matches a special case, exactly, then we'll use these specific icons. Otherwise, we will handle the general cases by just looking at the hundreds place and returning one of these more generic icons for each group and then by default. If we've got a code that's kind of just different from everything else, will just return this cloud by default. And there all right. So with that function defined, we are now ready to translate our code into a Unicode left. We go back down here, we can create a string variable, and we'll call it icon symbol, and we'll set it equal to the result of calling this function and passing in our weather code. So we're gonna take the weather code that we get back from our risk, Jason response and get that is an integer will pass it to our get icon for code function, and that will give us the correct Unicode symbol to use for our icon. So the final step here is we're going to take our weather image text view and set the text to be the Unicode symbol that we got from our function. And so now we will run our code and let that build switch back over to our emulator. And we see we've got a problem because the symbol shows up as this square with an extra, which is the symbol of fought uses when it does not know what the correct cliff is for a value specified. And the reason that happens if we go back to our designer, we can see that the font family is a generic Sand Sarah family, and so what we need to do is tell our text for you to use the correct font. Unfortunately, that font does not show up in our list because it's not a device fund and even though it shows up here in the Assets folder, so since it's an asset, we need to do something slightly different to make this work. So if we go back to our main activity, we will first at a reference to a typeface, and we'll call that tight face, whether font and all to enter or option enter to add that reference. And then, just like we do with fine view by I D will get a reference to our font. We're going to create a typeface from Asset and we'll get our assets folder, and we specify the name or path to the asset within that folder, which is just the name of our font file. And make sure that matches exactly what it shows in the Assets folder and then, once we have a reference to the actual font, will take our weather image and will set its typeface to that font reference. And so now that will happen in the on create function. So if we rerun our code and pop up our emulator, we'll see that now. When the code runs, we send it that Unicode value. And since it has the correct font, it displays the correct cliff and so we can see that has scaled nicely. It's not blurry or jagged, and that's because it's an icon font, which means it can scale to any size without losing any resolution. And so in our next segment, we're going Teoh modify our app so that rather than showing always the weather from one location, we will enter the location that we want to retrieve the weather for. 8. Getting the Location from the User: All right, so next what we're gonna do is go over to our main activity, and we can see that where we're specifying the zip code as part of the URL. We want to replace this and let the user type that in. So to make that happen, we need to build the user interface for it first. So in order to do that, we'll go back to our activity layout stream, and we'll have a text field, a plain text and just drag it here to the bottom. That's where they'll type the zip code, and then we'll get a button, and that's what they'll click to look up the weather. So for our layout constraints, what we want to do is center the east to controls at the bottom of the screen. So the do that we're going to set up a series of constraints. First, we will connect the left side of this control and in the bottom, and then we'll go to the button and connect the right side. But instead of doing the bottom to the bottom, but we're gonna do is connect the baseline of this control by clicking this button to the baseline of this control this way, the bottom of their text line up rather than the bottom of their control margins and that I looked a little bit nicer. Now this could be a little bit tricky to connect. So if it doesn't work the first time, um, just go and try again. And there we go. You can see the bottom of the tax lineup. So now we're going to connect the sides of the controls to one another. So we'll connect the right side of the text field to the button. But you can see we can't connect the button directly to the text field now because that strength is already being used. And so will go up here to the upper right to the constraint. Visualize er well, just click this plus button to manually attic it straight. You can see this constraint has changed to a chained, which means that those air bound together side by side and then we'll just change this margin from 36 to 0, and we'll click here and change this margin to zero so that these air now going to be centered with equal space between each other and then if we switch the landscape, you can see that how those stay centered, no matter what the orientation is. And so that's Ah, way to center, to controls on the bottom, which is what we want for these. Okay, now let's give this button and I d. We'll call it search button so that we can refer to it in our code. It will change the text just from just button to say Search, And then we'll give our text field and I d on this is gonna be ours Kotex and will erase the text from it. And rather than supplying, text will give it a hint. A hint is that kind of grade out text that disappears when you start typing, and it just tells you what you should type in the field. And so we'll type enter Zip codes of the user knows they're supposed to type their zip code there, And so that's everything we need for the user interface and we'll switch back over to our main activity and we'll get references to those two controls. We just added, All right, so now we'll go back over to our main activity. Those references at a text will call it sip code text. No, I don't enter at that reference, and we'll do the same thing for our button hole to enter or option inter again, depending on if you're on Mac or windows and at a search button variable and then we'll go through the same routine we will do you find view by i d. Passing the I d of those fields that we created to get references to both of those is search button on view by i D Pass in the I. D to the search button feel on. And now we've got references to both our ZIP code text in our search button. Next thing we want to do is make it so that our search button, when it's clicked, will execute the code necessary to retrieve the weather update. So to do that, we're going to use an on click listener. So will your search button, and we'll add and on Click Listener on will use that same keyboard shortcut auto complete that that we used in previous videos, and this code will be executed when the button is clicked. That search. But so when that button is clicked, we want to do two things. First, we want to get the ZIP code from thes co text field. So we'll grab that text it stored a string variable and convert it to a string because it comes out as a character sequence and we want to pass that zip code to this function to our update weather function. Just like we passed our condition code to our get icon function. We're gonna pass our ZIP code as a string because not all zip codes are America. And then we will execute our update weather function passed in the zip code here, and we'll delete that other call to update weather. So now when the button is clicked, will get the zip code and fix that upper cases. So we'll get our zip code and pass it to our update weather function, and it will go into this variable. So when that happens, what we want to do now is use a format string to insert that zip code, just like we've used format strings previously. So we will, instead of having this sip code every time, we will use a format placeholder, a string format, and then we will pass along zip code variable that we get in our function so that will be inserted into this string at that location, just like other format placeholders reviews. So if we run our app, we could see that in action. Bring up our emulator and type in a zip code nine of low 36 search. You can see the weather there changed, showing the weather for that zip code. And then we can show we do another zip code 24579 It's searching. Saw that temperature change to the weather condition, for that's it. Go. So now what we want to do is make it so that when you typed zip code, it is remembered between obsessions so that if you quit the app and restart, it will remember the last zip code that you entered and it will automatically retrieve the weather for that location. So to do that, we're gonna use the shared preferences feature of android Shared preferences is a set of key value pairs stored in a dictionary like object on, uh, in your device memory that allows you to store different values. Uh, and that persists between different sessions of your app for times that you run it. So in order to do that, first thing we need to do is we will create a shared preferences reference here, and we'll just say, get preferences and we will ask for the private preferences that air specific for this activity. And then we will create a shared preferences editor Press Ault Inter to add that reference and that'll allow us to change preferences once we have that editor, Then we can say we're going to store a string and weaken store different types, but we're gonna store a string and the string we're gonna store. We need to give it a key and name to store that value. But rather than typing it directly, we're gonna use what's called a string Const. This will allow us to make sure we never make any spelling mistakes or setting and retrieving the key. So we'll do that by coming up here to the sort of class variables it will create a static string. That means it will be part of the class and we'll just call it zip code, and we'll just set it equal to a value called zip code. Now it doesn't matter what the actual value is as long as it's unique. And by convention, we use upper case for string. Constance. So we're using, uh, zip code for that. So we will use that reference here for the key, and then the value will be whatever than the zip code variable. Then, to finalize that we will call the apply function is also a commit function, but applies offered way to do it amount modern android development. So we will apply that which will save that value to our preferences. So now what we want to do is whenever we run the app first time we want to check and see if we have ah saved zip code already. So to do that, you will get a reference to shared preferences again using the same, uh, context mode private, no private you. And then we will create a string and will zip code and will say, get string and we'll retrieve it based on that zip code static, constant passing the key. And then we have to specify what the default value should be if the key doesn't exist. But no. And then we can say if the zip code doesn't equal No. That means if we do have a zip code, then go ahead and fetch the weather for that zip code. So that code will launch Will run as soon as the application, uh, fix that case that doesn't like over K zip code. So this code will run as soon as the application launches. And it's OK that these air named the same thing because this variable since its inside this on click listener and inside another function within that that's actually in a different scope. So those won't, uh, harm each other. So then we can just run our activity. And if we have a ZIP code saved in our shared preferences, will get that zip code and we'll call update weather. Now let's test this. We'll run our app. Type in the code. Let's do do 3452345 brother. And we see that comes up in 84 degrees thunderstorm. Now we will quit our app singly, remove it from memory and then stop on. Then if we re launch are up and what we should see is the APP will come up with the zip code. The weather conditions for that zip code preloaded because it's gonna fetch that weather condition from the last zip code we entered before we quit. So now in our final segment, we will look at some ways that we can make this look and behave a little bit smoother on just have a better overall visual appearance. 9. Refining the User Experience: So in this final video, we're gonna make our application look nicer. And the first thing we're gonna do is increase the size of our weather icon rather than 1 28 Let's double that size, and I get to 56 both for with and for the height. And now let's change the size of that font to better fill The box will just keep modifying this number until we get it just right just centered. Maybe 1 80 a little bit lower 1 74 There we go that looks nice and centered. And then let's get rid of this text view placeholders. So when we launch the app, you seen that there's kind of this flash of content is it's It's commonly referred to where it says text view, and we've been leaving that in there because it makes our text you easier to visualize in the designer. But we don't want that to show the words text view. When the at first loads, you could replace it with something like loading or some other indication that the APP is still not hasn't acquired all of its data yet, but we're just gonna go ahead and delete it. And now when we do notice that kind of disappears from sight, it shrinks because we have the layout with set to wrap content. And when that happens, that means that if there's no continent there, the with shrinks to zero. But if you go over here to the component tree, you can still select that control just by clicking it here. Okay, so even if it's not visible, you can always select those. Now. Let's change that text size will make it a little bigger. And let's add one more text view, um, to display our location Name will just center that right below and to the center, to the left and right to the parent. So that will be in the center of the screen right below the temperature. And we'll just call this location text. We'll just put the name of the location there. So one other change we can make is let's imagine that this application is designed just for areas where the zip code is numeric. If we wanted to, we could change for this sip code entry field. If we select the input type and remove text, person, name and select number This means that when the keyboard pops up, it would just allow us to enter numbers. And let's get rid of this place holder for our icon as well. And well, just will leave this last one from our location and go back to main activity. And let's get a reference to that text you will create a variable appeared just like we did with our other control variables. And then we'll use but location, tax equals find view by I. D. And we will add are reference there and go back down to the update weather response. And here will get the location four our zip code, and we go back to our A p I and scroll down to our zip code. Jason response. We can see that if we look through this response tax down here at the bottom is a name associated with that zip code. And so we're gonna grab that name the value associated with the name key. So we go back here, I create a string variable, call it location, set it equal to respond, stop, get string. And again, the key is name. And so that will give us the name of the location, just like we did with Temperature. Will set location, tax call set texts and pass in that location string. Okay, so let's then run our application and see what that looks like. Bring up the emulator and that build finished. And when the emulator loads, the APP noticed there's no content there and then the icon appears, and it's nice and big. The temperature and the location name are still a little small, so let's go back here and adjust those again. I'll select it from the component tree on and let's change temperature label. We'll bump that text size up to 52 and the ZIP code text rather than location text. We will change that, too. 20. Yeah, 20 on Run that again and but our emulator load. And once that appears, we can see that's nice and big. And if we tap the zip code field we see now we just get a numeric keyboard, and as we type that in and hit search, we can see the location, name and the temperature chained 10. Conclusion / Next Steps: Congratulations. You just finished your very own weather app on Android. Now you can use it to predict the weather wherever you go or show off to your friends there . Lots of opportunities for customization. With this app, you can change the colors and fonts. And since we're using an icon font for the weather images, you can change the colors and sizes of those images as well without losing any quality. There are other things you can do as well. For example, instead of grouping weather condition by the hundreds place, you can show different icons for each type of drizzle or each type of thunderstorm. You could also use the different FBI endpoint, such as this one, which allows you to look up weather conditions by city and country code rather than by zip code. You'll just need to modify your user interface to allow the user to type in a city rather than a zip code. And make sure that you modify your Jason response sparser so that you're pulling out the correct information from the response. For this in point, you might also have noticed. Is there other AP I in points such as the five day in three hour forecast in point. You can use this to get long term forecast information. You could add extra user interface elements to your app and use those to display the long term forecast. There are lots of possibilities for customization. If you do something interesting, post screenshots of your app on the class so that we can all see it. The great thing about the skills you've learned in building this app is that they work not just for this weather a b I, but for any AP high that provides Jason data and there are lots of them. So check out what other AP eyes air available and see what other APS you can build.