Build an MVVM Camera App with CameraX - (Android)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome back to a new video in which we are going to build another MVM architectural design patn app which is a camera app powered by camera X so let's check the app this is how it looks like as you can see here we have four buttons here is my laptop and here is my fingers so here we if we click on this one we'll go to the gallery and when we click on this one we can record a video like this now when we click again we stop recording with this button we can take a picture we when we click on this one we can flip the screen which which is something I won't do now I'm just going to show you the gallery so here is the photo and video that we recorded it's in dsim camera app which is the name of our app here's the photo and here's the video of course with audio you can hear the audio so that's the app and make sure to stay till the end of this video to learn how to build such a cool app that you can have in your GitHub as a repository so let's get started the first thing we need is some libraries which are the health and Camera X let's go to our lips. versions let me just bring this one here and here there are the versions of camera X and also dger Hilt here we have the dger hilt plugin and then here are the libraries for camera X and then dger Hilt you can just copy this from the project I will link below it's on GitHub and then of course we'll go to our griddle file here and we'll find this Dills plugin and then in our app Gradle file as well we'll find the same plugin with cap that we need for for doger Hil and the dependencies of course for camera X and then dogal just copy these and paste them in your project and Sy and you'll be good to go to build the app so let's start with our data layer in our data layer what we are going to do is four things recording a video taking a picture and then save that video and picture so we'll have four functions in our repository of course you can have more than one repository if you want here I will have a package called domain. repository and I would just have my interface of repository here I'm going to name name camera repository that's a interface right now I will have two functions in here suspend fun take photo that just takes a controller of type life cycle camera controller and then we can just applicate this for the other function that is record video of course the other two functions for saving will be there but we don't have to make them abstractions because we won't use them anywhere else now in my root package this just close domain I'll create a new package called data. repository right here then I'm going to create my class which is my camera repository I need to inject The Constructor of course and then I will actually name this one Implement like this because this is just an implementation of our abstraction this one will Implement now my camera repository and here we have this functions to override all I need in my Constructor right here let me just bring this to a new line is application private VA application application and then let me just create that as well app maybe I already have it so I've already created it actually so application helps Android app and then in my manifest I need to register that app and also the permissions we need which are for camera and audio recording and Hardware because of course camera is a hardware thing that's all we need and now we can actually start taking the picture but first of all I need a recording private V recording of type recording and that is going to be n by default we use this recording to record a video and we need it later so right here to take a picture simply all I need to do is use my controller. take picture I need to pass the executor and that I can get it from Context compact. git main executor pass in my application and then I need to pass the callback for taking a picture so that's going to be object image capture do on image capture call back here I have one function to overwrite that is I have two functions but I'm only interested of course on on the sucess one in which I successfully take an image I get the image which is of Type image proxy which is exactly the image I just took now I want to make sure that my image is well rotated so I need Matrix for that V Matrix is going to be matrix. apply and here I have a typo post rotate my image do image in for DOT rotation degrees let me just bring this to a new line dot to float because that needs a float now I have my rotation degrees in my Matrix now I just need to create a bit map from this image so while image bit map is going to be bit map dot creat bit map I'm going to pass now my image do to bit map I need to pass the X and Y offsets that's going to be zero for both and then the image width and image height then the Matrix and filter to True like this now I have my image I just need to call the function that saves it so I'm going to name it save photo for example passing my image bit map this will be a suspend function for that I need a cortin scope cortin scope dispatchers do iio because this is an IO operation at the end I will launch that and then then call this one inside it I will create this function later now let's actually try recording a video this is actually for taking an image it's as simple as that for recording a video it's so simple and now we'll use this recording that we have right here so if I'm already recording then I need to stop recording if not then I need to record so if recording is not null then that means I am recording so I need just to stop recording recording do stop and then set it to null again recording is equal to null and then I can return probably it has to be a VAR okay now I know that I'm recording let me just change this one to my recording and here I just stop recording recording and return but let's actually try recording that video first of all the name of the video is going to be the current time in m so V time in mes is going to be system. count time in mes and then a video at the end is a file so file like this from IO java.io pass in my application. file de and then the name is going to be my my current time in M which is time in mes video like this so we know it's a video. MP4 not two but four because yeah that's the format I want and now I just want to start recording so my recording is equal to using my controller that I passed here do start recording I need now to pass my file output options file output options. Builder pass in my file. build and then the audio config audio config do create true so I do want audio obviously don't worry about this error you won't cause any issues just asking us for permission of course we'll ask for permission later context comp. get main execut will also need that here pass in my application here I simply get an event and that event tells me whether I successfully recorded or I finished recording all those stuff in my case I technically only care when I finish recording so if my event is video record event. finaly then I just finished recording and I need to check if I have any any errors event do has error then I did not record the video I just need to close my recording not stop but actually close set it to null again so recording is null else I then did record the video so I just need to save it using again a Quin scope passing my dispatchers do. launch let's call it save video passing my file simply now we've successfully recorded the video and take the photo we just need to save those because what's the point if we record them and take the photo without saving it let's start with the photo private fun save photo that takes of course a bit map that we want to save and since that's an IO operation we're going to switch to the io dispatcher dispatchers doio and now to save this photo we'll use media store but actually writing all that code is too much so I'm just going to paste it and explain it so here it is and I'm going to actually explain the first thing is that we'll use media store and media store only works for Android version 29 in the above so and 29 this probably won't work for that case you need to use a different method of saving uh in that case I will leave that to you but in my case I'm going to use media store so of course we get the bit map we do this in the dispatcher doio we need this content resolver to interact with our storage this is what we use to save that in media store and then where are we going to insert it in our image collection we get the volume which is external primary means external storage here I get the app name which is glare and just to create the folder that tells these photos and videos are taken by our app so we put them in a folder in our app name and here timing Millies again we don't have to have this one like this so the current timing milles the image content values is just used to store some metadata in the image like its name its path where it's going to be dsim and it's type gpg they taken is spanding here is one so submit data of course for the image here we have the image media store Ur and now we just use our resolver or our content resolver to store that image of course here we tell that it's in the exteral storage and then here is the content values or the emitted data of that image if our Ur is not null then we can start saving it of course first of all we need to compress we open an output stream and then we try to compress that image into a gpg format and we just bring this like this so to to save space and then simply we store it if everything is clear then we just clear our metadata we tell that it's no longer pending so we set that to zero we can also bring this to a new line and then update here to just refresh our Gallery if any or happens we leete that Ur that's what's going on here to save an image now we need to create another function to save the video private fun that's probably a suspend fun save video that takes a file of type file and this function is going to be almost identical go to the first one with some little differences here we need to add that annotation again because we use media store again our content solver our Video Collection so here in extender storage the app name the current time in mes we put submitted data in our video as you can see so again in our DCI folder and then up name folder again the type is M MP4 the DAT added date modified date taken all of that just metadata is spanding is one and then again we try inserting that that we get URL lify and search is great with our metadata so here we open our output stream and then we try saving our file of course we need a Ur So we get that Ur from the file and then after the output stream is used we actually make sure that it's closed properly so again we clear that and then we tell it's no longer pending and then we update our gallery and if any exception happens delete that Ur everything now is great we save the video and the photo and we also recorded that video and take it and now we can just start with our presentation package by going right here create a new package called presentation right there I'm going to have a screen let's actually start with the view model first camera view model okay this is going to be a health view model let me just get some space down here and then we need to inject The Constructor we extend or we Implement view model from life cycle and we need our repository but probably I first need to do some dependency injection di right here all I need is my camera repository module to provide my function or my repository that's going to be an abstract class of course this is a module install in Singleton component class now here I'm going to have an abstract function bind camera Repository this will take my implementation camera repository implementation all right and then returns my camera repository we annotate this with binds and then Singleton okay so now I'm done with the dependency injection I provided my repository make sure that I injected the constructors so everything is great I do have my app and private Val camera reposition here I will have one state which are whether I'm recording or not so that's a state private Val is recording that is going to be a mutable State flow of FS at first because obviously I'm not recording now the public version is recording this is going to be my is recording. as state flow and I will have two functions in this video I'm not going to create that on event class I don't need that I only have two events so I'm just going to have them as functions in here fun on take photo so when I try to take a photo I need of course the controller of type life cycle camera controller in that case I need a view model scope do launch and then I use my camera pository do take photo pass in my controller like that we can copy this for take a video or on record video Pro it's a better name here record video and that's it for the view model as simple as that all the magic is going to happen in our screen so camera screen and that's the only screen we will have that's going to be a composable camera screen all right and I just need to call that from my activity let me just delete all of this right here actually don't want the background color I want all the time black so I'm just going to call directly my camera screen and let's get started with it but actually before I'm able to record a video and take photos I need the permission for video recording and also audio recording for that let me go back to my main activity and ask for the permission right here and I'm going to create a function f let's say our permissions granted like this this doesn't take anything it just returns a pooling of course whether I do have the permissions or not not bundle but bullion let me create some space down here and then obviously I also need the permissions I need so that I'm going to put them in a component object and that's going to be Val say camera permissions is going to be array of manifest. permission. camera and then just applicate this for audio so record audio these are the two permissions I need and now I check if I have them or not so return my camera permissions. all and then right here I get the permission like this and I need to check for them so context compact. check safe permission passing first my application context and then my permission and then make sure that it's guaranteed is equal to package manager dot permission guaranteed so if this returns true I do have the permissions if it returns false I don't and I would actually ask for the permissions as soon as the user opens the app so right here in my own create function I'm going to check if permissions are not guaranteed like this and then I'm going to ask for them so activity compact. request permissions passing the activity which is this and then the permissions I want which are camera permissions and then request scode can be anything like 100 for example so I would just uh this is not the best way of asking for permissions but now we're just trying to be simple so I'm just asking for the permissions if I have them then I won't ask for anything if otherwise I will actually ask for them at the launch of my app this can be a private function and now let's go to my screen the first thing I need in my screen is of course the controller that I want to use to record videos and take photos that I also will pass to my repository V controller is going to be remember savable to actually just survive configuration changes that's going to be live psycho camera controller I also need application contact so for that I can just possibly pass my activity here activity ofp activity and then let's pass that right here this so I can use the activity to get my application context do apply just probably bring this to a new line set enable use cases and then I'm going to go for camera controller. image capture or camera controller. video capture so I can either capture an image or a video now I have my controller I just need to create my camera view model instance now while camera view model is going to be heal view model of course the type is my camera view model uh now I just need to take this from the save block and then put it in the screen block now I need the state that I get from my view model V is recording is going to be by camera view model dot is recording. collect aate and probably I think I don't actually update it in my view model so when I need to start recording a video I need to update that is recording so right here my is recording. update that is going to be the opposite of it so is recording. value so if I am recording in I try record a video then this one is already true so I'm now recording and then I want to stop recording so I set it to false and then I call my function in the repository that will check also the recording it has that is not n so it stops recording and if this was false I'm not recording then this will be true that I am recording now this one will call that function and the recording there is actually false and also it will be true or probably it won't be n I'm sorry and then starts recording so that's the logic behind this now right here to create create my screen let's actually see the screen so here it is we just have our camera preview we will actually also change the statu bar color to Black and then we have four buttons at the bottom let start with the status bar color by going to UI now I actually found a solution to change it without those issues I had previously right here in my case I always want it to be black so color do black and then right here I can bring these and then his light colors is always false so uh the statu bar is always dark as you you can see so we have light colors for the status themselves and that's it now let's proceed with the UI obviously everything will be inside a box box that just fills the max size also that box needs a background that is going to be color. black inside the box I'm first going to have the camera preview for that I need the life cycle V life cycle uh owner is going to be local life cycle owner. curent and then the preview is going to be inside an underw view so underw view I need a factory obviously of course we don't have a direct support for camera X in compos we need to use underw view for that the factory gives me a context and all I need here is a preview view passing it which is the context. apply this do controller is going to be my controller so the preview controller and then my controller do bind to life cycle passing my life cycle I also need a modifier for this let me just put it at the top here modifier modifier. fill Max size okay so just the preview fills the max size and then all I want is a row in which I'm going to put these four buttons my row needs some modifier do fil Max width only I'm going to have some padding from the bottom to push these buttons up let's go for let's say 800. DP import DP and then I want to align this uh row to the bottom alignment dot bottom center and then the horizontal Arrangement is going to be Arrangement dot space evenly and then vertical alignment is going to be alignment do Center vertically all right inside this row each icon here is eventually a box inside it an icon so box that definitely needs some modifier and with my modifier I'm going to clip the first icon which is the gallery icon so clip round it Corner shape and I'm going to go for 14. DP and then the size is going to be for this one actually there are different size these two are smaller than the take photo and video icons the size is going to be 45. DP background of it is going to be material theme color scheme do primary and then do clickable so when I click I want to perform something of course all I want to do is open in the gallery app like this as you can see I open gallery when I click on that to do that I need an intent intent let's import it and then I need intent doaction View and then to open the default gallery app I need a UR ur. bars that's going to be let me just paste it this one so content sl/ media internal images media this is how I open the default camera app so in my intent I just write dot also and need activity do start activity it because here I get the intent all right now I can open the default gallery app inside the box I will have the icon which is this little gallery icon that's going to be icon I need an image vector and here the image vctor is going to be icons. default. photo uh probably I need the extended Library uh extended icons Library so for that let's just close this emulator and go back to our lips. versions right here we need to add that library and that is going to be this one which is the extended icons Library the version of it is going to be much use icons version this is the version we can just syc and then let's go right here and call that like this so here it is let's just s again now we have our icons we can close these and open the emulator again so let's wait for a photo hopefully Library as you can see now the content description can be for example open gallery let's put that in a string resource if you want to translate the app and then we need some things in here like the ttin is going to be material theme. color scheme. on primary the modifier to give it a size so modifier do size that is going to be 26. DP we can just copy this one a few more times but in between them I'm going to put one little small spacer and I'm going to go for width or height it doesn't matter at the end it will have just one DP just to add extra space between these as you can see for this one in the on click first of all this one is record video so right here I'm going to write record video add that to Strings uh video cam for example but actually this one depends whether I'm recording or not let's first start with the container this is going to be circular shape it's going to be slightly big like this in the on click I first need to make sure that I have permissions because I don't want to record without permissions so for for that I'm going to make this one not private and then to call it right here I'm going to use my activity as main activity do our permissions guaranteed I'm just doing it this way which is a workaround of course in that case you might find another way to do it like for example not even showing the camera screen unless you have permissions so and then of course uh you can extend this app as I said and make it as cool as you want so if is recording this is going to be the icon not this one but actually stop if else it's going to be icons. default. video cam all right so this is for the icon let me just copy this one one more time but I don't need to add that spacer here check if I have permission or not so that's what I need to do like that if I do have the permission then I can call my camera view model do take this is actually video record video passing my controller so we can just copy this for the first one or this one is video this second one is actually photo on take photo like this right here we'll have one icon all the time won't have more than one icon which is going to be of course camera let's go for this first one the rest is going to be the same but the content description is going to be take photo all right the last icon I definitely need it to look just like this one but I also need a spacer here let's go for WID one. DP uh in the first one I also had width which is great now for this one I want to rotate actually my camera so if I was previewing the rear camera and I would want to preview the front camera or the other way around let just first of all here use my camera switch like this as well right here I'm going to write something like switch camera preview add these two strings when we click how do we switch we can use the controller to switch controller. camera selector is going to be if controller. camera selector is equal to camera selector do let me just probably close this one so camera selector dot back camera then I want to switch to the front camera so camera selector do front camera else I'm going to switch to the back camera Cera so camera selector do default. back camera all right now I switch one thing is that this icon won't actually be in the center of the container so I need content alignment alignment do Center for all of those let's do the same with this one not right here but here this one and this one and yes that's it we have an error right here so now the error is gone this is the original app let's close it and let's try our app okay here it is let's see if we have any crashes or errors to fix yes the app does crash even though it does ask has for permissions let's see why it crashes and let's try fixing it the reason why it crashes is that I did not annotate my activity with I always forget to do this on the with entry points let's try one more time and uh the app seems to still crashes let me let me see why oh yes I can't see the error I can't use remember receivable there so I can just use remember like this and then let's try one more time hopefully all right it's now working can we open the gallery we can of course we don't have any camera or something to switch to so the app different would crash but as you can see your camera is not supported so I'm going to try now my real device to see if everything is fine so here is my pixel 7 and let me just run the app on it let's give it the permissions and yes let's try recording something as you can see it's recording put a little tum stop recording let me actually take a picture great and I promise when you click on this one it work T but I won't do it and when you click on this one it will open the gallery and they also won't do it so now let's just check our Gallery if everything is there let's actually switch to dark theme or light theme because now I'm in Dark theme and there is how it looks like so here is my folder which is camera X app which is the name I gave to the app if we check our strings we'll find that it's called camera X here's the photo and here is the video the audio is recorded and everything is great and this is it in this video in which we built a hardware based app which is a camera app if you think what I'm doing is H for support me by a subscribe leaving a like and sharing this with your friends you can find the link to this code in the description leave a comment if you have any question and see you in the next video bye
Info
Channel: Ahmed Guedmioui
Views: 896
Rating: undefined out of 5
Keywords: android studio tutorial for beginners, android studio project, android studio app development, android studio app, android studio app project, kotlin android tutorial, kotlin tutorial, kotlin multiplatform, kotlin full course, jetpack compose tutorial, jetpack compose android, jetpack compose mvvm, jetpack compose state, jetpack compose viewmodel, jetpack compose vs xml, jetpack compose app, api key, jetpack compose animation
Id: F1yKQ6EOTXc
Channel Id: undefined
Length: 29min 15sec (1755 seconds)
Published: Wed Mar 27 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.