Introduction to Web Services in Android using the Flickr API (Part 2/2)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and welcome back in a previous video we wrote some starter code for a project called web services fun that is an android app that fetches interesting photo information and source images from the flickr api if you go to flickr.com explorer you can see the interesting photos of the day and these are the photos that we're going to request and display in our app so that we can appreciate these beautiful photos in our android app now a little bit of an overview from last video of how apis work our app has to create a request to an api server if the request looks good the server will essentially package up the data that we requested and send it back to us as a response we then need to parse that response all of this can take some time it might be less than a second it might be a couple seconds it could be even longer and for that reason we don't want to run this code that makes the request and parts of the response on what's called the main ui thread that keeps our interface live and updated and responsive for our user because if we do we could overload it and then we'll essentially have a ui that hangs or freezes and that's not a good user experience so that means we need to learn a little bit about threading if you're not familiar with reading no worries here's a super high level overview of a thread a thread is essentially a sequence of code that executes inside of an existing process here's a simple diagram of a process that contains two threads the threads over time are scheduled as the process is scheduled by alternating and completing different tasks the threads are essentially alternating so fast and the process is being scheduled with other processes on your cpu or cpu so fast that if this is all set up properly then the user is not even going to notice that essentially our ui thread and our background thread our alternating execution really really really really fast so our goal then is to learn a little bit about background tasks and how we can set them up to run on a different thread so that our main ui doesn't freeze up while we're trying to make this request and parse its response to do this we're going to use what's called the async task class from android this was added in api level 3 and i'll note that it was deprecated in api level 30 at the time of this video recording the current api level is 31 that just came out about a month ago or so so this really was recently deprecated i believe this deprecation is part of a larger movement to try and get people off of java and onto kotlin for android development because if you look here it says use the standard java.util.concurrent or kotlin concurrency utilities instead well we don't want to use java.util.concurrent what we want to do in the future is move over to kotlin so let's use asynctask it'll work just fine for demonstration purposes and learning as we essentially close out our java usage in android and start migrating to kotlin for these better concurrency utilities anyways these ones are really really really little so i'm going to head back to our source code here's where we left off last video we had just created a flickr api object and called fetch interesting photos which is going to essentially create the request make the request get the response back and parse the response here's the fetch interesting photos we have just created the url we printed it out to logcat we opened it in google chrome or your favorite web browser and we were confident that our url is correct because we were getting json data back and the data that contained was the photo information we wanted like the title the date taken an id url etc so let's take a little bit of notes about what we have to do here next essentially we have to start a background task to touch the photos for reasons i just mentioned even if we wanted to do this on the main ui thread android wouldn't let us we actually have to use a background task anyways so it's good practice so our ui thread doesn't get overloaded and frees up but it's also required if our background task we want to run involves doing anything with network activity so android will not let you do any network activity which is what we're doing when we're using the internet to make a request and get a response back on the main ui thread so what we do is we define a subclass of that abstract async task class that i just showed you in the documentation async is short for asynchronous which essentially means that the code that calls the async task to start executing is not going to block or wait for a response back it's going to start it on another thread and then carry on with what it needs to keep on carry on doing so asynchronous means doesn't wait or block i'll start it on another thread and then the main ui thread will continue doing its main ui thread things so i'm going to scroll down just a little bit here and i'm going to make this class i'm going to call it fetch interesting photo list async task which is kind of long and a mouthful i know but we're really descriptive about what this class is going to do it is going to be a subclass of async task which has three parameterized types the first one will be a string which represents the type of the arguments that are going to come into our essentially execute method next is going to be a type that represents how we're going to update our progress to the user we aren't going to update progress to our user in terms of like measurable chunks like you know fifty percent of one hundred percent or uh five megs of ten megs or something like this we'll just show an indeterminate progress bar which is essentially a circular spinner that just keeps spinning while we're doing something in the background and then the last parameterized type here is going to be what we're going to return to code on our main ui thread for displaying or using once this async task is done and successful so that is going to be a list of interesting photo objects which we have not declared yet so let's do that right click on our package new java class interesting photo interesting photo is going to be a class to represent the minimum information that we need for an interesting photo from flickr in order to display content in our app for our user so this includes a string id a string for the title a string for the date taken and a string for the photo url and then from here i'm simply going to stub out the rest of this class meaning an explicit value constructor a two-string getters and setters with the intellij shortcuts awesome i'm going to import java.util.list and then this is not compiling because there's one abstract method that we have to have which is called do it background so let's add that do in background and now our code compiles do in background is essentially the method that executes when we call execute on a fetch interesting photo list asynctask object we're going to pass in a list of strings for us so it'll just be one which will be our url and those are going to come in as what are called var args or variable arguments which we can essentially just treat like an array so let me make a few notes in here so fetch interesting photo list async task is a subclass of async task which executes on a background thread we cannot update anything on the ui thread like our uis our ui elements like our text views our image views etc unless we are in the appropriate async task method which we will see here momentarily due in background as the name implies is going to run on the background thread we cannot update the main ui thread from this method so in this doing background we're going to do three things the first thing we're going to do is open the url request the second thing is download the json response the third thing is parse the json response into interesting photo objects we'll put all those object references into a list and that's what we will return you know this is what we're going to return because look at the return type for doing background this came from our third parameterized type on our header here so let's call this method here's five interesting photos we will make a fetch interesting photo listasynctask object then we'll call asynctask.execute we don't call doing background we call execute and then all the proper thread memory etc is set up for us so we'll call execute and we can pass in a variable number of string parameters because that was the first parameterized type on our fetch interesting photo list async task header for us all we're going to do is pass in url so this will be the string at element 0 in our var args right here in doing background so let's grab it and i can make a little note here the string dot dot is called bar args and we can treat it like an array for a variable number of arguments so we'll grab the url our goal is to produce a list of interesting photo objects so let's create that list hoping everything goes well and we're able to return it so let's create a java.net.url object to represent our url that currently is a string this can throw an exception so we'll need to add a try catch block to correct to catch a malformed url exception in case the string we pass in is not actually a valid url it can't be parsed into our url once we have a url object then we can pass that in to or excuse me we can call openconnection on that url object in order to attempt to get a http url connection so http and we can use https by the way because if you look at our our url we're actually using https so we'll use https url connection url object here's the key part here dot open connection so open a connection to this url using https so this can also throw an exception that's where we're getting an error here so we'll add a catch clause for i o exception in case we're not able to connect to this url this could happen if for example internet is down now that we have the url connection what we want to do is attempt step number two which is download the json response so for right here we didn't end up in the second catch and we can attempt to download the json response so we'll get a string from the response we'll have to build this up character by character there are libraries out there that make this easier to do but we're just going to use the standard libraries to do it so it'll feel a little clunky but we'll get through it we're going to build the json string from an input stream so let's get the input stream so we'll do url connection dot get input stream so this will block and wait essentially for the input stream to be initialized and connected and then we'll need an input stream reader in order to read from the input stream [Applause] and now let's attempt to read data from the input stream reader so we'll call read which returns a single character if this fails then data will store negative one so while data is not equal to negative one we'll do json result plus a sign type casting that integer to a char building up our string character by character and then here's our progress towards our boolean condition being false so let's write this string out to logcat and make sure that it looks good we should match what we saw in the browser when we open this url with chrome in our logcat it takes a little bit of time which is why we're running it on a background thread there it is and look it matches exactly what we saw in chrome so here's our photos root object there are five pages we have data for the first page with 100 interesting photos per page and then here are the interesting photos themselves this is what we want to parse out we want to get this photo array and then go through each single photo object grab its id grab its title grab its date taken and grab its url underscore h which is right here so that's our next big task so now if we're here we were successfully able to get a json result and what we want to do is now parse the json so we'll use json object or json the package we'll create a json object from this string this will be nice because though we can call methods on the json object like git json object get json array etc this can also throw an exception so we've got to add another catch clause here so we'll add a json exception if this is not actually a valid json string then we won't be able to parse the json object from it okay so here with json object now what we want to do is first grab that root photos json object the one right here to get this json object so another json object i'll call this photos object okay now we have the photos object from the photos object i want to get the photo array so this will be a json array so just to be really clear i'm not making up these strings here in the first case photos is the key i see that from the json and the second case photo is the key and it's interesting because photo gives us the array of photos even though it's named singular so we have to look at the json response in order to know what keys we put in here now with the photo array we can walk through each photo object in the photo array and attempt to parse out an interesting photo object truly the interesting photo type that we created earlier and then put it into our list and then return the list so in here we'll grab the single json object for a photo grab the json object add index i and then try to parse a single photos info let's write a method to do this and call it parse interesting photo passing in our single photo object and if anything goes wrong in this method as we attempt to parse out our needed data we'll just return null so we should check to make sure that we were able to get all of our information by testing the interesting photo is not null from this method we're going to write here in a moment if it's not then awesome we can add this to our list and we will return this list right down here so let's define this method here it's going to return an interesting photo hopefully it will return null on failure we'll pass in a single photo object represented as a json object like i said if anything goes wrong we'll just return null and a lot of things can go wrong we're going to be calling get string on our single photo object if we pass in a key that is not actually in the interesting photo for whatever reason the most likely reason this would be would be our url h that we requested is not available for this particular photo then a json exception is going to be thrown what would be good is to uh you know print out stack trace and or try to request a different url what we will do is nothing if we can't get all four pieces of information that we need from an interesting photo then we'll just skip this photo there'll be lots of other photos that we can display and we'll see how many out of the 100 that we can successfully parse but if this was a production application then we should try to do something here to recover so let's start with the id we don't really need the id because we're not going to display it in our ui but it's always good to store the id in case we needed it later for for perhaps we're trying to request a different url or trying to do something with it it's just good practice to get the id because it's unique identifier there could be overlapping titles or date takens but the id will always be unique so it's always good practice to grab that so we'll try to get a string id okay and i'm just grabbing this string right here out of the first elements keys so id next we'll grab title next we'll grab date taken and this one's tricky because when we constructed our url scroll up a little bit here date taken had an underscore here but in the response date taken doesn't have an underscore so that's why it's always important to read the documentation and look at the json that you're attempting to parse and that's where that pretty printer can come in handy too and then last but certainly not least url underscore h so this is the one that's most likely to fail this line here if the url underscore age isn't available for this particular image so if we can get this awesome then we got all four pieces of information we need in order to create an interesting photo object scrolling up a bit here here's where we're calling parse interesting photo adding it to the list if it's not null meaning we're able to grab all four strings that we need from the object the return type on this do and background is list interesting photo which is what we're returning right here so where does this go if we head back to the asynchronous task reference on the android documentation there are four steps when an asean's task is executed the task goes through four steps on pre-execute which we did not override due in background which we did override on progress update which we didn't override and on post execute which we didn't override what's interesting is do in background returns a value that value is the result of doing background and it's going to be the parameter to on post execute onpostexecute is a method that runs on the ui thread after the background computation finishes and like i just said the result of the background computation is passed to this step as a parameter so result which is our third return type and our three parameterized types right here list interesting photo this is going to be the parameter type for our last method here in the four steps on post execute the only one of these four you have to override is doing background because it's abstract so if you don't need one two or three or two one three or four then you don't have to override them but we do need four because the result from doing background is the parameter to onpost execute which runs on the main ui thread which is where we can essentially call our main activity a callback and essentially pass it back so inside of our asynctask subclass i'm going to bring up our override methods again grab on post execute notice how it autofilled to have our parameter type be a list of interesting photo this will be a reference to this list right here so what do we want to do here let's do two things let's first write out a log message with interesting photos dot size so we can see how many that we can successfully parse out hopefully it's close to 100 and then we've got a reference to main activity so let's call a method that we'll write here in a moment called receive interesting photos and we'll pass in interesting photos this will be a callback method essentially a main activity that we call to say hey main activity we're done with the background work here's the interesting photos you asked for for a while back now you can do something with them in main activity let's write this method let's run this and let's see how many interesting photos we get remember this takes a little bit of time here we are on post execute so we were successfully able to parse 91 photos which is awesome we don't have the actual source images yet for them we just have their urls but we can at least start some work and main activity here in order to show the title and the date taken and on fab floating action button click be able to flip through them and then the last thing we'll have to do is go fetch essentially the source image from the urlh for each current photo we will do that last so i'm going to head up to the top of main activity and i'm going to add two attributes here i'll do a list of interesting photo objects and i'm also going to add an integer called current photo index which will start out as negative one this will represent where in this list we currently are displaying a photo to the user so in receive interesting photos i'm going to set this dot interesting photo list to the parameter interesting photo list and then i'm going to call a method called next photo which is essentially going to do all the work to set up our ui to display the next photo i'll also call next photo from our floating action button on click listener so that whenever the user presses the fab next photo will execute and this will set up everything we need to display the next photo so let's do a little bit of checking here if the interesting photo list is not null meaning we were successfully able to parse some interesting photos and the interesting photo list dot size is greater than zero so it's not empty then what we want to do is increment our current photo index if we started at negative one then this first call right here will bring current photo index to zero which will be our first valid index we have 91 photos currently but on any you know given day we could have a different number so if the user ever clicks through all of them and truly gets to 91 as an index then we should wrap this around to zero so i'm just going to update curve photo index to mod by interesting photo list dot size that way like i said if they ever get to the end of our list we'll just wrap it around to zero i'm gonna get references now to our title text view and our date taken text view that we set up in a previous video in our constraint layout [Applause] grab the interesting photo add index curve photo in it current photo index and now update the title text view and the date taken text view make a little to-do here so we don't forget come back and add support to fetch the source image using interesting photo dot get photo url that'll be the url underscore h string that we parsed out over in flickr api let's try this like i said right now we're not have any support for seeing the actual photo images themselves but we should be able to flip through and see the title and date taken for all 91 images we're able to parse out right now looks like it's done let's take a look so there it is atomic explored number one that's the title and then here's the date taken and i can click on my floating action button and flip through and see all 91 titles and date takens so far so good let's do one more thing before we move on to our last to do here back in flickr api we've overridden on post execute and do in background we can also override on pre-execute which is invoked on the ui thread before the task is executed this step is normally used to set up the task for instance showing a progress bar in the user interface this is exactly what we want to do we want to show a progress bar in the user interface while our doing background is executing so we can bookend do a background with onpreexecute which runs on the ui thread we'll show a progress bar and we can bookend on the other side do a background with on post execute where we can remove the progress bar because this runs on the main ui thread if you're interested i put a link to material design on progress indicators so you can take a look at all the different progress bar options that we have out there we'll use a simple one which is a simple indeterminate circular progress bar so it'll look like this a circular indicator and it's indeterminate because there's essentially an unspecified amount of wait time we don't know how long it's going to take to make the request so therefore the progress isn't detectable and it's also not necessary to indicate how long the activity will take if you have essentially progress that is detectable and you know how long it will take then you should use a determinant indicator which essentially goes from 0 to 100 and if you want to do this then asynctask has a step step three with a method on progress update where you can essentially publish your progress to the main ui thread so that's kind of fun something to take a look at if you're interested so let's add a progress bar i'm going to go back to our constraint layout here i am going to drop out of this presenter view in order to add our progress bar because with the design editor sometimes everything is just a little too big to show on my laptop so let's find a progress bar here's our circular one we can drag it out and we need to constrain it so i'm going to head up to the constraint widget and we can simply constrain it to just be centered over our image view that would be easy to do and it looks like some of these went to the parent so i'm just going to drop down into xml real quick here and fix this so i want top to top of image view start to start of image view end to end of image view and bottom to bottom of image view and see how that looks awesome so it looks like it's going to be centered over our image view and now the only thing left to do is give it a nice id so i'll just call it progress bar and head down to visibility or head over to xml and set android visibility attribute to be gone i don't want it to be displayed until onpre-execute executes in my flickr api fetch interesting photo list async task so i'm going to override onpre execute this executes on the main ui thread so i can safely get a reference to that progress bar this will be mainactivity.find view by id progress bar dot set visibility to visible now i need to do this same thing in on post execute but i need to make its visibility back to gone probably do this after main activity has updated so i'm going to launch this and then immediately head over so we can see that progress indicator looks like it's spinning and as soon as we get all 91 of our photos parsed then it should go away and it looks like it did awesome we are so close to being done all we have to do now is fetch the photo the true photo source image whenever we flip through to the next photo so that's the to do that i left in main activity right here essentially the game plan for this is to define another asynchronous task subclass attempt to get a bitmap that represents the image from the server and then display that bitmap in our image view rather than deriving that code i'm going to simply paste it in i'll explain it and then we'll run it and we'll be done with web services fun so let me go ahead and grab that and move it in to the project i've just pasted the rest of the code we need to finish the app to add support to fetch the source image so what i did here in our next photo method is i created a new flickr api object and i called fetch photo bitmap passing in interestingphoto.getphoto url which is the current interesting photo we're about to display to the user so let me show you that method here it is fetch photo bitmap we've got a string for a url i create a new photo request async task and call execute passing in photo url following the same template that we did earlier for this big big big class up here called fetch interesting photo list async task so here's the class on pre-execute i show the progress bar again on post execute i remove the progress bar doing background attempts to open an http url connection for that url i've got an input stream here and i just use this convenience method decode stream from bitmap factory to get a bitmap and if everything goes well i return bitmap otherwise i return null down here and on post execute here's a reference to that bitmap that hopefully isn't null if everything went well i passed this bitmap reference to a callback and main activity called received photo bitmap and then over here in receive photo bitmap this is where i have the reference i grab a reference to the image view and then i use the bitmap reference to set the image views image bitmap so let's run this and see the whole app in all of its glory so here it is we've got the progress indicator spinning while we are fetching all of those interesting photos information as json objects when we get the first one in addition to seeing the title and date taken like we saw earlier we should also see the image there it is so let's flip through a few more of them now as i flip through them notice that there's a brief amount of time where i'm showing the progress indicator while we're fetching the next photo but it really doesn't take all that long to download that bitmap so there they are we did a lot in this video and the previous video where we did our setup and created our url essentially the big picture is this there are servers out there that are running services for third-party developers and applications like ourselves to make requests for content now if we read the documentation for that service we can figure out how to structure a request such that it's valid and we can get a response back with whatever content data we want we have to parse that response like we did with all that json work in order to get it in a form that we can then use in our app but this is essentially how a lot of apps are built apis are building blocks and you can piece them together to make your app highly functional without needing to reinvent the wheel so think about services like google maps how many apps have google maps in it that aren't essentially written or maintained by google a lot that's because google maps has an api it also has often an sdk software development kit for developers to use to incorporate that app services into their own app so really like i said apis are the building blocks of building apps with a lot of functionality and with this in your back pocket i encourage you to go to a github repo called github.com public apis public apis because this is a really great place to get started working with apis it's essentially a crowdsourced list of free apis for use in software and web development and it's got a really nice table of contents with all these different categories so for example if you're interested in blockchain you can see all of these apis available to the public that you can use to start making requests for information about blockchain just using that as an example so take a look here to get some great ideas for how you can increase the functionality in your app by using existing services out there via their apis that's it thanks for watching and please subscribe to see more awesome videos like this to help you with your software development thank you
Info
Channel: Gina Sprint
Views: 132
Rating: undefined out of 5
Keywords:
Id: uEjtA8M1KZ0
Channel Id: undefined
Length: 44min 3sec (2643 seconds)
Published: Mon Nov 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.