Android_guides: A good example of background service getting location updates

Created on 29 Sep 2016  ·  71Comments  ·  Source: codepath/android_guides

Please I really need help.

I'm facing a problem here. It is impossible to find A GOOD EXAMPLE of how create a service that must run in background and receive location updates. Also, all examples on developer.android.com are terrible, any one of them really works.

My app aim is get location updates in background, something which looks like so simple but unfortunately I could not find any good example about how to do it.

Most helpful comment

@veda2vratha thank you very much, I have tried these examples that you have sent to me. Actually they are both the same.

Testing it I could see in this example it runs every second requesting a very precisely location. So, I change it to every 20 seconds and 500m for distance which gives me a service running every 20 seconds.

Then I realise that I could be making a mistake about what I'm looking for. The point is, my app does not need a very precisely location in addition, it does not need to run every second ou minute. My app needs only collect relevant location position.

So, what I need indeed is a passive location collector. I've been told that Android OS can broadcast for any app in passive mode location position changes. This is great because reduce battery usage. So, my service location (listener location) will be fired only when Android OS has been request for location by other app for example, Google Maps.

After a few hours looking deep on location providers I found it which is called LocationManager.PASSIVE_PROVIDER. Thats is really cool, looks like exactly what I need.

Here I will share how my service looks like now.

Now, I would like to make a question, why any developer and even on Android Training do NOT talk about LocationManager.PASSIVE_PROVIDER? What is the matter about using it?

I would like to say tank you @veda2vratha again 👍

My Location Service:

package com.example.roberto.trainingbackgroundservice;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

/**
 * Created by roberto on 9/29/16.
 */

public class MyLocationService extends Service {
    private static final String TAG = "MyLocationService";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 1000;
    private static final float LOCATION_DISTANCE = 10f;

    private class LocationListener implements android.location.LocationListener {
        Location mLastLocation;

        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location);
            mLastLocation.set(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    /*
    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };
    */

    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.PASSIVE_PROVIDER)
    };

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate() {

        Log.e(TAG, "onCreate");

        initializeLocationManager();

        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.PASSIVE_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[0]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }

        /*try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[1]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }*/
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listener, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: "+ LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }
}

All 71 comments

@veda2vratha thank you very much, I have tried these examples that you have sent to me. Actually they are both the same.

Testing it I could see in this example it runs every second requesting a very precisely location. So, I change it to every 20 seconds and 500m for distance which gives me a service running every 20 seconds.

Then I realise that I could be making a mistake about what I'm looking for. The point is, my app does not need a very precisely location in addition, it does not need to run every second ou minute. My app needs only collect relevant location position.

So, what I need indeed is a passive location collector. I've been told that Android OS can broadcast for any app in passive mode location position changes. This is great because reduce battery usage. So, my service location (listener location) will be fired only when Android OS has been request for location by other app for example, Google Maps.

After a few hours looking deep on location providers I found it which is called LocationManager.PASSIVE_PROVIDER. Thats is really cool, looks like exactly what I need.

Here I will share how my service looks like now.

Now, I would like to make a question, why any developer and even on Android Training do NOT talk about LocationManager.PASSIVE_PROVIDER? What is the matter about using it?

I would like to say tank you @veda2vratha again 👍

My Location Service:

package com.example.roberto.trainingbackgroundservice;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

/**
 * Created by roberto on 9/29/16.
 */

public class MyLocationService extends Service {
    private static final String TAG = "MyLocationService";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 1000;
    private static final float LOCATION_DISTANCE = 10f;

    private class LocationListener implements android.location.LocationListener {
        Location mLastLocation;

        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location);
            mLastLocation.set(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    /*
    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };
    */

    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.PASSIVE_PROVIDER)
    };

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate() {

        Log.e(TAG, "onCreate");

        initializeLocationManager();

        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.PASSIVE_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[0]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }

        /*try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[1]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }*/
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listener, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: "+ LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }
}

also,i was confused with this problem these days,and found some mobile (maybe the Android Version caused)is ok,some is not work,can't get the location callback (location changed) in background.i have try your written service,didn't work after App switch to background

How can i call in MainActivity?
Can you please help me

startservice(new Intent(this,MyLocationService .class));
@vani-chikaraddi

You can try out Google's Locations API...

I want to display longitude and latitude how can i do that. I tried the following code but getting white screen

@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
longitude=location.getLongitude();
latitude=location.getLatitude();
Toast.makeText(MyLocationService.this,longitude + "yes" + latitude + " ",Toast.LENGTH_LONG).show();
}

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

"but how do I pass the location found back to my app,?" I have created a background app where the user determines how often (in minutes) location services should be activated. It then sends info to SMS, email or both. The easy way (which I use) to transfer data within an app is SharedPreferences. It looks so easy that I was at first sceptical about its use - but it has never failed me.

Thanks, I found I send it back in a broadcast.

@AndyCr15 , definitely one of the easiest way to do that is sending the collected data trough broadcast message. :-)

really helpful

very helpful. Thanks for sharing.

Hello

I am developing an app and there is one scenario in which I have to send user location on server every 15 min all is working but sometime current location is incorrect.

I need help to get current accurate location . I have created GPS Tracker - Using GPS provider and Network provider Now the issue is

  • I need location from GPS but when I remove Network provider and use GPS Provider only then Current Latitude & Longitude is 0.0 in Noughat & Marshmallow version.
  • If I used both GPS & Network then it returns wrong sometime .

Please suggest what I have to implement to get current & accurate location in Android app.

You can use

mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
and when it is connected

try {
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
longi = mLastLocation.getLongitude();
} else {
Toast.makeText(getApplicationContext(), "Unable to get Location Check GPS is ON", Toast.LENGTH_LONG).show();
showSettingsAlert();
}
} catch (Exception e) {
e.printStackTrace();
}

@RaziaSandhu Hi Thanks for your reply.
I need location without Google play services. This app is for dummy devices for security purpose So there is no play store and play services.

Hi,

I am working on Gps to open the plot details if the plot(lat,long)details is matched open the plot details otherwise it show a message , and it working for 5 plots after that if he is not in that plot and the plot is opend .
In other case when i restart the device again it works fine.
this is the problem i am facing can any one help me fast.. i have only one day to submit this work.

this is my location service class pice of code
boolean gpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean networkProviderEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (gpsProviderEnabled || networkProviderEnabled) {
            if (networkProviderEnabled) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    providerType = "network";
                    Log.d(LOG_TAG, "network lbs provider:" + (location == null ? "null" : String.valueOf(location.getLatitude()) + "," + String.valueOf(location.getLongitude())));
                    updateLocation(location);
                }
            }

            if (gpsProviderEnabled && location == null) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
                if (locationManager != null) {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    providerType = "gps";
                    Log.d(LOG_TAG, "gps lbs provider:" + (location == null ? "null" : String.valueOf(location.getLatitude()) + "," + String.valueOf(location.getLongitude())));
                    updateLocation(location);
                }
            }
        }

This is exactly I was looking for, thanks. I’m building a custom gps tracker, with plotting my path as my location changes, and plotting an altitude-time graph parallely. This creates too much workload on the main UI thread, and it was skipping frames. This will reduce considerable overload.

@betorobson This is the best way to get the periodic location data. But I wonder how can I location data to server. I am beginner, can anybody help?

@betorobson and @veda2vratha Thank you so much. I was looking for this everywhere. finally i got the answer from you.

@Veer50 I am beginner. Can you let me know how can I get the longitude and latitude from this service in other activity? and how can I send this location to server periodically? little bit explaination will help me a lot. Thanks in advance.

@toton6868 I am not sure about it will work in this case, but whenever i want to pass data between activities i use Dependancy Injection which is achieved by Dagger.You can inject the instance of this class into another class and get access to the location variable from where you can fetch longitude and latitude(Read about Dagger..). As I am also beginner i don't know how to send location details to server periodically.

I'm so glad to help others with my snippet code.
@toton6868 , have you tried a simple?
Here you go a very simple straightforward example that I believe can help you: https://developer.android.com/reference/android/os/AsyncTask.html

@betorobson Thanks for the reply. I am known to async Task but I want to know actually how to retrieve Longitude and Latitude in another activity.

@veda2vratha , @betorobson

Hello and thanks ! it's working great !

i have a question and post it here 'cause i explored internet since solution.

Let me explain:

I had to send my location to our server (REST API with Express) with a Simply GET +appId (generate Unique ID) + lat + long.
For that i had to retrieve my appId and my token for my request, store in my share preferences.

I used
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this );

I saw a lot of responses about context in services and i already test every solutions, i try in the onCreate / onLocationChanged / onStartCommand but its not recognize my Token or appId .

is there a solution? i'm sorry i'm from the web (html/css/js/php) and i'm juste start learning Java
Life Cycle it's hard for right now

Try this,
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
or Try using name of sharePreference where you stored it by,
SharedPreferences.getSharedPreferences("NAME_HERE",Context.MODE_PRIVATE);

OnLocationChange is not running...

About the topic, 3 good recomendations based on my experience:

  • Use PARTIAL_WAKELOCK to getupdates or do the same action at the same rate when the device is screen off and standby.
  • Best service for this case is Foreground Service. It won't be killed by the system, it is the highest priority server. But you must show the notification widget.
  • Implement a GPS singleton or similar logic with service or application context. Don't rely on any Activity or Fragment to avoid components life cycle.

@AroundPixels , The aim of my question in this topic is opposite of your suggestion.
It is pretty common to see implementation of location update running in Foreground Service however, my poporse here is that app listener for those location updates running in passive mode which means less CPU and Battery usage.

For who is looking for a foreground service here it NOT the case.

This issue has been solved by the following solution:
https://github.com/codepath/android_guides/issues/220#issuecomment-250756857

Hi @betorobson . I'm only sharing my experience about location services, because I've done several with huge precision requirements. If you need precision, you will need wake locks. I've tested them in hundreds of devices in production mode, and as you may know, every device is different when screen is switch off. Lot of Android surprises.

Anyway, the differences between Service and Foreground Service are minimal: widget, and priority level. Implementation is the same, so I though my advices my be useful for someone who get this thread and needs a minimal slightly different location service than you.

If you were offended by my post, I'm really sorry for you.

It is all good @AroundPixels , I have not get offended.
My concern it is just keep the mindset of this topic about Location service in Passive Mode.

Hi @betorobson ,

I have checked your example above for fetching the latitude and longitude via service.

Can you please let me know how to get the latitude and longitude when the Mobile Device is Offline state (i.e when there is no Internet Data connectivity and Wifi Connectivity ) only GPS is enabled. Will we be able to fetch the Latitude and Longitude.

@sairamandroid , the OS will handle it for you, which means you do not to do anything. What I can tell you is that under hood the Android APP request/listen for location changes and the Android OS will grab it for you using what is available at the moment.

In my example. it is not requesting, just listening for significantly location changes. I've try it for 3 months, collecting location data, saving on user data and displaying in a mapview. The result was impressive. Driving all weekends to the beach, 120km far way from my home it display my history position including places that has no mobile networking or wifi.

I will share my demo project for everyone here in a couple of days, it looks like that will help more than just a code snippet.

Hi @betorobson ,

Thank You for the Reply.

I have two queries :

  1. You were mentioning as to request/listen for location changes and Android will grap and provide. Can you please share piece of code for this. So that I can check this functionality.

  2. Also I have other query i.e If we call the this MyLocationService Service class once, Will it be keep on running in the background to fetch the current latitude and longitude. ( i.e will the service be running constantly or we need to invoke it at a certain interval to get latitude and longitude. )

@sairamandroid
Here you go:

  1. If you want request the location for instance, create a button and every time the user that it your app request the current location, here is the example for it. https://github.com/codepath/android_guides/wiki/Retrieving-Location-with-LocationServices-API

  2. Indeed, it will running in background forever and the cool part is that it will not drain you battery because it is just listening for location changes in passive mode. Here is the code snippet. https://github.com/codepath/android_guides/issues/220#issuecomment-250756857

Hi @betorobson ,

So in the code snippet that you had shared, For the first time if we register the location listener then whenever there is location change then directly onLocationChanged will be called and we can get the updated locations?

Kindly confirm the flow as this process is running in background I need clarity regarding the flow.

Basically my requirement is a service should run in background constantly and fetch the location without users intervention.

@sairamandroid , for sure it will run in background, once the app starts the background service will start at the same time listening for location changes. This snippet code will address exactly your requirements.

@betorobson ,

Thank You.

how can i get latitude and longitude from another activity ..

B

Hi,

Used Google api location change listener

On Apr 20, 2018 7:35 PM, Zain notifications@github.com wrote:

how can i get latitude and longitude from another activity ..


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHubhttps://github.com/codepath/android_guides/issues/220#issuecomment-383116285, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ADn8Iu2jtvLSPemZA-AiKu5Lqu_Hox--ks5tqfJHgaJpZM4KKc6K.

thank you veda2vrath !
it was very helpful

@betorobson

and as you show the values ​​of latitude and longitude in the MainActivity consuming the service, the code that you provided, and knowing what would be the most correct way to be sending the information to a server to show in web platform, new in this help

Run Gps as background service and send coordinates to web server (PHP)

Not getting location update information, even when location changes...

Any suggestions? Using your code exactly.

Hello Everyone,

I have some question about location tracking and background services like (background/foreground/firebasejobdispatcher/jobshedular/workmanager).

Currently, my app is targetting android 28 version. And I am testing on Android 8.0 now. Above code is working perfectly on pre-O and post-O android version. But getting location after every 1 min.

I am creating foreground service but some devices like MI which stop this foreground service. And is the correct way to get locations or service will run in the background?

jobshedular/workmanager periodic time which is not lesser than 15 min.

Have anyone working on facing the same problem and resolving then please guide me.

Thank you

can anyone tell me how to store that location in the MySql database using Rest API

can anyone tell me how to store that location in the MySql database using Rest API

@saadmohammed I don't know is this correct or not but currently, We are creating a geoJson for location parameter. And push this geoJson to the server using API.

You can store this geoJson in your MySQL Db.

How can i call in MainActivity?
Can you please help me

Intent startLocationService = new Intent(MainActivity.this, MyLocationService.class);
startService(startLocationService);

Make sure you declare the service on androidmanifest.xml

Check Example Application usimg latest version of location upsate service FusedLocationProviderClient tutorial link https://www.freakyjolly.com/android-background-geolocation-service-without-any-kill/

Since android Oreo above limit background service location, None of those above works. i try sample by google (https://github.com/googlecodelabs/background-location-updates-android-o/blob/af7660cfb91d114f330818e2033ca0175f11e07d/BackgroundLocationUpdates/app/src/main/AndroidManifest.xml) also not working for broadcast and intent service. This is sample code I did

In Main Activity :-
private PendingIntent getPendingIntent() { Intent intent = new Intent(getActivity(), LocationUpdatesBroadcastReceiver.class); intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES); return PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }
Running the service/ broadcast:
`FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
mLocationRequest = new LocationRequest();

    mLocationRequest.setInterval(UPDATE_INTERVAL);

    // Sets the fastest rate for active location updates. This interval is exact, and your
    // application will never receive updates faster than this value.
    mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());`

My BroadCast:

LocationUpdatesBroadcastReceiver extends BroadcastReceiver{ public static final String ACTION_PROCESS_UPDATES = "<idpackage>.action" + ".PROCESS_UPDATES"; private Location lstart = null; private Location lEnd = null; private Location mCurrentLocation; private double speed = 0.0, distance_accumalative = 0.0; private String cumulativeDistance; private ClientInterface client; private PersonModel personModel; private SessionManager sessionManager;

@Override
public void onReceive(Context context, Intent intent) {
    if (intent != null) {
        sessionManager = new SessionManager(context);
        personModel = sessionManager.getDriver();

        final String action = intent.getAction();

        if (ACTION_PROCESS_UPDATES.equals(action)) {
            LocationResult result = LocationResult.extractResult(intent);
            if (result != null) {
                List<Location> locations = result.getLocations();

                for (Location b: result.getLocations()){
                    mCurrentLocation = b;

                    if (lstart == null) {
                        lstart = mCurrentLocation;
                        lEnd = mCurrentLocation;
                    } else {
                        lEnd = mCurrentLocation;
                    }

                    speed = ((double)b.getSpeed() * 18 /5);
                }

                //if speed more than zero update location
                updateLocation();

                LocationResultHelper locationResultHelper = new LocationResultHelper(
                        context, locations);
                // Save the location data to SharedPreferences.
                locationResultHelper.saveResults();
                // Show notification with the location data.
                locationResultHelper.showNotification();
                //Log.i(TAG, LocationResultHelper.getSavedLocationResult(context));
            }
        }
    }
}`

Anyone know how to run service location in background for oreo above.

@hafiz013 you cannot do this in background. You need create a intent and run as a persistent notification.
Move you code into a intent with persistent notification and it will works like a charm

@hafiz013 you cannot do this in background. You need create a intent and run as a persistent notification.
Move you code into a intent with persistent notification and it will works like a charm

Yeah I did as move to getpending notification but somewhore it only work on 10 minute then it gone and not call anymore. For your information, when i check result android 7 will show up notification above while doing in getpending intent meanwhile, android 8 and 9 does not show notification above.

Thanks, I found I send it back in a broadcast.

can you tell me how are you doing that I am really stuck here and I do not know how to do that for Pie devices.
Thank you

Thanks, I found I send it back in a broadcast.

can you tell me how are you doing that I am really stuck here and I do not know how to do that for Pie devices.
Thank you

Are you trying to use the Passive Mode or High Accuracy geo location?

First you need class LocationUpdatesBroadcastReceiver extends BroadcastReceiver. Then inside broadcast :

`public static final String ACTION_PROCESS_UPDATES = ".action" +
".PROCESS_UPDATES";

@Override
public void onReceive(Context context, Intent intent) {

    if (intent != null) {
        final String action = intent.getAction();

        if (ACTION_PROCESS_UPDATES.equals(action)) {
            Utils.setLocationUpdatesResult(context, DateFormat.getDateTimeInstance().format(new Date()));
            try {
                Utils.getLocationUpdates(context,intent,"PROCESS_UPDATES");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}`

after that, create class Utils which content static mehtod for pass value location and call notification builder.

`public static void getLocationUpdates(final Context context, final Intent intent, String broadcastevent){
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

    Notification.Builder notificationBuilder = new Notification.Builder(context)
            .setContentTitle(" ")
            .setContentText(" ")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .setStyle(new Notification.BigTextStyle().bigText(" "))
            .setAutoCancel(true);
    notificationManager.notify(3, notificationBuilder.build());

}`.

After that, in the main activity call this function:

`mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());

    LocationRequestHelper.getInstance(getActivity()).setValue("RequestingLocationUpdates",true);

    Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
            Utils.UPDATE_INTERVAL,
            getPendingIntent());

    task.addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {

        }
    });
    task.addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            //Log.i(TAG, "addOnFailureListener mActivityRecognitionClient "+e);
        }
    });`

and function getPending like this;

private PendingIntent getPendingIntent() { Intent intent = new Intent(getActivity(), LocationUpdatesBroadcastReceiver.class); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES); return PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }

That's all due, and for stop update location:

` if (getPendingIntent() != null && mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(getPendingIntent());
}

    Utils.removeNotification(getActivity());

    if (getPendingIntent() != null && mActivityRecognitionClient != null) {
        Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
                getPendingIntent());

        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
            }
        });
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {

            }
        });
    }`

function remove notification:

public static void removeNotification(Context context){ NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.cancelAll(); }

Thanks sir for your great reply but here you can see my problem . Can you please shot out my problem I really need your valuable help.
Thank You

First you need class LocationUpdatesBroadcastReceiver extends BroadcastReceiver. Then inside broadcast :

`public static final String ACTION_PROCESS_UPDATES = ".action" +
".PROCESS_UPDATES";

@Override
public void onReceive(Context context, Intent intent) {

    if (intent != null) {
        final String action = intent.getAction();

        if (ACTION_PROCESS_UPDATES.equals(action)) {
            Utils.setLocationUpdatesResult(context, DateFormat.getDateTimeInstance().format(new Date()));
            try {
                Utils.getLocationUpdates(context,intent,"PROCESS_UPDATES");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}`

after that, create class Utils which content static mehtod for pass value location and call notification builder.

`public static void getLocationUpdates(final Context context, final Intent intent, String broadcastevent){
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

    Notification.Builder notificationBuilder = new Notification.Builder(context)
            .setContentTitle(" ")
            .setContentText(" ")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .setStyle(new Notification.BigTextStyle().bigText(" "))
            .setAutoCancel(true);
    notificationManager.notify(3, notificationBuilder.build());

}`.

After that, in the main activity call this function:

`mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());

    LocationRequestHelper.getInstance(getActivity()).setValue("RequestingLocationUpdates",true);

    Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
            Utils.UPDATE_INTERVAL,
            getPendingIntent());

    task.addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {

        }
    });
    task.addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            //Log.i(TAG, "addOnFailureListener mActivityRecognitionClient "+e);
        }
    });`

and function getPending like this;

private PendingIntent getPendingIntent() { Intent intent = new Intent(getActivity(), LocationUpdatesBroadcastReceiver.class); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES); return PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }

That's all due, and for stop update location:

` if (getPendingIntent() != null && mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(getPendingIntent());
}

    Utils.removeNotification(getActivity());

    if (getPendingIntent() != null && mActivityRecognitionClient != null) {
        Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
                getPendingIntent());

        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
            }
        });
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {

            }
        });
    }`

function remove notification:

public static void removeNotification(Context context){ NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.cancelAll(); }

Thanks sir for your great reply but here you can see my problem . Can you please shot out my problem I really need your valuable help.
Thank You

sorry due, in order to get location from service to be served to another activity is quite difficult and i do not know how to do it.

I know it was late but you can find best code here

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

I'm sorry my bad... i tried to use this code on API 19, and when you click the button app crushes

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

I'm sorry my bad... i tried to use this code on API 19, and when you click the button app crushes

Pay attention here ...

  1. If problem with my repository you have to open a issue there.
  2. Bro according to my repository gradle file have min Sdk is 22 so if you want to use in 19 so change a gradle file.

Thank You !

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

Can you please provide the full code?

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

Can you please provide the full code?

You can check my repository . I mentioned a link above.

run a foreground service and fetch location by location listener. Your app wont be killed and will work all the time. or Use activity recognition API to detect user movements and run location fetching code.

run a foreground service and fetch location by location listener. Your app wont be killed and will work all the time. or Use activity recognition API to detect user movements and run location fetching code.

I have done this via a foreground service. Everything works out very well. However, I am curious on if doze mode or wakelock affects foreground services? And every call that comes from the onNewLocation handler, I send the data to a restful api to store then able to view on the admin side, it is killing battery though. Any pointers?

In a foreground service, i'm using FusedLocationProviderClient to request for location updates. If the gps is turned off then i'm not getting the onLocationResult() call back. How to handle this problem ?? Before starting the service, location was on and i got a couple of callbacks in onLocationResult() method. After sometime, user turned off the gps, after that i'm not getting the onLocationResult() call back. Any idea how to deal with this problem ??

Can anybody help me out
I am building an application with following specs:
· This app is aimed to record trips of the user.

· Whenever user wants to go on a trip, he/she will START the trip. The app will record the location (through GPS/4G) at specific interval of time (e.g. 10 seconds, 1 minute etc, a configurable value through menu). Whenever user finishes the trip, he/she will STOP the trip.

· All trips will be saved locally on the mobile. User should be shown the list of all saved trips. Any trip should be selectable, which will fetch the saved data, in form of table.

· Next step will be, integration with GoogleMaps library. All recorded location points should be plotted on GoogleMaps view, to show entire trip (not in GoogleMaps app, but in Track-My-Trip app itself).

· GoogleMaps view can be used for live tracking of current trip, updated real time.

Following key elements should be used:
-Android Studio
-LocationManager APIs
-data storing methods, e.g. SharedPreferences or SQLite DB
-Learn Google Maps APIs
-Learn Android App UI Components

Outcomes:
· Recording of data for 1 trip.
· List of all saved trips
· Loading of data of selected trip
· Plotting of Trip data on Google Maps
· Live plotting of location data on Google Maps view

Hey @99002688, Should the location tracking should happen in the background or while the app is open. If you want to track while the app is open you can create an app with a Wake lock that will not turn off the screen until the user presses the power button.

With this approach, you will write a location tracking broadcast using fused location API and create a pending Intent that will generate a Broadcast and in broadcast just do what you want to do with the data or you can have callbacks too and in the locationresult callback just write the code what you want to do with the coordinates.

If needed in background even when the app is closed and removed from the activity stack, I prefer you to go with Foreground service approach. Create a Foreground service that will have Fused location API code and in the location result do what ever you want.

Note: Foreground services may be stopped in some chinese devices like Xiaomi, Realme, Oppo, Vivo etc. For those devices I went with Alarm manager approach which will trigger foreground services for every given time. (Note > 10 min) and some may work with 5 min too.

Alarm managers are vulnerable to doze mode conditions i.e. they may get delayed when device goes to doze mode. for that i have used One of the Wake lock which will turn on the screen to make device come out of doze mode. (FULL_BRIGHTNESS) .

Was this page helpful?
0 / 5 - 0 ratings

Related issues

savekirk picture savekirk  ·  8Comments

nesquena picture nesquena  ·  11Comments

debpedrano picture debpedrano  ·  8Comments

nesquena picture nesquena  ·  4Comments

kpradeepkumarreddy picture kpradeepkumarreddy  ·  5Comments