How to Build a Simple REST API With Ktor + Android App

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome back to a new video in this video i'm going to teach you how you can build a simple k2r rest api if you don't know what k2 is that is a kotlin only backend framework which is really cool it combines all these cool kotlin language features like extension functions proteins all that stuff into one back-end and if you love kotlin you will love k-tour i promise you in this video i just want to show you how to build a simple api with that you can already see a little bit we're going to build a rabbit's api so essentially this api will just serve us with some rabbit images that you can choose with some information about these rabbits and we can click on new rabbit to get um information about them about a new rabbit about random rabbit um i think it just shows yeah the same rabbit again you can see we have some some other rabbits here we can actually uh click through and yeah you feel free to extend this list of rabbits i only have five rabbits in here and the api will just respond with random one of these so i will show you everything here how you can build the api that responds with that and also how to build the android app here using jetpack compose to actually display that and retrieve the data using retrofit so without further ado let's jump right into it and we're going to start building the api the api isn't built in android studio instead we built it in intellij that is also a jetbrains ide and i think most of you will have it if you don't have it um you can simply just google intellij download so let's just do that intellij download download intellij and yeah you just want to download this community edition that is free um you gotta set it up with the jdk if you need a tutorial for that um i won't show you in this in this video but you can check the first i think the first video or the second video of my kotlin ub2 pro playlist in which i actually actually show how you can set up this id if you've done that if you have installed intellij idea you want to go to you want to open a new browser tab and you want to go to start.ktor.io because skater projects have some specifics and a specific project structure kind of um we kind of need a project generator for that in the past there was a plugin in that in in intellij um with which we could easily create that project the plugin still exists but it is marked as obsolete so i wouldn't use that anymore or if you actually have access to intellij ultimate the paid version but as a student you get access for free i think um then you can also use that because in that ultimate edition the project generator for k2 is already integrated as far as i know but i only have the community edition so we can just use this free website to generate our project and then simply open it in intellij so let's go through this step by step first of all our project name well that is pretty obvious what we need to enter here just something like ktor rabbits and then we can extend this here and click adjust project settings and we can we can actually set up a little bit more first of all we can choose a build system so from android you know gradle groovy but for caterer i like to choose the the kotlin dsl version of gradle which is just a little bit cooler it's more kotlin-ish or you could also choose maven but i like these two more because i'm used to these from android apps then the website um that's basically just the the first part of your package game in android so you can just say plcoding.com for example and then you can see this is how your package will end up being called you can choose a caterer version um which you should just choose the latest one here you can choose an engine here which is netty and yeah you can choose some others the engine is basically what drives cater so if you know retrofit then for retrofit the engine would kind of be ok http what makes the actual network requests that retrofit is a layer on top of okay http that just makes everything easier and it's the same way with caterer and these engines so these engines do the actual work behind the scenes but cater is just a framework on top of that that we can easily use to um actually yeah build our backend and we can choose configuration in and right now it says hokan file maybe it says code for you so there are two different ways we can actually put our server configuration in on the one hand that is such a hoe con file it's very similar to json just a very jsonish style of defining configurations or you could simply put it in your kotlin code i like the token file so i would advise you to choose the same if you want to follow along and then we're actually not done yet because you can see there is an add plugins button i'm going to click that so what are these plugins ktor is almost fully built with these plugins so these plugins kind of allow us specific back-end behavior that we typically want to use in back-end frameworks so you can see we can we can just see all the the available plugins here for example authentication so if you want to have some authentication mechanisms like logging in users like distinguishing between normal users and admins then you want to add some plugins here from security you can simply click add and then it will be included in your caterer service setup if you don't do that then of course you can still add this later this will basically just add a dependency and some default setup and you can also do that later if you encounter that you forgot something and you just need something else here so you can add sessions auto head responses all that stuff what we want is routing of course so routing just allows us to define routes at which we respond with something in our case with the rabbit data then we also want to add static content that means we have some static files that we already know um we don't need to know these but we have some some really real files that we actually want to respond with at certain routes so that is typically for using or responding with images you can respond with any files also text files pdfs but we use it here to display images so our app can actually call a specific route like a localhost report slash rabbit.jpg and actually access the image there so we click add as well um you can yeah we don't need status pages that is used to simply throw an exception in your code and your your server will automatically respond with a certain exception so you could for example throw an unauthorized exception somewhere in your route and then cater will automatically respond with the unauthorized http status code very useful but we don't need it here we need content negotiation that is used for json parsing so that when we respond with the kotlin data class it will automatically be parsed to a json um default headers you can include that you don't need to with that you can just um yeah attach default headers so just stuff that will be attached to every single header of every single response your server actually replies with we can let's add call logging it will just log whenever a client makes a request to our server so we can see that you can use templating so you can of course also use cater to respond with css or html content for making a website and we want to add something for the serialization so that is actually needed by this content negotiation to parse something to json we need one of these kotlin x serialization json or jackson i'm gonna use the kotlin one you have websocket plugins here but that is pretty much everything we need so when we're done we can click generate project and you can see it's just downloaded as a zip file we can now um actually just open this not the zip file just copy over the zip file into your intellij project directory extract it there and then i must see you back here so i opened my intellij idea and right now i have my twitch stream project open the social network which i also use ktor for if you actually want to see how i do that how i build a bigger app in my twitch live streams and you often miss these live streams then you can also um just join this channel by clicking on this join button down here that's like a for first small fee every month but then you can get access to all my live stream recordings from the past and in the future other than that let's go to file and we open the project that i just extracted from the zip file so this is my intellij folder and i extracted this k12 rabbits here that's the the folder we want to open clicking ok this window and now our project is being opened and built so i'll see you when that is done so there we go let's actually explore the ktor project structure um it's a little bit similar to android so um not too different a little bit if we open the root folder we can see that kind of seems a bit familiar we have we have a build a gradle kts file this time it's the kotlin version of gradle and it's as an android here you just have your dependencies you can see the plugins were automatically added like uh serialization um the logging stuff and stuff like that and yeah that's just the place where you can configure everything regarding your build not important for us here we don't need any extra dependencies we want to dive into the source folder main and now we have kotlin and resources oh it's not the test one cotton and resources and the resources folder is the folder in which we put well our resources like the images of the rabbits so what i will do is i will just copy over these rabbit images go inside static new directory and call it rabbits and where can you get these rabbits from well you can simply get these from the github repository a link down below so you will just see this product structure in this repository you can download it and then you will find this rabbits folder in the resources package here with all these images but as i said of course just feel free to pick your own rabbits you can just take one from google images or so just make sure that that's only for your personal use then of course but yeah now we have these five rabbits in here in a rabbits folder in our static folder so let's further explore this project structure we have our carton folder in which we have our application kt file if we open that that is the entry point for our program so what's an android the main activity here in ktur it is this application file and here we just have the normal main function as we know it from plain kotlin programs which is not relevant for us so don't modify this here um and we have an application module so we can also structure caterer servers into multiple modules um in rather simple backends you only have one which is this one the application module and for these modules you can actually have these configuration functions and these are actually located in the plugins folder so depending on which plugins you actually added when you were on that start.cater.io website it just created some default files here let's check a monitoring for example you can see it installs the car logging feature which is only possible if you have the dependency for that but that was also included and then you have a lambda block here in which you can configure that so how detailed logs do you want if you want to filter your log messages you can configure everything regarding call logging in this block and this now extends this application class which is why we can simply call it in here you can see that also extends the application class that's the cool thing about kator it allows you a lot of freedom where to put your code because everything here could be an extension function you will also see how that works with our routes later but that's very cool you you're so free in choosing how you structure your projects let's check the the routing that kt file that is where the routes are defined that our server responds at so you can see we have a routing block so now we define and configure the routing feature and it automatically generated this get request at our root url and when we when actually a client calls the zero l this block is fired off and it responds with some text hello world so we can simply launch this now and actually try this out by clicking in application kt and on this green play symbol click run application kt and then you can see it launches the server um but you will also see what happens here for me is it throws an exception it has address already in use and the issue here is the default port it launches this server on is this one eight zero eight zero that's the typical port for backend services for website services but it appears that on my machine there is already another application running on that specific port which is why i need to change this this does not need to happen for you if there is no application running on your machine on this specific port it won't crash but if it does then you need to change the default port of ktor and for that we have this application config file in your resources package or yeah in the resources package double click that and this is this hokan file that you have seen in the project generator here you just have cater specific configuration such as this port for example so we can change this to let's say 8 1 0 0 choose any number you like and if we now relaunch this then this should not crash and what we can now do is we can go to our browser and we can type http localhost colon 808100 which is the port you've chosen and just press enter and you will see it replies and responds with our hello world code that we have in our routing block here so that was just added by default and you can see how easy it is for us to now respond with stuff so i will actually remove this we don't want this hello world response instead we want a response that gives us a random rabbit so how can we do that um one thing before that actually i forgot the serialization file let's open that nothing special it just installs the content negotiation feature and just calls jason here this will just set up cotton x serialization here on our server but other than that um you can see how you could respond with that um so you can just respond with a map of stuff and that will then in the end be adjacent response we're not going to use this so we can remove the writing block here and actually right click on our root package create another package called routes and in this routes package we're going to put all of our routes we're only going to have one here we create a file in that routes package called rabbit route and that will be a file so not a clasp instead we choose a file here and as i said in k2 almost everything is an extension function not everything but a lot is an extension function also our routes so we can say function road import this iok to a routing route dot rabbit for example or we can call it random rabbit and in this function we can now configure our route we can determine what we will respond with how this route looks like all that stuff first of all what's important is what kind of route is it so if you're familiar with http then you will know there are get requests post requests put requests all that stuff in our case we just have a simple get request here because all we do is we get some data from the server we don't post anything to the server we don't update anything we don't delete anything we just get something so we say a get and we're going to choose this overloaded version here of that get function which allows us to define a path this path will be the route at which we actually access this so slash rabbit for example or again random rabbit random rabbit you can also do like this let's do it like this and then we open this lambda block and in here this will be called when a client actually accesses this route and well what happens in here you could of course attach some query parameters for get requests so if the client also needs to give you some data for example if the client wants a specific rabbit and you want to find that in your database then you could get some career parameters using call dot parameters for example at rabbit id or so and that would give you the rabbit id if the client attached one but we don't have create parameters here we actually just want to respond with a random rabbit so let's first define what is actually a rabbit and for that i will create a data package here in our root package so data dot let's call it data.model and in that model package we create a class rabbit that will be a data class and because we want to serialize this class in this class with um kotlin serialization we need to annotate this with serial a serializable actually so that will just allow us to parse this content of the class to json and send it over the network so each rabbit will have a name it will have a description both of type string of course and it will have an image url which will be the url of uh yeah the image so we can actually access that on our client then we will make use of this rabbit class by defining a list of rabbits that we can possibly respond with so we will just have a list of rabbits and then we will pick a random one of these and respond with that i will actually just put this in our rabbit route um in a bigger bag and of course i would structure this a bit better and i would have maybe a constant follow so um that contains that but this is super simple here so i'll leave it like that first of all we need to think about when we actually construct these rabbits we need to know our base url or yeah just the server url and the image urls so what what are these so we can define a private cons val base url and that is just http colon slash and now a lot a lot of you might think that's just localhost eight one zero zero so just localhost in the port because right now we just access our server here on our local machine of course that's different if you deploy your backend and that is usually also correct if you access that in your browser that will work but the thing is if you want to access this server on your android emulator then a localhost will refer to the local emulator because localhost for the emulator is the emulator and because on the android emulator there is no server running it won't work so if you actually test this on your android emulator what you need to choose here is 10 0 2 2. if you just do this in your if you test this on your phone on your actual device then you need to put in your local ip address of your computer in here so you can just open cmd to find that out and enter ipconfig and here you will find this ethernet adapter and you can you can see here is an ipv4 address this is the local ip address you actually want you can copy this and you can paste it in here so this will if you use this way then it will also work with your emulator because this is just local to your to your network at home so every device that's somewhat connected to your router will have such a local ip address and now i will actually paste my list of rabbits it's just a list of five rabbits as you can see feel free to give these rabbits your own names your own descriptions but what's important is this image url here so you can see for each rabbit i just attached the base url rabbits which is this uh static rabbits folder and then followed by the rabbit name depending on how many rabbits you have then you need to change the url accordingly now what we can do here in our route is we can go ahead we can say call that respond um we're gonna spawn respond with an okay status code so just telling the client hey your request was okay and we want to attach some data and that is just our rabbits list not our rabbits list actually we want to pick a random one so rabbits that random so that will pick a random entry of this list maybe carl maybe florian maybe federico and it will automatically parse that rabbit to jason and respond with that json string right now that function is unused you need to actually call that in your routing configuration to apply that in your backend so let's go to routing and in here we can just call random rabbit and that will just make sure that we set up this route and if we now launch this back end we can check this box and click stop and rerun then hopefully nothing will crash for you you can go to your browser and here you can simply say slash random rabbit click enter and you can see there's our json response and it responds with a random one this time with carl with the corresponding uh image url and if we click on that i'm not sure if that works right now that doesn't work because let's go back to intellij um we actually just need to remove this parentheses here so what this will now change is that it doesn't um if we leave it like that we would need to we would need to append a prepend static so static rabbits rabbit one jpeg for example if we don't do this the the static path won't be included in our url so this this way we just say okay we have resources in our static folder but the static isn't actually part of the url so we can just say as you've seen in our browser if we relaunch this we can just say our url slide rabbits rabbit one if we click reload then this time it will actually load a rabbit and that's already our api so very simple but actually very cool with ktor i love caterer because it uses kotlin and i can only suggest to you if you are an android developer and you want to build backgrounds for your clients for for yourself for any app then yeah really take a look at caterer it's an awesome back end it's not that popular yet but i'm pretty convinced that it will become more and more popular will take time of course but it already changed quite a lot in the past and in a good way um yeah so definitely try it out and let's now get to the android part and implement that in our android app so here i am just an empty jetpack composed project and i've already also included the dependencies here so on the one hand the dagger hilt plug in here kotlin capped and dagger hilt and some dependencies the companies library to load images using coil using uh the network view model scope curoutines um yeah and dagger hill and retrofit so just to make the http request will be a very simple app um just to get these dependencies and all that initial code just get the the initial project down below from my github repository and then you're good to go so let's actually start to set up two packages as i said it will be very simple won't set up any super special package structure here i will just have one for data and one for di dependency injection and we are going to start in the data package so we create our retrofit api interface so let's actually first create the rabbit class which we can essentially just copy from our server so let's open that just copy this rabbit class and paste it in android studio in our data class so just ctrl v paste this yes i add that to git we can go to the package name press alt plus enter and change this to the right package name remove the serialization stuff because we don't need this here i think i use g's in here yeah just because i just copied over the dependencies for retrofit doesn't really matter now we have the uh the retrofit class the rapid class and we want to implement the retrofit interface so we go to the data package new kirtland class of file select interface and call this rabbit's api press enter and here if you know retrofit we just define the routes that we have that we need to access our our backend that is just one route here slash add get actually and we define the the actual route which is random rabbit actually slash random rabbit the function for that will be a suspend function so just in a curtain asynchronously get random rabbit doesn't take any parameters and we can just return such a rabbit and that we just created then let's go to our di package new kotlin class or file select object called app module that's going to be the place in which we provide our retrofit api interface so that will be a module we install it into the singleton component so all these dependencies will be singletons and then we're going to have the typical provide functions so it provides a singleton dependency and we call it provide rabbits api returns a rabbit's api and we can say return retrofit that builder at converter factory so we just did we just say hey we want to use the the json library to parse the json content here so decent converter factory at create and we're going to specify a base url which i will just hard code here we can also just put it in the the api interface here using a companion object cons the valve base url is equal to http slash colon slash slash this will be the same ip you have actually copied before whoops i think it is this one right quickly check routing rabbit route yes exactly and also we need the port here then we can go to app module say rabbit's api dot base url that build and dot create and we pass our rabbits api double colon class at java and that's all we need for the retrofit interface let's do the next step which is defining a viewmodel in which we actually call our function and provide the data for the ui i'll just put that in my root package new class called main view model um actually we also need to set up dagger hilt but let's first do the view model stuff i'll select file and i'll use my live template hill to view model which will just set up the default constructor for hill view models you won't have this live template most likely so you have to tap this by hand i'll call it a main view model it will take a private val api which is our rabbit's api and then let's see what we have in here we definitely need a class for the state for our ui so their class rabbit state which will contain the current rabbit which is initially null so let's set it to null and it will contain and is loading boolean which is false initially then we can say vm state which is also a live template you won't have if you want to find out how i set up these live templates then just search on my channel for that like for the black live templates android city or so then yeah that's a video where i show exactly that um i'll call this just state that will be of tab rabbit state and initialized with an empty rebel state we can remove this and then we will have a function to get a random rabbit what will this function do well it will launch a routine in the model scope so your models got that launch and in here we're going to have a try and catch block so in case something goes wrong with our api call if we don't have internet or so then i will just log the exception here i won't do any specific error handling or display that in our ui because that's such a simple app the tag will be main view model and we can attach our exception here if we have an exception we want to set the stated value to stated value copy we set is loading to false um before we make the actual network request we want to set this loading to true so standard value that copy is loading true then we say stated value is stated value copy this time we set the rabbit to our api and get random rabbit and it's loading to false again because this of course delays our crew team we have some yeah just some delay in which we can show progress bar and that is already it here for the view model let's just call this function in the init block get run up rabbit so we just initially load one rabbit and yeah now only the ui is missing in the dependency injection setup let's go on with that just creating an application class rabbit app inherits from application and we annotate this with hilt android app we need to register that in our manifest so let's open that we say name a rabbit app when we're already here we can also add the internet permission and because we work with our local our local backend here and we don't use https we also need one additional config here which is uses clear text traffic we need to set that to true in a production app that should be set to false so you only allow encrypted traffic using https but since we don't have that here we need to explicitly allow that we can close this again we can close this and actually go to main activity and just set up our ui now so we're going to have a column in which you just put our different composables our image title text description text and button and progress bar that column will have a modifier to fill the whole screen size and i will add some padding of 32dp and can we format that yes we can then in that column we will need a reference to the view model type main view model which is equal to hilt view models build view model and to be able to do that we need to annotate this activity with android entry point suggest that dagger hilt is able to inject dependencies in this android component which in activity is in the end and then we can get the rabbit state using our viewmodel that state that value that rabbit and we can get this loading state using viewmodel state value is loading and if that rabbit now is not equal to null then we want to show our rabbit data so first of all we want to show an image of the rabbit that we just load from our api we use the call library for that so we can say image the painter will be remember image painter that comes from the coil library with which we can easily now load a remote image we can say the data is our url so rabbit dot image url and we can also make this fade a little bit by adding a builder where we set cross rate to true content description could just be rabbit for example rearrange this a bit and we need an annotation here i think yes now we can move this to main activity then we will have some space below that image let's set the height to 80p we wanted text for the rabbit name so rabbit.name i'll set the font way to bold and the font size to let's say 20sp import sp format that we can take the spacer put it down below we can have another text for the description rabbit does that description um something that comes down below yeah we want to have another spacer um and then outside of the zlat block we want to show the button so we always want to show the button no matter if the loading was successful or not so we can say button on click will be view model double colon get random rabbit so we just call the get reno rabbit function and i want to align that to the end so modifier is modifier.line alignment.end and the text of the button will be get um or just next rabbit okay and one more thing for the progress bar let's have another spacer with a height of atp and then we have a check if we're actually loading if we are we show a circular progress indicator and that should actually be it so i think this android site should be pretty clear if you're somehow familiar with android and my projects so that's why i went through this a little bit faster because that's also not the focus of this video but let's actually launch this and try it out so that's my old app let's wait until the other one is actually built so let's hope everything goes well and nothing crashes and we don't get anything oh we do yeah so that looks fine we could have centered this of course um i wasn't sure if my api was running so make sure that your server is actually running we can click next rabbit and yeah we get another rabbit these images are very large here so one is even like like 20 26 megabytes or so of course in a real wagon you would compress this for such a simple display that i was too lazy to do that so that should actually now work fine and call also caches these so when these are um loaded once then these will display a lot faster but that works pretty cool so if we now take a look in our back end then you can see all these get requests that is this call logging feature just whenever a client accesses a route then it will log this here very useful so that is actually it for this video if you want to learn more about cater so if you learn how to how to use a database in that so to persistently save data like mongodb specifically if you want to learn how you can use authentication in cater if you want to learn how you can actually communicate with real time traffic in cater so with web sockets then you really want to check out my courses down below i have one course about caterer that shows you how to just build the typical rest api so mongodb authentication hashing passwords and all that stuff that um belongs to typical rest api and i have another course the doodle concurs which is in which we will basically build a real time and drawing game so drill real time scroll game and that will use web sockets so that fully focuses on this websocket feature of cater which is comparable for example to a firebase snapshot listener so the real-time um listener of firebase that will notify you about changes and yeah you really want to check these courses down below i will also give you a discount code here because you finished watching this video and you're obviously interested in caterer and that is ktour underscore lovers if you use that you will get 15 percent off of my both um cater courses enjoy that and thanks for the support apart from that i wish you an excellent day and i see you back in the next video again bye bye
Info
Channel: Philipp Lackner
Views: 7,427
Rating: 4.9612589 out of 5
Keywords: android, tutorial, philip, philipp, filipp, filip, fillip, fillipp, phillipp, phillip, lackener, leckener, leckner, lackner, kotlin, mobile
Id: c6I3Dw0xDlQ
Channel Id: undefined
Length: 41min 55sec (2515 seconds)
Published: Sun Sep 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.