Closed betorobson closed 6 years ago
@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
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 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. @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
@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:
@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 :
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.
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:
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
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.
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.