3

I am using the FusedLocationProvider API for an app. The location of the device should be updating regularly since the user is expected to be moving around all the time, and the app should behave differently depending on the current device location.

In order to keep the Main Thread clear from network requests I wanted to move the code for retrieving location data into a seperate loader. However, I have no clue where to put this part of the code:

locationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(UPDATE_INTERVAL)
            .setFastestInterval(FASTEST_INTERVAL);


        try{
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
        }catch (SecurityException a){Log.w(TAG,"No location permission.");}

If I put it in the LoaderClass and call this method in loadInBackground(), there will be the error java.lang.NullPointerException: Calling thread must be a prepared Looper thread.

It also feels very wrong to call the Loader again and again. So my question is how can I implement requestLocationUpdates using Loaders so that the Loader updates the changed location which I can retrieve in onLoadFinished() and update the corresponding UI? And what should I do with the method onLocationChanged() of the Location Listener which is needed to be overridden? Or is there perhaps another effective way to move the FusedLocationProvider into a background thread?

It would be really great if someone can help me here, many many thanks!

rfn123
  • 151
  • 3
  • 12

1 Answers1

2

Or is there perhaps another effective way to move the FusedLocationProvider into a background thread? It would be really great if someone can help me here, many many thanks!

If you wanna receive location updates in background thread, you can use Looper version of the requestLocationUpdates method.

requestLocationUpdates(GoogleApiClient, LocationRequest, LocationListener, Looper)

In that case, onLocationChanged method will be triggered on the looper's thread.

private HandlerThread mLocThread;
private void initThread(){
    mLocThread = new HandlerThread("locationThread");
    mLocThread.start();
}

private void requestLocUpdates(){
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, 
    locationRequest, this, mLocThread.getLooper());
}

@Override
public void onLocationChanged(Location location) {
    // locationThread thread
}
blackkara
  • 4,900
  • 4
  • 28
  • 58
  • thanks for the quick reply! I'm really sorry that I'm not that experienced with android yet, therefore I don't quite understand what a Looper thread is in my case. Does this mean I have to somewhat create a new background thread? – rfn123 Dec 22 '16 at 22:47
  • 1
    Yes you are right, but these topics aren't something that can be described in just a comment. I updated the answer to give better idea. You can check this [link](https://blog.nikitaog.me/2014/10/11/android-looper-handler-handlerthread-i/) to get idea what thread and looper are. – blackkara Dec 22 '16 at 23:31
  • Ok I read the link you gave me and several other tutorials/documentations, but there are still some things unclear: so do I have to create a runnable in which I override the OnLocationChanged() ? or do I have to include the e.g. requestLocUpdates you wrote above in the runnable? – rfn123 Dec 23 '16 at 22:41
  • @Blackkara is it right to say that the location update will happen on the thread of the looper I pass in ? Also great link about looper and threads. – rgv Mar 24 '17 at 20:44
  • 1
    @NoobDogg yes right, check the current thread inside onLocationChanged() method – blackkara Mar 25 '17 at 02:55