This is a question which has been asked numerous times but I could not find a solution that always works.
I am developing an application using the Fused location provider.
In the onConnected() method, I am requesting for location updates and the application logic will be initiated once a location fix is generated and onLocationChanged() is called. (Please refer to my code below).
Problem onLocationChanged() method is never called on some devices. I use a Samsung Tab 2 and a Samsung Galaxy Grand for testing. This code works perfectly fine on the Tab 2 but does not work on Grand. By does not work, I mean that locationClient gets connected but onLocationChanged() is never called.
Earlier, I used the location manager for getting location and in that implementation, the same problem occurred. So, I tried implementing the fused location provider but I still get the same problem.
Can anyone help me out with this issue? Is there something I am missing here?
public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
LocationClient locationclient;
LocationRequest lr;
Location loc1;
static String address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationclient = new LocationClient(this,this,this);
locationclient.connect();
}
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
lr=LocationRequest.create();
lr.setInterval(100);
locationclient.requestLocationUpdates(lr, this);
Log.d("LocationClient","On Connected");
}
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
locationclient.disconnect();
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location loc) {
// TODO Auto-generated method stub
// Application Logic
Log.d("LocationClient","Last Known Location LC:" + loc.getLatitude() + "," + loc.getLongitude());
}
}
I observed same behavior on Galaxy Nexus and recognized two things causing onLocationChanged() to not being called. There are
Corresponding location source is not enabled in System Settings. For PRIORITY_HIGH_ACCURACY the GPS satellites must be enabled, for PRIORITY_BALANCED_POWER_ACCURACY Wi-Fi & mobile network location must be enabled.
Even for the enabled location sources there can be no valid location information available. For instance, PRIORITY_HIGH_ACCURACY source is enabled, but there is no (or not good) GPS reception (e.g. device is inside a building). Or PRIORITY_BALANCED_POWER_ACCURACY source is enabled, but both Wi-Fi and mobile data are switched off. In those cases location cannot be detected and onLocationChanged() will not be called.
To fix #1 I had to check whether required location sources are enabled even before connecting to Google Services API and if they are switched off, then I notified a user asked him/her to allow location access.
To solve #2 I decided to use LocationRequest.setExpirationDuration(). I set timeout at about 10 seconds, and immediately after calling requestLocationUpdates() I post a callback delayed by same 10 seconds. If delayed callback is called before requestLocationUpdates(), this means location cannot be detected due to reason #2. I do three retries and then show user an error message.
Android documentation is not great at this place, that's why I hope this helps.
lr.setInterval(100);
with it your interval is 0,1 second so it very hard for gps chipset to detect location. Your interval should be > 1 second.(with me it is > 10)
locationRequest it should be set:
setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
because PRIORITY_BALANCED_POWER_ACCURACY in outdoor it doesn't get location . Code will look like :
lr=LocationRequest.create();
lr.setInterval(5 * 1000);// 5s
lr.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationclient.requestLocationUpdates(lr, this);
Hope this help.
See if you're getting a passed location by testing for if (loc == null). Even though it's the same provider, maybe one device is coming back null and bombing out, resulting in a look like it's not firing.
This maybe non-sense but I have faced this problem before, someone suggested that you should create your own LocationListener instead of letting your MainActivity implements LocationListener. Basically this:
locationclient.requestLocationUpdates(lr, your_location_listener);
Hope this helps.
I solved this by setting both parameters, minimum distance and minimum time between updates to 0.
As per what I have tested on 2 devices, now onLocationChanged() is being called regularly after requesting for updates.
try to remove and reinstall "google play services". Install it from google market link bellow,
google play services
Here Check this code out...
public class MyActivity extends Activity implements LocationListener {
double destLat, destLong;
LocationManager locationManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
destLat = location.getLatitude();
destLong = location.getLongitude();
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
Related
I have tried (but in vain) to force request GPS location updates on my Android Widget (Android Oreo).
The widget is set to update every 15-20 minutes and fetch the current location of the phone and display.
However, it only picks up the location of the phone where it was installed and subsequent runs don't return a new location even when the phone moves.
I read through the solution provided here How does it work - requestLocationUpdates() + LocationRequest/Listener and implemented it, but it doesn't seem to help.
LocationManager locationManager = (LocationManager)
context.getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
300000L, 500.0f, new LocationListener() {
#Override
public void onLocationChanged(android.location.Location location) {
if(location != null)
{
LocationPreferences.setLastLocationLatLon(context,location);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
});
Having said that, it is more reliable when it's in one of the activities (and not in a widget), but given that the widget is supposed to perform background location updating, it doesn't work, the onlocationchanged never gets called (I'm sensing it's silently killed in the background)
Has anyone created/ worked with Android widgets using GPS on Oreo? Any help in the right direction will be appreciated. Thank you very much in advance.
I've read the Google doc and this post notably the interesting #bendaf's answer, about managing Location settings, and everything works well.
Anyway one problem remains if the user first decide to not use its position and then decide later to activate it, the application is not trigged by this action so I don't know that I can request for periodic updates.
What did I miss here?
You can provide an AlertDialog every time user launches an app so that user can enable the location. But this will be a bit annoying because every time you have to deny to same thing.
Alternatively, you can use Preferences so that user can enable/disable the location
There is another better way to do it. Use LocationListener. It is for the sole purpose that you want to achieve.
public class XYZ Activity implements LocationListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,10,this);
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}
I think this is the right thing that you are looking for. It's the event way.
Happy Coding :)
#fralbo Although this thread is a tiny bit old, I just wanted to provide a solution for you, as I recently had to do something similar myself.
I would recommend implementing a BroadcastReceiver into your App, with the intent filter PROVIDERS_CHANGED..
This will trigger every time the Location/GPS Provider state changes - and you can use an if statement inside of the BroadcastReceiver's onReceive method, to determine whether or not your required conditions are met, and proceed accordingly.. For example, inside the onReceive method of the BroadcastReceiver, you can determine whether the PROVIDERS_CHANGED event has made the GPS become available (and to what degree) - and if it now meets the needs of your App, you can then call whichever Method within your App that is responsible for starting the required calls to the GPS engine, etc.
Here's an example of what the code might look like:
public class LocationReceiver extends BroadcastReceiver {
private final static String TAG = "[ LocationReceiver ]:";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "PROVIDERS_CHANGED has been detected - Firing onReceive");
// Retrieve the LocationManager
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// Provide boolean references for Location availability types
boolean isGpsEnabled;
boolean isNetworkEnabled;
// Provide values to retrieve the Location availability
isGpsEnabled =
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled =
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
Log.i(TAG, "Detected - GPS: "+ isGpsEnabled + "NET: "+ isNetworkEnabled);
// If (for example), the GPS is ENABLED, start one of your Activities, etc.
if (isGpsEnabled) {
Intent startYourActivity =
new Intent(context.getApplicationContext(), YourActivity.class);
context.startActivity(startYourActivity);
}
}
}
I hope this helps! Better late than never :)
Happy coding!
I need to check whether GPS is locked in my application. I am able to check whether GPs is enabled in the phone. But once the GPS is locked, while running the application, it gets unlocked and I noticed that the GPS icon of the phone is blinking. I need to show an animation similar to that of phone in my application to acknowledge the user the GPS is unlocked. Anybody who knows the solution please post it.
Thanks in advance....
This is what I use. Start your animation when you requestLocationUpdates and end it when you get the onLocationChanged call. See my code below, it should solve your issue.
public class YourLocationClass implements LocationListener {
private LocationManager lm;
public void getLocation(Context ctx) {
lm = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 15000, 25, this);
//START YOUR ANIMATION
}
public void onLocationChanged(Location location) {
//HERE YOU STOP YOUR ANIMATION AND GET NEW LOCATION
}
public void onProviderDisabled(String provider) {
// DO SOME STUFF
}
public void onProviderEnabled(String provider) {
// DO SOME STUFF
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// DO SOME STUFF
}
}
It seems for me it is getting called the first time the activity starts, just after onCreate, it then seems to be called at random intervals, whether I move or not???
Regardless of that is it simply called automatically if I have code like this in the onCreate method?
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
Is that right???
Cheers,
Mike.
Your question is not clear initially.Your code and title are not matching. I am giving answer for your title only.
You have to register Location Listener for your Location Manager, then only onLocationChanged() will be called according the settings you supplied while registering location listener.
See below code how to do that. I used GPS Provider, you can use any provider based on criteria also.
LocationManger lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
});
Coming to your question, onLocationChanged() will be called if the current location update is not matching with last known location.
The updated location will be changed for every minTime (in my case 1000 milli sec) and also if device moved minDistance (in my case 0 meters) distance.
I hope you will understand this.
if you want to catch new locations, you have to register a LocationListener like this:
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
LocationListener listener = new LocationListener() {
...
}
locationManager.requestLocationUpdates(GPS_PROVIDER, intervall, distance, listener);
With intervall and distance you can configure:
If intervall is greater than 0, the LocationManager could potentially rest for intervall milliseconds between location updates
If distance is greater than 0, a location will only be broadcasted if the device moves by distance meters.
When the LocationListener is registered, the LocationManager starts to get your geo location and calls the onLocationChanged(). If the distance is very low, it can happen that the method is called very often in a short period of time. According to the intervall, the LocationManager will rest afterwards.
I think, the LocationManager will only start doing it's work, when a LocationListener is registered.
Hope that helps...
Cheers,
Tobi
public void onLocationChanged(Location location)
the above method gets called automatically once your location has been changed..
I've been working on an application that emails the GPS location of a phone to the user- and it is very important that the phone sends the current location, not the location from a while ago.
I tried a couple fixes, such as changing minTime and minDist, as well as removing (or not removing) the listener when done. This application is to be used only at certain times, however, and I want minimum battery use, so leaving it running isn't a good option.
I have had luck with some updating if I set the minTime to a small amount, and never removed the LocationListener, in which case the second message I sent would be updated, but other than that...
This makes me think I need to give it more time to get the GPS location for sure- but how would I force it to do that?
With this in mind, I have been trying this snippet:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
};
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, (long)(.000001), (float)(0),
locationListener);
String s = "";
SimpleDateFormat timingFormat = new SimpleDateFormat("hh:mm");
timingFormat.format(new Date());
s += "The current time according to the clock is: "
+ timingFormat.format(new Date()) + "\n";
Location location = lm
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
lm.removeUpdates(locationListener);
(returns the String s, with the address added)
You should put something in onLocationChanged to do something with the location updates coming in.
Normally you first get a rough approximation, and when the GPS tunes in the accuracy gets better. To handle this efficiently, have onLocationChanged check if the location is accurate enough, and let it kick off whatever you want to do with the accurate location.
A good start would be to just put
Log.v("myapp","Location changed: "+location);
in onLocationChanged() and then watch the output.