Tracking User Location in the Background - MVVM Running Tracker App - Part 13 — Transcript
Full transcript
- 0:01[Music]
- 0:10hey guys welcome back to new video so in
- 0:13this video we will implement the full
- 0:15functionality of our user tracking that
- 0:17means we will get the users location on
- 0:19a consistent basis and then simply save
- 0:21those locations to be able to later
- 0:24observe on changes on those locations so
- 0:27whenever we get a new location by the
- 0:29user then we can simply react to those
- 0:31changes in our tracking fragment and to
- 0:34be able to observe on those changes we
- 0:36will have live data objects here inside
- 0:39of a companion object in our tracking
- 0:41service so we can easily observe on
- 0:44those from the outside first of all I
- 0:46want to have a live data object with our
- 0:48current tracking States so just a
- 0:49boolean if we are currently tracking the
- 0:51user location or not that will be a well
- 0:54is tracking and we're going to set that
- 0:58to immutable live data of type boolean
- 1:05so we will just whenever the tracking
- 1:08state changes post the new value instead
- 1:10of this is tracking live data and then
- 1:12we can observe on those changes from the
- 1:14outside and we will also have another
- 1:16life data here for this video which is a
- 1:18little more complex than this boolean
- 1:21life data because this life data I want
- 1:23to create here will hold all the tracked
- 1:25locations from a specific run and the
- 1:28intuitive answer here is to just save
- 1:31that as live data of list of coordinates
- 1:34so we just have a list of several
- 1:36coordinates and then we will simply draw
- 1:39a line later on after those coordinates
- 1:41inside of that list but this intuitive
- 1:43answer won't help us much here because
- 1:45it will produce a bug later on if we
- 1:47implement it like that and why that
- 1:49happens or why we why that is not enough
- 1:51I want to show you in my emulator in the
- 1:54actual final app here you can see I can
- 1:57simulate a route that the emulator will
- 1:59run let's click on play route and start
- 2:03a new run then you can see that the
- 2:07tracking stars it's working perfectly
- 2:09fine and a single line here consists of
- 2:12several coordinate
- 2:13so that is basically just a list of
- 2:15coordinates and that is pretty clear I
- 2:17guess but if we now click on stop
- 2:20then the emulator is still continuing on
- 2:23that route but we don't track right now
- 2:25because if we now click on start again
- 2:28so we continue that route then of course
- 2:31a new line needs to start and it
- 2:33shouldn't connect this line with the new
- 2:37line instead during that time inside of
- 2:40this window where we didn't track we
- 2:44also don't have any coordinates and we
- 2:46don't want to display them in our map
- 2:47because let's say the user run and then
- 2:51he stopped the service then he walked a
- 2:52little bit and then he clicked on start
- 2:54again so he wants to continue running in
- 2:57that case we of course don't want to
- 3:00connect the old run with the new run so
- 3:03in the end we can say that each single
- 3:07line we have here is a list of
- 3:10coordinates but since we have several of
- 3:12those lines that live data that we want
- 3:15to create now must be a live data of
- 3:18list of lists of coordinates so we have
- 3:20a list of several lists that hold
- 3:23coordinates and that sounds pretty
- 3:26complex right now let's actually stop
- 3:28that tracking here and it will actually
- 3:30get clearer when we implement that
- 3:32so let's actually implement that that
- 3:34will be a well called path points so
- 3:38just the points on our run path and that
- 3:41will be immutable live data of type
- 3:44mutable lists of type mutable lists of
- 3:51type let long if you don't know what let
- 3:55long is that is just the coordinate
- 3:58format of maps since the earth is not
- 4:01flat and rectangular well who knows but
- 4:04you cannot simply have an x and y
- 4:06coordinate format for describing
- 4:09coordinates on the earth and that's why
- 4:11we have that special lat/long
- 4:13coordinates format here so again because
- 4:15this is really a complex type here first
- 4:18of all we have our mutable life data
- 4:19that just allows us to observe on
- 4:22changes of this type later on so
- 4:25whenever we get a new coordinate in
- 4:27of our polyline list then we can observe
- 4:30on that change we can see that there is
- 4:32actually a change in our tracking
- 4:34fragment and draw the actual line on our
- 4:37map view then we have that mutable list
- 4:40of mutable list of lat/long one mutable
- 4:44list of let long here is just a simple
- 4:46polyline just a line of coordinates on
- 4:50our map and since we can stop our
- 4:53service and resume it we simply have
- 4:55several polylines or we can have several
- 4:57polylines in our map so we have a list
- 5:00of polylines I think if we describe it
- 5:04like that that immutable list of that
- 5:06long is actually a polyline then it's
- 5:08much clearer so what we could do here is
- 5:10actually define a type alias for that
- 5:12that is just a different name for that
- 5:14complex type and we can do that by
- 5:16writing type alias and let's do that for
- 5:20a polyline and define that as a mutable
- 5:23list of lat/long and then we can also
- 5:29have a type alias for several polylines
- 5:31so polylines is equal to a mutable list
- 5:35and now we can say a mutable list of
- 5:37Tolley line and if we now take that
- 5:40whole block here and replace it with
- 5:43polylines it's actually much clearer so
- 5:47I hope that is clear now and since we
- 5:49just created that life that are here and
- 5:52here that life data just doesn't hold
- 5:55any value right now and that's why I
- 5:57want to create a function here that just
- 5:59posts initial values inside of those
- 6:01live data objects so private function
- 6:03post initial values and inside of this
- 6:07function we just want to use our is
- 6:09tracking live data and call post value
- 6:12and initially we are not tracking so we
- 6:15post the value false and we want to use
- 6:18our path point live data and post the
- 6:21value mutable list off so just an empty
- 6:25list because we don't have any
- 6:26coordinates in the beginning the next
- 6:28function we want to implement here is a
- 6:29function that adds an empty polyline so
- 6:32an empty list of lat/long coordinates at
- 6:34the end of our polylines list because
- 6:37when we post our tracking and then we
- 6:40zoom it again then we simply need to add
- 6:42that empty list first before we can add
- 6:45coordinates in it and let's actually do
- 6:48that down here that will be a private
- 6:51function add empty polyline and we are
- 6:56going to set it to path points dot value
- 6:59so the value of that life data that is
- 7:02in this case our whole polylines list so
- 7:05all of our polylines and we call that
- 7:08apply on that and here we can just call
- 7:12add so we want to add a list to that
- 7:14path points and we want to add an empty
- 7:17list so just mutable list off and then
- 7:20afterwards we want to use half points
- 7:23dot host value and use this because
- 7:27we're instead of this applied log here
- 7:29this refers to this current polylines
- 7:32object and because we added that new
- 7:35polyline there is a change so we want to
- 7:38post the new value of that so our
- 7:40fragment will be notified about that
- 7:42change later on but what could also
- 7:44happen is that this value is null and in
- 7:47that case we won't execute that block so
- 7:49we won't add an empty polyline in that
- 7:51case we also need to take care of this
- 7:54case in case it is now because then we
- 7:56simply want to post the initial polyline
- 7:58so just the first empty polyline let's
- 8:01use path points dot post value mutable
- 8:05list of type mutable lists off so here
- 8:09we just initialize our polylines list
- 8:12and we also add the first empty polyline
- 8:16inside of that list so we can easily add
- 8:19coordinates to that and start the
- 8:21tracking and then we can simply call
- 8:23that at empty polyline function inside
- 8:25of our star fragment service function
- 8:27because when we start our service we of
- 8:28course want to I'm at that first
- 8:30polyline that first empty polyline so
- 8:33simply call that function at the start
- 8:35of that start program service function
- 8:36and now that we have that function that
- 8:38adds an empty polyline at our polyline
- 8:41list we also need a function that adds a
- 8:44coordinate to the last polyline of our
- 8:46polyline list and for that I will create
- 8:49another function a private function at
- 8:53half-point and that will take a location
- 8:56as a parameter which is of type location
- 8:59that is just very similar to a lat/long
- 9:02coordinate but it holds more information
- 9:05about a specific location but we only
- 9:07need the latitude and longitude
- 9:09coordinates of that location parameter
- 9:11here but that's just the type that we
- 9:13get later on when we get the user's
- 9:15location so instead of this at power
- 9:19point function we want to check if that
- 9:21location that we got here is actually
- 9:23not equal to null and I forgot to make
- 9:25it a nullable type here that is
- 9:26important because the locations we get
- 9:28later on will be nullable too so we
- 9:31simply use location and check with let
- 9:35if that is not equal to null so if we go
- 9:37inside of this lab block and that means
- 9:39that location is not equal to not and
- 9:41now as I said we have that long
- 9:43coordinates inside of our polyline
- 9:45instead of a single polyline and here we
- 9:48have a location and that is not a
- 9:50lat/long coordinate right now
- 9:51so we someone need to convert that but
- 9:53that is very easy to do we just have a
- 9:55well position and set it to new led long
- 9:58and that consists of two parameters the
- 10:01latitude and the longitude we can get
- 10:04the latitude by writing location dot
- 10:08latitude and location dot longitude and
- 10:12now what we want to do is we want to add
- 10:15this position to the last polyline of
- 10:18our polylines list so we will use our
- 10:21path points live data again dot value
- 10:24question mark apply so we make that null
- 10:28check here and here we want to get the
- 10:31last polyline of that and since that is
- 10:33a mutable list here we can simply use
- 10:35last year to refer to the last index of
- 10:38that list and since that last index is
- 10:41also list the list of let long
- 10:44coordinates we can add a new coordinate
- 10:47here and simply pass our position and
- 10:49since we changed something in our path
- 10:52points like that we also want to post a
- 10:55new value so path points dot post value
- 10:58and simply write this and that's already
- 11:01it for this ad path point function the
- 11:03next step is to define a location
- 11:05callback because 2 X
- 11:07get those location updates what we will
- 11:09use here is a so called fused location
- 11:11provider client that is just something
- 11:14that we can use to request location
- 11:16updates so it will basically deliver us
- 11:19on consistent basis with new location
- 11:21updates whenever the location changes or
- 11:23we can set an interval for that when we
- 11:25want to get a new location update and
- 11:27then simply deliver them to us and for
- 11:30that we will just need that callback to
- 11:32get the actual location results let's
- 11:35define that up here Val location
- 11:38callback which is an anonymous class so
- 11:41of type object : location callback call
- 11:45the constructor here and here we press
- 11:48ctrl + o and we want to implement that
- 11:52function on location result then we want
- 11:56to rename that p0 parameter here
- 11:58pressing Shift + f6 to result because
- 12:03that's a little bit more clear of course
- 12:05and in here we want to check if is
- 12:08tracking that value and also assume that
- 12:12this is not equal to now because at this
- 12:13point there is no way this can be now so
- 12:16this line just means we want to check if
- 12:19we are currently tracking because only
- 12:21then we want to add coordinates of
- 12:23course and then use that result
- 12:25parameter here so the location result to
- 12:30make an object here and use locations
- 12:34because that will hold the locations of
- 12:36that result which will usually only hold
- 12:38a single location but that is still a
- 12:40list so we want to make a null check
- 12:42here again in case those locations are
- 12:45now if they are not now let's actually
- 12:48call that locations if they are not now
- 12:53we just want to loop over them so for
- 12:56each location in locations and simply
- 13:00call our function at path point and past
- 13:03that location
- 13:04so all that callback does now is
- 13:06whenever we retrieve a new location
- 13:08which is saved in that result variable
- 13:10we just add that location to the end of
- 13:13our last polyline and now the last real
- 13:16function we need to do for this video is
- 13:18a function that will up
- 13:20location-tracking so whenever that is
- 13:23tracking value here instead of our life
- 13:25data changes we also want to update the
- 13:27location tracking because if it changes
- 13:29from false to true so if we want to
- 13:31start a location tracking we need to
- 13:33explicitly request those location
- 13:35updates and if it switches from true to
- 13:38false so if we stop the location
- 13:40tracking we don't want those update
- 13:42anymore and for that I will define a
- 13:44function that will be a private function
- 13:47update location tracking which will take
- 13:51the is tracking parameter as a boolean
- 13:53in the parameter list here and inside of
- 13:57this function we want to check if we are
- 13:59currently tracking so if is tracking is
- 14:02equal to true if it is we also want to
- 14:05check if we actually have the location
- 14:07permissions so if we are allowed to
- 14:09track so let's make another if check
- 14:12here if tracking utility that's why we
- 14:15have that function that has location
- 14:17permissions and context is just this
- 14:19year since we're instead of a service
- 14:21class there is no problem so if we have
- 14:24the location permissions then we want to
- 14:26request location updates and for that we
- 14:28need a location request which will just
- 14:31hold some parameters regarding our
- 14:33location updates I will call this well
- 14:35request and that will be a location
- 14:38request dot apply and here we can make
- 14:43some changes on that location request
- 14:45first of all we want to set the interval
- 14:47of that location request so how often
- 14:49will we actually get our location
- 14:52updates and for that I want to set a
- 14:54constant in our constants file and now
- 14:57we kinda have to set it the average
- 14:59interval at which we will get location
- 15:01updates that's not super accurate but
- 15:04let's set that by writing a consul
- 15:07location update interval and I will set
- 15:11that to 5,000 milliseconds so every 5
- 15:15seconds we will get a location update
- 15:16but what this location request also
- 15:19takes is the fastest update interval so
- 15:22the interval which is basically the
- 15:25lowest interval possible so we will
- 15:29never actually get more updates than
- 15:32this fastest location
- 15:33interval let's call this fastest
- 15:36location interval and I'll set that to
- 15:392,000 milliseconds so two two seconds so
- 15:42it will never happen for example that we
- 15:44get location updates each second at
- 15:46minimum we will have that two seconds
- 15:48interval which is just to save memory
- 15:51resources but as I said that really
- 15:53differs it could be that we receive a
- 15:55location update after 3 seconds after 6
- 15:57seconds and that is just a value that is
- 16:02approximately to the interval that we
- 16:04set here then we can go back to our
- 16:06tracking service and assign the interval
- 16:09here to location update interval then we
- 16:14want to assign the fastest interval to
- 16:17fastest location interval and what is
- 16:21also very important here is the priority
- 16:25which we will set to priority priority
- 16:31high accuracy import that here which
- 16:35just means we want to get accurate
- 16:37location results here and as I said to
- 16:40actually be able to request those
- 16:41location updates we need a so called
- 16:43fused location provider client let's
- 16:46actually scroll up and create it up here
- 16:48which is Lady Navarre fused location
- 16:51provider client and instead of our on
- 16:55create function from our service we want
- 16:57to initialize that fused location
- 16:58provider client so let's overwrite on
- 17:01create here and set that fused location
- 17:05provider client to new fused location
- 17:08provider client which takes the context
- 17:11so we just passed this year and then we
- 17:13can scroll down again to our update
- 17:15location tracking function and after
- 17:18that applied lock we want to use that
- 17:20fused location provider client and call
- 17:22that week rest location updates and that
- 17:26now takes our location week rest as a
- 17:28parameter so we just passed that request
- 17:30here it will take the callback we
- 17:34defined down there so our location
- 17:37callback and we need to pass the looper
- 17:39which is just blooper dot get main
- 17:42looper and as you can see it throws us
- 17:45an error here because
- 17:47it wants a permission check by us but we
- 17:49actually did that permission check here
- 17:51but since we do it with that easy
- 17:53permissions library it doesn't recognize
- 17:54that so let's click on that press alt' +
- 17:57enter' and suppress this warning with
- 18:01this suppress linda annotation here and
- 18:03then this error will go away and now in
- 18:05case that is tracking variable is false
- 18:08so we stop the tracking then we want to
- 18:10remove those location updates again so
- 18:12let's add an else block here and simply
- 18:15use our fused location provider client
- 18:17dot remove location updates and you can
- 18:20see we simply need to pass the location
- 18:22callback here so let's do that and that
- 18:24is everything you need to do and now we
- 18:26only need to scroll up to our on create
- 18:28function here first of all I want to
- 18:30call that post initial values function
- 18:31here before we forget that and at the
- 18:35end of uncreate we want to use our is
- 18:38tracking live data and call that observe
- 18:40on that has this as a life cycle ona and
- 18:43that is only possible because we
- 18:45declared that service as a life cycle
- 18:48service otherwise we couldn't pass a
- 18:50service as a life cycle
- 18:51owner and as a second parameter we will
- 18:53pass an observer here and here we just
- 18:57get updates whenever our is tracking
- 18:59state changes and whenever that changes
- 19:01we want to call our update location
- 19:03tracking function and simply pass it
- 19:05here and when we start our service now
- 19:08then the only thing we need to do is to
- 19:10post the value true in our is tracking
- 19:12live data so that observed block here
- 19:14will actually be caught with the value
- 19:16true as a boolean then we will call up
- 19:18the location tracking with true and then
- 19:21we will simply request those location
- 19:23updates so let's scroll down to our
- 19:25start foreign service function and here
- 19:27we just want to call is tracking the
- 19:29post value true and to test that
- 19:31functionality I just want to scroll up
- 19:33to our location callback or on location
- 19:35result function because that's the
- 19:37function where we get a new location and
- 19:39here I just want to add a lock statement
- 19:42with timber timber D new location and
- 19:46simply pass of a location that longitude
- 19:49no latitude first latitude and then
- 19:54location dot longitude
- 19:58and if we now run our app and take a
- 20:03look in our emulator then you can see
- 20:05that emulate a menu here or the options
- 20:08for that emulator on those three little
- 20:10dots here let's click on those and then
- 20:12you can see we have a location tab and
- 20:14instead of this location tab we have a
- 20:16routes tab and instead of this routes
- 20:19tab we can now set up our custom routes
- 20:21that the emulator will simulate so if we
- 20:25want to do that we need to go into this
- 20:26text field here and type the destination
- 20:31where we want to simulate that route too
- 20:33so in my case I will just choose Hamburg
- 20:36here in Germany choose that one and now
- 20:40I can see we can start that route let's
- 20:42click on that icon and now we have to
- 20:45set up the start point and in my case
- 20:48that is my hometown Hannover choose that
- 20:52one and if we now click on safe route
- 20:55then we can give it a name I will just
- 20:57click on save here you can see that
- 21:00route is saved in our safe routes tab
- 21:02here and now we can choose a playback
- 21:05speed so how fast that emulator will
- 21:07simulate that route I will choose four
- 21:09times here and click on play route and
- 21:12now if we zoom in you can see that the
- 21:17position is actually walking that route
- 21:20or driving that route or whatever and if
- 21:22we now go into our emulator we will
- 21:25actually receive those location updates
- 21:28let's open lock it here and choose the
- 21:33correct emulator of course open the
- 21:35emulator here click on the floating
- 21:37action button and if we now click on
- 21:41start the tracking will start and you
- 21:44can see we receive location updates with
- 21:46the latitude and the longitude exactly
- 21:49as we want it so everything is working
- 21:52perfectly fine I hope this video was
- 21:54helpful for you even though this was
- 21:56very long but I just wanted to set up
- 21:59that hole location stuff in a single
- 22:01video because that kind of belongs
- 22:04together and I just wanted to have that
- 22:06in a single part and yeah if this video
- 22:08helped you please leave a like and
- 22:09subscribe to my channel if you haven't
- 22:11already have
- 22:12stay tuned the next video bye-bye
- 22:19[Music]
About this transcript
This page contains the full transcript of Tracking User Location in the Background - MVVM Running Tracker App - Part 13 by Philipp Lackner, generated from the public captions YouTube serves with the video. The transcript has 3,695 words across 505 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.