Media3 + Jetpack Compose: The Ultimate Guide to Building a Audio Player App

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back again so you have mastered the audio playback mechanisms with media 3 and exop player in the first part of this tutorial series now it's time to make your app shine with jar compose the modern tool kit for building native Android uis in this part we'll use Jaa compost to create stunning and interactive UI that work similarly with the playback controls you learn how to design the layout end user interactions and use view model for UI logic so before we begin I want to remind you to subscribe to our Channel if you haven't already this way you'll never miss any of our awesome tutorials on Android development also don't forget to leave a comment below and let us know what you think of this tutorial series we love hearing from you and your feedback help us improve our content and of course if you find this tutorial helpful please give it a thumbs up and share it with your friend and fellow developers thank you for your support and let's get started okay so for this case let's just close all of our Tab and here now inside our UI package I want to create a new package and we can easily just call this audio so inside here I'm going to put my view model and also my screen so we going to have only a single screen and all a single view model so if you want to expand this application feel free to expand it okay so for this case let's create here our class and the first case let's create our audio view [Music] model okay the first case here we have to annotate this with at view model to tell this is just going to be a view model the next case we have to inherit from The View model class okay so here we require to have two variables so the first case is just the audio service Handler which we have created from the previous part so this audio service Handler here is going to help us to uh control between the UI and also the playback mechanism and for this case here we want to get also the repository so let's create here a private variable and call this repository and because our our audio repository actually it's Constructor injected so we do not have to create the instance or to provide the instance by creating a module for this okay so another thing we have several things which we can easily uh acquire so for example the duration the progress and other things so we are going to use a sa State Handler in order to save our data okay so there is one Library which we require to add here in order to create a safe distate handle so for this case let's just go inside our bu. G file here and below here we can easily just add this dependency here which I forgot to add it earlier so this is just the life cycle view model compose which is going to help us to to create aate handle and access the life cycle method with a composable way okay so now our build is complete okay so we want to get the S theate uh so here we can just call here our s theate handle and this one is going to help us to uh get our data from our UI and also pass it to our view model and for this case we can easily Save Our State whenever we have a configuration change or we have a process dep basically we can just return to the same state and for this case we can just easily now start to use our saved State handle so for example here we want to get our duration so we can just call this duration and we can use a buy delegate method and called s theate handle and here we want to use a savable which is just a composable extension function to a s the state handle and for this case we want to call a mutable State off one L because our duration is going to be in types of long now let's press contrl D and for case here we want to get the progress and for the progress this is just going to be f now the next case here for example if you want to provide a progression string so inste here we're just going to provide a string and for initially we want to occupy this type of ring so if you want to construct it you can easily use it another thing is to check if is playing so let's just press contr D here duplicate and change here is playing and this is just going to be a Boolean and initially this is just going to be false okay the next case here is to check if our current audio selected so what audio has been selected so you can create here a variable and call here current selected audio so for this case here above we can just create a dumy audio so let's create here a private variable and call this audio so this one is just going to hold up our initial state so for this case here we can just pass in this to beur okay so I have created here an empty audio so as you can see we have empty variables here which which is just going to be our initial state so for this case here we can just call here our audio Dy to be as our initial State okay the next case here is just our audio list so for this case we can just call here audio list okay so this just our initial State now the next case here is we want to create our state and also the events which can be easily observed outside our view model so for this case let's just come below here and let's create a sealed class and call this UI State okay so for UI State here we want to mainly to have to State here so we have the initial and this is when our US state is not loaded so for this case we can just return our initial and also we have when our our state is ready and this is just going to take up our UI State okay so we can easily forward the event here so let's just create here a s class and we can just call this UI events and we want to seek to a certain position so for this case we can just call this seek to and here instead of index we have to pass in the position in terms of flots and this actually is going to be inheriting from a UI event now the next case is whenever we want to seek to next whenever we want to skip for example to our next item so we can just call this seek to okay the last case here is just to get our data class and here we want to get an event for update progress and here we can pass in a new progress which we are going to receive and this is just going to be in terms of flot now here we can just check our UI events and have everything ready here okay so now here we have our UI events the next case here we want to create an state that we can easily observe it outside of our view model so for this case let's create here a private variable let's just create here a state I have a shortcut here and for case we can just call this UI State and initially here we're just going to call our UI state do initial okay so now let's create here an init function so whenever we initialize here our variable we want to uh init our our views so for this case we can just call here our view model scope. launch and inside here our init we can just call here our audio service Handler and we want to call our audio state which is just the state that is defined inside our audio State Handler and for this case we want to collect latest and here we can just uh initialize this to Media State rename the reference sorry now we want to check by using a wayin statement now when our state if this is just going to be jet audio so we can use here our jet audio state do initial so if this is going to be the case then we want to change our U state so we can call here UI state. value and actually initialize the One initial now let's check here by using is course we are going to check if this is going to be a type of a certain class now we can do one thing here we want to calculate the progress if we are starting to buffering here so let's create here a function that is going to help us to calculate the progress so for this case let's create a private function and this one is going to take us a current progress which is just going to be of type long okay so inside here we can just initialize our progress and we want to check if our current progress is going to be greater than zero then we want to return this type of progress here we can perform here a simple mathematical calculation so what we can do we can just get here our current progress value and change it to flot and we want to divide this with the total duration which we have and also this change it to float what we are doing here we are getting the current progress dividing it with the total durations which we have and the next case here we want to multiply everything by 100 so for this case we can just multiply everything with 100f and if this is not the case so before we multiply this so we can place contrl X in order to make it more readable so we can just uh put another parenthesis here now if this is not going to be the case so we can just check here else and just return z f okay so as you can see here we're taking the current progress dividing it by float and also multiplying it to 100 so we want to get the proportion of the current duration so that we can easily display it inside our progress so for this case we have uh calculated this by by multiplying here by 100f and if this is not going to be the current progession is not going to be greater than zero then we can easily just return 0f and this is just for safety purposes because sometimes this can easily just give you something which is not uh great so also here we can just uh reinitialize our progress uh progression string and we can just easily create here a format duration function that is going to help us to format the duration so let's create here a function and call this we can pass in here our duration and we want to format it to a millisecond so we can just call here time units okay the next case here we can just pass in seconds we can just call this seconds and what we want to do we can just use here our minute and we want to substract this with a minute multiplied sorry this minute is going to be multiplied by our time unit second and we want to convert this so here we can just pass in here one and call here time unit do minute and for this case we get our seconds and here you can easily just return so you can use string. format so you can provide different type of formats here to format your string so for a case I'm just going to provide this so here let's just pass in a percentage sign and also here we can just pass in our minute and also our seconds which is going to be formatted in this type of format here which we have passed here okay so we can initialize our progression string here and pass in our format duration okay so let's just go back inside here our audio if it's buffering and we can just call here calculate progression string and basically now we can just use our media state do uh progress which is just going to give us the progress so here we can use is jet AIO if this is currently playing here so we can change here is playing and use our media state that is playing the next case here is to check if is audio progress so we can just call here our audio do progress and here now we can just easily call here our calculate progress values and basically pass in here our media state do progress now the next case here is to check if what current audio is playing so we can just check here is use our jet audio state currently playing so here we can just change our currently selected audio index and we can easily obtain our audio list so let's just get our audio list and we can use our media state do media media item index which is just the selected media item here and we easily get our audio and for this case here we can just finish up with the last part here if our audio stage is going to be ready so we can just check here is ready okay so if we get to this state here we want to reinitialize our duration and here we can just call our media state. duration and the next case here we can change our UI States and pass in here our UI state do ready to make our UI ready in order to show it so I think here everything is looking perfectly so the next case here is to hook up the events so here we have our state handled now the next part here let's just handle our UI state so before we continue to handle anything else here we have first to load our data from our repository and actually set the media items so for this case let's create here a private function and call this load audio data and now we can use here our view modos scope but launch and basically create here our audio and call here our repository. getet audio data which is just going to give us the audio data now the next case here we want to set our media items so let's create here a private function also and call this set media items so basically this one is going to help us to set the Mia items list so here we PCH our audio now the next case here we can just use our audio list so we want to transform this audio list and not in the audio which we actually have inside our model so here we can just rename this to audio now let's create here a media item we can use this Android media 3 and Call here our builder in order to build the media item now let's create here set URI now we can just use here our audio. URI the next case here is to call set media item Builder metadata sorry so we want to set the media metadata first then we can just call here our media metadata using the Android media 3 and Call here Builder now the next case here we want to set the album artist and basically we can just call here our audio. artist and let's call do build and the next case here is to build our media item let's call here [Music] build in order to build our media item now after we transform here our audio list we want to call that also also scope function here and what we want to do is to use our audio service state Handler and call said media item list and what we want to do is to change our media item list here to itat okay so now let's navigate back here so we can easily set our media item list so we can change here our audio list and initialize to our audio and for this case here we can easily Now set our media items so we can just call here set media items and let's just make this as M here and now let's create here an init function and inside here let's just call here load audio data and this data is loaded here now okay now our audio data is loaded we can create here another function which is just called the on UI events and actually we are going to receive here a UI event and now we can just call here a modos scope. launch okay now let's check here by using our way statement so we can just pass in here our UI event okay now let's Implement a single UI event so let's call here UI event backward so so we can just call here our audio Services Handler and call here on player events and this player event here we want to pass in here the player event do backward okay the next case here is let's just press control D here so if it's forward we can just pass in here forward and here let's just pass in to be forward okay so the next case here is to check our UI event so we can use e because here we are going to have a data class so for this case we canot use just directly here because it's not an object so we can check here our your event do play oruse so if this event is going to be forwarded so we want to change our audio Service uh Handler and pass in here our own player event and here now we can just easily substitute with our player event but play oros let's press contrl D again and here we want to seek to a certain position so for this case we can just call Se to and here we have to pass in the SE position okay so in order to obtain our s position here because our duration is going to be differently forwarded from our UI because our UI is going to convert this to 100% so we have to convert this so we can just perform here a simple calculation so we can just call here our duration multiplied by UI event do position so we just reversing what we did before and for this case we just going to uh divide this to 100f and actually all of this we have to surround them inside the parenthesis and call this too long then we can just check e is going to be UI event do selected audio change now we can just call here our audio service Handler and call the on player event and here we have to pass in our player event do selected audio change and here we have to change the selected audio index index so we have the selected audio index so we can just call here our UI event do index and because here we are scoping this that's why we are being able to receive this type of events so as you can see here we have your events. index and when you look here inside we defined for example when I selected audio index we defined here a variable to be an index so don't get surprised why here I'm getting these values okay the next part here we can easily scope this so we can use here our UI events do uh progress update progress here and now we can use here our audio service Handler and call their on player event and call here our player event do update progress and we have to pass in here here a new progress so for this case we can just call here our UI events do new progress and here everything is complete inside our view model and as you can see we have our event which are just going to be hooked up inside our screen or inside our our Jaa compose implementation and also here we have now our state uh which is just exposed here as a state flow okay so now here our view mod is complete the next case here let's create our home screen or our audio screen so let's just create here a cting class of file and from a case I'm just going to call this home screen so inside here okay so the first case here inside our home screen you want to get the progress which is just going to be of type flot and here the on progress okay so this is just our home screen here and these are the parameters which you require which are going to be helping us to hook up the event and the state okay so we are hoisting the state up our composable colors and the composable color here is not going to require to provide a state inside this uh here okay so the first case here we want to create a scaffold because we have the Bottom bar that is just going to be a player so for this case let's just create here a scaffold okay so the first case inside here our scaffold and here we have to opt in because it's just still experimental okay so the first case here is just the Bottom bar so we have only our Bottom bar okay now let's create here a new composable and call this bottom and pass in here the audio is audio going to be playing and also the on start and they on next so for on start no need to pass in here an integer okay so for this case we can just use a bottom bar a composable function from Material 3 okay so we can just provide here our content so for our content we can easily just create here a column now for the column here we can just pass in here our modify and we can just give it a pading of 8 DP so inside here we can easily create a row okay so let's pass in here modify and we want to fill the max size and also provide a heit of 56 DP okay and also the horizontal Arrangement and here we can just pass in here Arrangement do space between and pass in here the vertical alignment and we want to center it vertically okay so for this case here we want to create a separate composable for the artist information here so let's create here a new composable and this is just going to be similar to what we have and an audio to receive here now for the artist information we can easily create here a row and inside here a row we can just pass in here our modifier and we want to pass in here a modifier with the padding of ODP let's pass in here the vertical alignment and we want to pass in here alignment center vertically okay so the next case here we want to create a composable for a player icon so we don't have the composable for this so we can create our custom composable let's call here our player icon so for this case here we can pass in here a modifier default modifier let's pass in here the icon and basically this is just going to be an image Vector let's pass in here the Border stroke and by default this is just going to be [Music] null also the background color okay so for this case let's create here a surface okay let's pass in here for the shape we want this to take up a circular shape so we can just call here circular shape let's pass in here and B and we can just pass in here our border border stroke the next case here is the [Music] modifier so we want to clip whenever we click it to be in a circular shape not a square and add here a clickable modifier and pass in here the on click and actually invoke it okay the next case here is to pass in the content color and here pass in the color and for the color here we can pass in the background color content here we can just use a box and here let's pass in here our modifier and actually use our icon the next case here is to pass in the content description and for my case I'm just going to keep it null so here we have our item and also we want to make this to be aligned Center so we can pass in here the content alignment and let's pass in here the alignment do Center okay so inside here artist information now let's create here our player icon and for the icon here we can just use our icons the next case here we can easily pass in here a border stroke okay the next case is to implement the click ability but for this case we want only to display the item so we're not going to pass in here the click ability of our modifier okay so the next case here we can just pass in here a little bit of a spacer so let's pass in here modifier okay so here we have the artist information for the first case now the second case here we want to display for example the title and the content so for this case let's just create here our column let's pass in here our text now for the text here we can just use here our audio and we can make this to be bold and here we want to use title large and if there are any overflow we want to clip them so we can just call here text overflow do clip and pass in here our modifier and give it a modifier of weight 1f so that it cannot push other items out of our screen and we want this to occupy only max line of one okay the next case here let's add here a spacer and for a space we want it to take only okay so the next case here let's pass in another text so this is just going to be displaying the title so let's pass in here the text so here we can use our [Music] audio and for example we can just call here display name or we can just pass in here the artist so let's just call here the artist and we want to use the font weights our case we want to use normal and for our style here we want to use a body small and whenever we have overflow we can just clip it and for the max lines also we want it to take only one okay so for this case we can easily just call here our artist info and we have to pass in here our audio and also pass in here a modifier now the next case here is to create a media controller that is just a controller that is going to help us to pause play and do other things so for this case let's just come below here and create a composable function and call this media player now we can easily check his audio playing and pass in here the on start and we can easily pass in here the vertical alignment and we want to call alignment do Center vertically and the next case here is to pass in the modifier and we want the H to be 56 DP and the next case here is to pass in the party this to be for DP now the first case here we want to display the player icon so we can just pass in here the player icon item and basically here we can pass in our icon and we want to check here if is audio playing so if our audio is playing so basically here we can just use our icons and if this is not the case so we can just add here an else part and we can just use here our icons. default okay the next part here is to uh manage our clickability and we don't pass in here the Border stroke so we want it to be only free okay so for this case we can just call here our own start and basically it's just going to be invoked here now the last part here is to add here a sper okay so the last part here is just to pass in here an icon so I'm going to pass in here the image vector and the next case here we can just pass in here a modifier and pass in here to be now so basically here I'm going to implement only one handle that is going to help us to skip to the next so if you want to handle the forward and backward you can just easily add here another icon that is going to handle this so for my case here I have the play which is just going to be handling the start the play or posst and also here we have the icon that is going to also help us to skip to the next uh media playing so this is just our media controller here implemented so for this case let's just navigate inside here our artist information and pass in here our media player controller and let's check here is audio playing and pass in here our audio playing on next and other things yeah because they're just going to be invoked directly okay so we have here our media player the last thing which I want to view here is the slider so this slideer is just going to be like a progress that is going to tell a user hey the media is play and if you want to seek to a certain position you can easily slide that so we have here a composable function so we can just call this a slider and pass in here the value and actually the value is just going to be the progress and whenever our own value changes whenever the user drags that slider here we want to call our own progress and actually pass in here it and pass it the value now we want to define the value range so basically our value range is going to start from 0 f to 100f so basically we're going to start from 0 to 100 that's why inside our view model We performed the calculation from 0 to 100 so we have like a percentage way okay so for this case let's just go inside here our Bottom bar and actually now we have is audio playing so this is just our Bottom bar player here being implemented fold content so here we want to use a lazy column so we can just call here our lazy column and here one thing which I want to change is just the content and content padding in order to remove these errors here so here we have our content padding and everything is looking perfectly so the next case here is just to take the item index so for this case we can just call here our items index and I want to get our audio list and here basically we have to initialize the index and the item so for index here we can just leave it as it is and here we can rename it to audio now here we can easily create an audio item so let's just navigate below here and create a new composable and for this case we can just call this audio item now let's just call here an audio and also create an item click here so whenever our item is going to be clicked so we want to perform here an an action so for this case let's create here a card and for this case we can pass in here a modifier the first case we want to fill the marks with so we want to provide here a padding of 12 DP and make this to be clickable and inside here now we can just invoke on our on item click here and we can use here our audio. ID in order to invoke the item here so here we're not going to pass anything and what we want to do here is to change this int here and to pass in back the cability so for this case we have here our card now let's create here a column and for our column here let's pass in here a modifier so the first case here we want to give it a weight of 1f and give it a padding of 8 DP also now the next case here is to provide the vertical Arrangement and we want to arrange it to the center okay so the first case we can just create here a spor and give it a 4dp now let's create here a text and here we can use our typography now let's add another text here okay the next case here we can easily display our timestamps so for case let's just create here our text okay the next case here let's pass in here the text and we can easily create here a simple function that is going to help us to calculate the time stamps so let's just create here another private function and here we want to pass in the position or the duration you can name whatever you like so here this is just going to be okay so one thing here we want to get the total seconds so we can easily create here a total seconds so we can use here a flow and basically calculate here our position divided by one exponent of three which is just a th and change it to int and also calculate our minutes so for our minutes we can just calculate here our total second divided by 60 and calculate the remaining second for example we can just calculate our total second minus minutes multiplied by 60 we change it back to seconds okay so here we have and we can just try to return if the position is going to be less than zero and then we can easily just return this and else we can easily format this so we can pass in here our percent sign and pass in D and let's format this and pass in here our minute and remaining seconds and basically get here our time stamp okay so for our text here we can just call here our time stamp now so here you can pass in the duration or you can pass in here the audio directly so for my case I'm just going to pass in the duration so I'm just going so for example going pass in here the progress in order to calculate this so for my case I'm just going to pass in the duration and call this too long now after this let's me add here a little bit of a spacer and give it a space of H DP okay so our audio item is ready the next case here we can just navigate back inside here and we can just call our audio item and here basically pass in here our audio so we can just easily invoke it here we can just call here our on item click and pass in here the index which is just the selected item and now here our home screen is actually complete so we can easily preview it here so let's just go below okay now let's create here a new composable and call this home screen brief let's add here at preview annotation and call here show system UI and make it to be true okay so here we can just call call here our jet audio theme and we want to call here our home screen okay let's give it here the progress we can just give it 50F okay so for this case we can just duplicate here to have two items okay so basically here we have our home screen ready now let's try to rep preview this and now here I can see everything is looking perfectly so we have here our title and our duration here is formatted correctly so this was just a bit here okay so now our home screen here is complete so the next case let's just navigate inside our main activity okay so the first case we have to annotate this with at Android entry point now the next case here we can optain the reference to the view model so let's create here a private variable and call this view model and actually this is just going to return us with the audio view model we can use a delegate method and use the view modeles and actually this one is going to give us the view model the next case here we want to check if our service is running so I can create here variable and call this is service running and we can initialize this to force okay so the next case here we can easily check the permission state so we want to check if we have the state to read the external storage or if not then we tell the user hey you have to access or you have to Grant this permission so for this case we can write here a variable and create here a permission a permission State and we can pass in here a remember so we are going to use here Google compan stally to help us to remember permission state so here we can use the Manifest and we want to use this Android manifest here and we want to call do permission read external storage okay so we have to opt in because here we are using a Google accon regularly so as you can see we have to use this experimental permission apis for this case Okay so the next case here we have to obtain the life cycle owner so let's create here the life cycle owner and we can easily obtain the reference from the local life cycle owner. current by using jar compost so here we have to use a disposable effect because this is just a side effect so we can just call here disposable effect and for the part of key here we can easily pass in the life cycle owner so whenever the life cycle changes then we have to retrigger this so for this case we have to create the Observer so let's create here The Observer and we can use here our life cycle event Observer so we have this listener here which we want to uh invoke it so for this case here we are going to not use the first parameter and the second parameter is just the event okay now let's write here an if statement so if the event is going to be equal to life cycle so we want to launch now the permission request so we can just call here our permission State launch permission request because now we are inside the own reg now here let's just add the own dispose remove this error first then we're going to handle it here so here we can just call here our life cycle owner with life cycle and we want to add Observer and basically pass in here our Observer to add it now let's handle here the life cycle when is just disposed so we leave our composition so for this case we can just call here our life cycle owner life cycle. remove Observer and basically remove our Observer for this case we can easily handle this okay so we can just move this let's just keep it outside here okay so inside here now we can easily Now call here our home screen okay now let's pass in here our progress so we can just call here our view model do progress the next case here is whenever our on progress change so here we can create our own progress or we can just call here our view model and we want to pass in our own UI event now we can just call here UI event and we can just call here SE to now let's pass in here is audio play so basically here we can use our view model but is playe the next case let's pass in here the the audio list and basically we can just call here our view model audio list and let's pass in here our current playing audio and we can use here our view model that currently selected [Music] audio and the on start here you can use here our view model on youru event and basically pass in here our UI event do play or pause the next case here is whenever our item is clicked so we can just pass in here on item click and now here we can use here our view model on UI event and we can pass in here our UI event and we can use here our selected audio change and we want to change it we can pass in here the index and we want to start a service whenever we click an item if it's not running so for this case we can create here a private function so now let's just collapse this and create here a private function and let's check here if not service is running so if the service is not running then we have to start the service let's create here the intent first let's pass in here this for the context and here what we want to start is the J audio service and we have to pass in the class reference here okay so now let's just a start to check here so we can call here start for ground service and basically pass in here the intent okay so we have here an error and we can easily use around here a check and check if the for ground service is going to be greater than API 24 then we have to use it okay else here we can just start a service and pass in here the intent in order to start the service and basically is service running we can just reinitialize this back to true so you can easily handle this differently but for Simplicity I have just used this a simple way okay so for this case inside our own item click so whenever click our item you want to start our service so for this case we can just call here start service and basically our service is going to be started now the next parameter here is just the OWN next okay so we have to rename this not starting with the capital letter here okay the next case here is to there on next and here we can use our view model on UI event and basically use here our UI event see to next so these are just the methods which I want to implement so we have several other methods which we have used inside our UI event so you can easily follow the similar button to expand your application okay so I think here our home screen is complete so the next case here is just inside our Android manifest we have first to specify the permission which we want to use so we can just uh add this to permission here so the first permission here is just to read the external storage and let's just set here the max xdk to be 32 okay the next case here is just the foreground uh service so we want to ask the permission that we require to use this type of permissions and notify the user hey we want to use this type of permissions so after we add here our permissions the next case here we have to add a service so because here inside we are going to use a service so for this case we can create here a service tag and it automatically generates here we want to use this type of service here okay so the next case here you want to add other parameters here and we want to make this to be true Android exported and another case here is Android foreground service type and basically our service type is just the media playback okay so after we Define this we have to Define here an intent filter and inside our intent filter we can Define here the action so we can use this Android X okay so we have added here our Android X media3 session. media service so after we include this service here now we tell the Android OS okay so we have here media playback service which we are going to require and the next case here which we have to finalize is just to create an Android application that we can easily tell Dill to generate all of the dependencies so for this case inside here our top label package we can easily create here our jet audio application and this class here is going to inherit from the application class and here we have to annotate with at Hil Android app our application is almost complete now let's try to run here application and see the outputs when we try to run our application we are getting here this error and able to start activity and as you can see here it's just held hit activity must be attached to a he Android application so it suggest us that we forgot to declare this inside our manifest and basically we did forget in inside here application so we have to specify the name and we have to specify the name of the class which we have generated now let's try to run again okay so now our app is launched successfully and as you can see here we have the permission request so let's just allow it and whenever we try to play here an audio so for example here I can just easily locate so this are just the audios which I have inside here so let me just click here and play I don't know if you can hear them so actually the audio is playing but we have one major problem here so as you can see whenever we click here we not going to be updating this so we have to fix this problem here because this uh is giving us uh the progress buy is going to go full whenever we play a media item so this is not ideal so one thing we can just go inside here our audio view model inside here our view model when we go inside our UI event and as you can see inside here the update progress we're not changing the progress so we have first to change the progress and use the UI event do uh new progress and we have to reinitialize this so this one is going to reinitialize to create the progress changes and create that movement now another thing which we did not handle is inside here so first uh before we just skip here inside our view model and another thing which we forgot here is just whenever our view model is going to be cleared so we have to remove the resources so for this case we have to all the we override here the uncleared now here inside our uncleared we want to change the state we can do we can use here our view modos scope. launch and basically we can call here our audio service Handler and we have to update our player event and for this case here we have to pass in the player event and we can just call here player event. stop so this one is going to help us to stop the player event and release the media So currently we did not do it okay so after that we have to go inside here our jet audio service Handler and inside here one thing which we forgot to add here is just the init block so the init block here is going to initialize it to a listener and to make the EXO player actually use this class here to listen so the audio is playing but we are not getting here the output so for this case we have to tell the listener hey we are just listening to the audio so for this case I can just call here our EXO player and call add listener and basically now here we can just call this and for this case this is just going to add The Listener now the next case here which we have to fix is just a simple thing and inside here our Global scope we just calling here dispatcher doio and this is not actually required to be called inside a dispatcher iio because it's required to be called inside a main dispatcher so it's going to be accessed in the input output uh thread other than the main thread and this actually is required to be accessed inside the main thread and this is going to cause our application to crash actually so for this case we have to change this dispatcher here to Main and for this case let's try to rerun again so uh app is launched successfully and right now here let's try to select any type of audio which you have so for my case I can just click this one here and see so I don't know if you can hear them because I'm using headphones here okay so as you can see here now the progress is just updating and it's not like the first time we just went to the end here and whenever click here it's just going to pause and as you can see here we have a controller that is going to help us to control this we can easily pause here you did it guys you have built a media playback app with media 3 and Jaa compose you have created stunning and interactive uis that work seamlessly with the audio playback functionality I hope you had fun and learned a lot from this tutorial series if you have any questions or suggestions please leave them in the comment section below I'll do my best to answer them thank you for watching and following along this tutorial series if you like this video please give it a thumbs up and share it with your friends and fellow developers and if you haven't subscribed to our Channel yet please do so and hit the Bell icon to get notified of our future videos thank you for your support and happy coding see you in the next video bye-bye
Info
Channel: HoodLab
Views: 6,953
Rating: undefined out of 5
Keywords: jetpack compose, jetpack compose tutorial, jetpack compose android, kotlin, android
Id: ZTLNSN2umjs
Channel Id: undefined
Length: 68min 13sec (4093 seconds)
Published: Sat Sep 09 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.