MWM-for-Android
MWM-for-Android copied to clipboard
Location doesn't work when using GPS or other location providers
Should be a simple fix
http://developer.android.com/reference/android/location/LocationManager.html#getBestProvider(android.location.Criteria, boolean) with http://developer.android.com/reference/android/location/Criteria.html#ACCURACY_COARSE and the GPS permission should fix it, I think ;)
Would that be smart enough to switch between GPS and cell location if the user turns gps on and off whilst the app is running, or would we need to detect the state change and reinitialise the location listener?
That, I can't answer. Probably not. :/
Not entirely sure if I understood the problem but, regarding location... When you request updates from the LocationManager it will be associated with a specific provider (even if you pass a Criteria in). You should then listen for the onProviderDisabled event and get the best active provider again. This might complicate things a bit again because, if you want accuracy you'll have to manage when GPS becomes active again even if you're using another active location provider.
Anyway, so far, the best advice on location I've seen was here: http://android-developers.blogspot.co.uk/2011/06/deep-dive-into-location.html
But maybe I didn't understand the problem hehe :)
Yeah - put simply it currently just uses the extra-course cell location provider, which fails entirely on devices that don't have cell radios (e.g. Nexus 7). What we really want would be for it to automatically use gps or wifi based location if those are available, but fall back to cell based location if not.
It only updates location every half hour, or so, but ideally it'll use as little power as possible.
I'll have a look at that example and see if I can rework the existing code to match its suggestions.
If it isn't for real-time location tracking, what do you think about using the Last Known Location as in the example (under Freshness means never having to wait)? Basically, you'd have to setup your own timer for it but you could consider that for scarse updates is basically the same as when you just started the app. You don't even need to only get location from active sources only. It might be the case that GPS was disabled fairly recently and is still a reliable position :)
What I mean with this is, the code from that example can be used almost as-is :)
I hope this helps (I'm almost getting my watch! YEAH! I could look into this after if you don't mind, I'm really excited! hehe)
It already does check for the most recent update when it does a weather refresh, in case the OS has a newer location than the one it was last notified about - the main issue is that it won't activate and scan with GPS unless you actively tell it to.
Btw, even without a watch you can still experiment with the app - if you tick the "Show fake watches" option in Preferences/Device, then open the Select Watch option, you'll see a "Fake digital watch" entry - select that, and MWM will pretend it's connected to a digital watch - you'll be able to see the location and weather update status on the status tab, and will be able to see what the idle screen(s) look like on the widgets tab, to see what weather data it's pulled in.
I've used location in some of my Android Apps and I'm sure you can get the Location Manager to give you the best fix it can without specifying whether or not it should use GPS. Isn't that what we need here? Or have I misunderstood - in which case please either ignore or put me right :)
On 11 October 2012 12:04, Richard Munn [email protected] wrote:
It already does check for the most recent update when it does a weather refresh, in case the OS has a newer location than the one it was last notified about - the main issue is that it won't activate and scan with GPS unless you actively tell it to.
Btw, even without a watch you can still experiment with the app - if you tick the "Show fake watches" option in Preferences/Device, then open the Select Watch option, you'll see a "Fake digital watch" entry - select that, and MWM will pretend it's connected to a digital watch - you'll be able to see the location and weather update status on the status tab, and will be able to see what the idle screen(s) look like on the widgets tab, to see what weather data it's pulled in.
— Reply to this email directly or view it on GitHubhttps://github.com/benjymous/MWM-for-Android/issues/65#issuecomment-9336108.
Yeah, we don't even need a particularly accurate fix (we're just trying to get weather for the current town/city, after all) - so really we just need a simple way to get a fairly recent location every time we do a weather refresh, in a manner that will work on devices without cell radios.
So ( wifi location || cell location || gps location ) I guess.
Try using this:
LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String provider = manager.getBestProvider(criteria, false);
Location location = manager.getLastKnownLocation(provider);
(warning that was from top of my head, needs a bit of testing...) That should give you a location and I don't mind looking at doing the 'proper' get the best known location later.
Don't forget to add
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
to your manifest ;) (FINE_LOCATION also includes COARSE permission so you only need that one ;) )
By the way, can you point me to the place where the Weather update happens? :)
That stuff all happens within Monitors.java
https://github.com/benjymous/MWM-for-Android/blob/master/src/org/metawatch/manager/Monitors.java
Finally started looking into it! hehe Can you see the diff? https://github.com/DiogoNeves/MWM-for-Android/compare/fix-location
At the moment, anything older than Gingerbread will only use network (which I will change tomorrow or so). On old devices I'm planning on listening for provider changes with the normal listener and switch to the current best active provider. I'll have to profile the battery on that one though.
Anyway, if you could start having a quick look at the code, anything stupid, just let me know hehe :)
(I'm experimenting with fluent pattern which I think fits the purpose but let me know if you don't like the style hehe)
Yeah, looks good so far.
I wouldn't worry too much about adding new functionality for pre-gingerbread, as long as the network location still works - the main issue is location on tablets that don't have a cell radio, of which the vast majority will be running 3.0+
(Only 4% of MW-CE's users are still on 2.1/2.2)
So really, we want something like
- Use GPS if available (but not in a way that is detrimental to battery life)
- if GPS disabled, then use wifi location
- if wifi disabled, or can't get a location from the ssid, then use cell location
The current code only updates every half hour, or so - If you're manually polling instead of using the listener, can you wrap that into the existing weather update refresh?
Ok, great! :) I'm not pulling at the moment but using the Intent based interface. I've also moved the location updates into their own class to make it easier to maintain. If we can neglect pre-gingerbread, I won't spend much more time on it then and will leave the best active provider on.
One thing I just noticed... if we have GPS enabled, as we only update every 30 mins... that means it'll go off between updates (unless another app is using it). I just got this realisation now! (I think I was too sleepy yesterday!)
Either we conclude that we don't need GPS's accuracy for the weather (which I don't think it's the point) or I'll actually start pulling the location using that last best known location and only triggering the update when it isn't good enough (like the article I shared does). This avoids waking up the GPS but still using it's location if it was updated recently. I'm thinking about using the available position if it was collected on the last 5 mins, otherwise trigger an update. Minimal battery cost, highest accuracy, possibly 5 mins old.
What do you think?
I'm finishing something else and I'll look into this next :)
My 2p/2c worth:-
The weather doesn't vary much within the location of a single cell tower so whilst we're only using the location for weather I don't think we need GPS. We can't get the forecast at all unless we have a signal from a cell tower and I would have thought that location would be sufficiently accurate?
I use Wunderground for weather because they are more accurate than the Met Office in my opinion, and they zero in closer to the required location, but often to get a forecast they are decoding the information from the METAR from the local airport and that is often more than a cell tower away; for local conditions they will use a local weather station if one is available
- for example: Ruddington UK often uses data from the weather station on the roof of my house since I provide a 10 minute real time feed into Wunderground - if someone checks roughly 5 minutes between my feeds then they get conditions from 7 miles away because it is fresher so Wunderground obviously consider fresher being more important than closer as long as it's close enough.
Hope that helps - end 2p/2c :)
On 24 October 2012 00:25, Diogo Neves [email protected] wrote:
Ok, great! :) I'm not pulling at the moment but using the Intent based interface. I've also moved the location updates into their own class to make it easier to maintain. If we can neglect pre-gingerbread, I won't spend much more time on it then and will leave the best active provider on.
One thing I just noticed... if we have GPS enabled, as we only update every 30 mins... that means it'll go off between updates (unless another app is using it). I just got this realisation now! (I think I was too sleepy yesterday!)
Either we conclude that we don't need GPS's accuracy for the weather (which I don't think it's the point) or I'll actually start pulling the location using that last best known location and only triggering the update when it isn't good enough (like the article I shared does). This avoids waking up the GPS but still using it's location if it was updated recently. I'm thinking about using the available position if it was collected on the last 5 mins, otherwise trigger an update. Minimal battery cost, highest accuracy, possibly 5 mins old.
What do you think?
I'm finishing something else and I'll look into this next :)
— Reply to this email directly or view it on GitHubhttps://github.com/benjymous/MWM-for-Android/issues/65#issuecomment-9722301.
That's a good point! ;) I'd like to avoid switching GPS on, on purpose as well, but that does mean that trading freshness for accuracy might be a mistake... What do you think of using getLastBestKnownLocation and pulling it every half an hour (and using the lowest powered solution for a quick update if the location is too old)? This would use whatever is best at minimal cost, because we wouldn't turn anything on (unless we don't have a choice).
Yeah, the weather is (currently) never updated more frequently than every half hour, anyway, so the location doesn't need to be that up to date, though ideally you want to keep it in sync, so that the location will be updated before the weather update, rather than afterwards.
There should probably be a setting where you can choose to allow GPS usage or not... People (including myself) tend to be picky about what to allow, battery wise. Frequent usage of GPS can kill your battery quickly.
On 24 October 2012 15:38, Diogo Neves [email protected] wrote:
That's a good point! ;) I'd like to avoid switching GPS on, on purpose as well, but that does mean that trading freshness for accuracy might be a mistake... What do you think of using getLastBestKnownLocation and pulling it every half an hour (and using the lowest powered solution for a quick update if the location is too old)? This would use whatever is best at minimal cost, because we wouldn't turn anything on (unless we don't have a choice).
— Reply to this email directly or view it on GitHubhttps://github.com/benjymous/MWM-for-Android/issues/65#issuecomment-9739481.
I quite like that suggestion.
On 24 October 2012 14:38, Diogo Neves [email protected] wrote:
That's a good point! ;) I'd like to avoid switching GPS on, on purpose as well, but that does mean that trading freshness for accuracy might be a mistake... What do you think of using getLastBestKnownLocation and pulling it every half an hour (and using the lowest powered solution for a quick update if the location is too old)? This would use whatever is best at minimal cost, because we wouldn't turn anything on (unless we don't have a choice).
— Reply to this email directly or view it on GitHubhttps://github.com/benjymous/MWM-for-Android/issues/65#issuecomment-9739481.
Ok, here's another version, this time with pulling :) https://github.com/DiogoNeves/MWM-for-Android/compare/pull-location
It uses whatever is the best available location and requests a single update if it isn't good enough. At the moment, whenever we have to request a single update, that will trigger the twice... I'm thinking about returning a boolean on the RefreshLocation() for cases when the location isn't good and ignore the weather update until the next update comes through.
What do you think?
I forgot to mention, it's possible to tweak the settings of the location finder, for example, if we do create an option for using GPS or not, the best way to go about it would be to set a new criteria like:
Criteria criteria = new Criteria();
if (useGPS)
criteria.setAccuracy(Criteria.ACCURACY_HIGH);
else
criteria.setPowerRequirement(Criteria.POWER_LOW);
locationFinder.setCriteria(criteria);
if you set it to low power, it'll still use an accurate location if it is available in the getLastBestKnownLocation() but won't turn the GPS on if it sends the single request. This is actually the default behaviour at the moment...
To summarise: Prefer accurate available locations but only request new ones from low powered providers :)
I'm not entirely sure if I should do this but... On the new code I'm just finishing, if the location isn't good enough, I'm setting the LocationData.received to false and skip the weather update until the next update (which should be soon). Is that ok?
Ok, submitted another change (the diff link should still work :) )
Setting LocationData.received to false will cause all the weather widgets to display a "waiting for location" message, so it's better to just leave the previous known location in place if you're unable to get a new one - weather from the wrong location is better than no weather at all!
ok, I'll revert to the previous commit which didn't cause that hehe
Review that one :) doesn't set the received flag