Alin
Alin

Reputation: 14581

Position tracking issues on background service in Android

Details:

I have a service that needs to do the following: - listen constantly for GPS locations, with 50 meters as parameter (works fine) and send it to a server - each 60 seconds, if no GPS location was read, start listening for a Network location and send it to the server

This may sound weird, but this is the project requirement. So the user is constantly being tracked using GPS. When he stops, or GPS is not locked, or is inside a building, every 60 seconds start a quick Network location read, and send this location to the server. As the service uses the same thread as the main app, each server update is done in its own thread. And another important thing: each location read should be sent one after another, so for instance if the user is driving, and multiple reads are done, each should be send to the server, after the previous one has been sent. That's why I decided to use ScheduledExecutorService as I can submit threads and they will be execute one after another.

Here is the code:

private ScheduledExecutorService scheduleTaskExecutor;
Handler locationHandler = new Handler();
private Location lastNetworkLocation;

@Override
    public void onStartCommand() {
        scheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();

        //prepare to execute Network reading every 60 seconds
        scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                    initNetworkReadings();

                    //usually a network location read is done almost instantly
                    //however after 5 seconds I check if a location has been read by the Network listener inside the locationRunnable
                    locationHandler.postDelayed(locationRunnable, 5000);
                } 

            }
        }, 60, 60, TimeUnit.SECONDS);

        locationRunnable = new Runnable() {
            @Override
            public void run() {
                    if (lastNetworkLocation !=null){
                         //send location to the server if valid
                    }
            lastNetworkLocation = null;
            }
        }
    }

    private void initNetworkReadings() {
        locationManager.removeUpdates(locationListenerNetwork);
        try {
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
        }

        if (isGpsEnabled) {
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
        }
    }

    LocationListener locationListenerNetwork = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        lastNetworkLocation = location;
        // stop listening for Network locations
        locationManager.removeUpdates(locationListenerNetwork);
    }
    ...
    }

Each time I read a GPS location I add it to the threads queue as:

scheduleTaskExecutor.submit(new Runnable() {
        @Override
        public void run() {
            updateLocationOnServer(readLocation);
        }
    });

The problem I have is that the Network location listener never gets onLocationChanged() called,when I use it like in the code above, in the Runnable. BUT if I add on service start, the initNetworkReadings(), I get onLocationChanged() fired right away. So I believe it has something to do with being used in scheduleAtFixedRate. What do you think it could be the problem ? Anything bad in the way I thought of the workflow ?

Upvotes: 1

Views: 975

Answers (2)

Rabarama
Rabarama

Reputation: 73

Same problem, I have a background service that detect locations. If network is avaible, it uses networks, otherwise it uses gps.

It works well with many smartphones ( nexus s 4.1, galaxy nexus 4.2, galaxy note) , but with Galaxy s3 jb (4.1) network location never rises any location.

Same code with gps locations, works just fine.

Upvotes: 0

FoamyGuy
FoamyGuy

Reputation: 46856

What if you try to set up your repitition with a Handler and a Runnable instead of scheduleAtFixedRate()?

Handler h = new Handler();
Runnable run = new Runnable(){
    //Do your repeititive work here!
    h.postDelayed(run, 60 * 1000);
};
h.post(run);

Upvotes: 1

Related Questions