-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A good example of background service getting location updates #220
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? |
startservice(new Intent(this,MyLocationService .class)); |
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 |
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
Please suggest what I have to implement to get current & accurate location in Android app. |
You can use mGoogleApiClient = new GoogleApiClient.Builder(this) try { |
@RaziaSandhu Hi Thanks for your reply. |
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 . this is my location service class pice of code
|
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 and @veda2vratha Thank you so much. I was looking for this everywhere. finally i got the answer from you. |
@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. |
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. I used 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 |
Try this, |
OnLocationChange is not running... |
About the topic, 3 good recomendations based on my experience:
|
@AroundPixels , The aim of my question in this topic is opposite of your suggestion. For who is looking for a foreground service here it NOT the case. |
This issue has been solved by the following solution: |
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. |
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 = "<id.package>.action" +
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){
}`. After that, in the main activity call this function: `mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());
and function getPending like this;
That's all due, and for stop update location: ` if (getPendingIntent() != null && mFusedLocationClient != null) {
function remove notification:
|
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. |
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. |
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 |
hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99) |
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 ...
Thank You ! |
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. |
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 · 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: Outcomes: |
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) . |
Hello @GadepalliAditya1998 . Do all Chinese manufacturers restrict location access from any kind of background activity. I tried getting location periodically in the background using normal services, foreground service & WorkManager. But each time, after 10s of the phone being locked, the location wasn't being tracked anymore. I actually created a broadcast receiver that starts a WorkManager when powerbutton is clicked but even then while the WorkManager is started, I am not getting location data. Same happens with Foreground service. On the other hand, turning the Battery Saver option of the app to no restrictions fixes this & now I am able to access location long(15-20 mins) after the phone has been locked. Is WakeLock the only solution or is there any other way. Can WakeLocks be initiated from Broadcast receivers? My problem is that while the service/workmanager itself runs, unfortunately I am not getting location data. |
If you see the docs of the Work manager and compare with Old API like Alarm
manager, Job scheduler etc.. Work manager is suitable for the jobs that can
be postponed lets say Whatsapp backup can be postponed but Image upload
cannot be postponed in Facebook, so it uses Foreground service.
Since your case is to fetch location in background, You can use alarm
manager to trigger some service. If your task is less than 10s, you can do
everything in broadcast,but if exceeds its better to call a service. I have
used foreground service so that they won't be killed easily and broadcast
can call service via a Pending intent.
Wake lock will actually make your device come out of the doze mode, where
device actually tries to stop all background processing to save battery. So
Wake lock with Screen FULL brightness makes the device to turn on the
screen and will come out of doze mode.
… |
You see...my problem isn't with Foreground service or WorkManager not running. Both run just fine in the background whenever they are called even when the device is locked. But my problem is, for some reason location access is being restricted to these services while they run in the background after the device is locked. When I turn off all battery saving features then the location data gets properly passed to the Foreground service/WorkManager & they are able to store it in Firebase. Is there anyway to go around the battery saving feature of Chinese ROMS to get location access? Or does the battery saving feature also control doze mode & me disabling the feature also disables it? If so should I proceed with a WakeLock since I read somewhere else that Chinese roms restrict location access for even foreground services & only WakeLock fixes it? |
For Stock Android like Pixel and motorola etc, You can use
IgnoringBatteryOptimizations to turn off battery optimization for your app.
But But... The chinese roms can impose other sorts of restrictions which
may have to be turned like
In vivo it will be like: Permission manager > Advanced permission > Turn
off restrict background jobs
In oneplus: It will be turn off advanced battery optimizations and deep
level battery optimization, those are to be turned off
I haven't come across a single generic API, that will manage these.
…On Mon, Jan 25, 2021 at 1:32 PM Nahush ***@***.***> wrote:
You see...my problem isn't with Foreground service or WorkManager not
running. Both run just fine in the background whenever they are called even
when the device is locked. But my problem is, for some reason location
access is being restricted to these services while they run in the
background after the device is locked. When I turn off all battery saving
features then the location data gets properly passed to the Foreground
service/WorkManager & they are able to store it in Firebase.
Is there anyway to go around the battery saving feature of Chinese ROMS to
get location access? Or does the battery saving feature also control doze
mode & me disabling the feature also disables it? If so should I proceed
with a WakeLock since I read somewhere else that Chinese roms restrict
location access for even foreground services & only WakeLock fixes it?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#220 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AMGJTW2LXLUQRF74OOCMFYDS3UQQLANCNFSM4CRJZ2FA>
.
|
hello who can help me google map doesn't work in the background I looked at the replies but it doesn't work |
I am a mobile app development learner/beginner. I am in the lookout for a sample code for tracking and logging location in the background. Can you all please help me with the sample code where the MyLocationService code from this thread is used... Thank You... |
private fun locationEnable(): Boolean { |
are there kotlin example? |
Hello everyone. Is there a version of the same codes written in Kotlin? |
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.
The text was updated successfully, but these errors were encountered: