[TIMOB-9434] Android: compass event "trueHeading" not generated for recurring compass events
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Medium |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2012-07-12T00:43:29.000+0000 |
Affected Version/s | Release 1.8.0 |
Fix Version/s | Release 2.1.0, Sprint 2012-12 Core |
Components | Android |
Labels | core, module_geolocation, qe-testadded |
Reporter | Arthur Evans |
Assignee | Arthur Evans |
Created | 2012-06-06T18:51:11.000+0000 |
Updated | 2013-01-17T15:59:30.000+0000 |
Description
When calling
Ti.Geolocation.getCurrentHeading
, the trueHeading
property is defined in the callback object. However, when registering for heading updates, the trueHeading property is not defined in the event -- **unless you first call getCurrentHeading
**.
When we encode the event into a hash map, we do this:
if (geomagneticField != null) {
float trueHeading = x - geomagneticField.getDeclination();
if (trueHeading < 0) {
trueHeading = (360 - trueHeading) % 360;
}
However, geomagneticField
is only initialized in getCurrentHeading.
String provider = tiLocation.locationManager.getBestProvider(criteria, true);
if (provider != null) {
Location location = tiLocation.locationManager.getLastKnownLocation(provider);
if (location != null) {
geomagneticField = new GeomagneticField((float)location.getLatitude(), (float)location. getLongitude(), (float)(location.getAltitude()), System.currentTimeMillis());
}
}
If we were to initialize geomagneticField
when a listener is added, it might fix the immediate problem, although this wouldn't address the case when no last known location is available. Even if the user registers for compass updates and location updates at the same time, a location may not be immediately available.
Also, I think this should be reevaluated in light of the new Android Geo code. Instead of calling getLastKnownLocation(provider)
, it might be preferable to call tiLocation.getLastKnownLocation
, which will check all providers.
Think I have a fix for this issue, need to test it on device.
Fix didn't work on Nexus 1. Booting this bug back to the big boys. After discussing this with Josh, I think we really should be recalculating the declination periodically, but I'm not sure of the best approach to take. - Since we generate several heading events a second, generating a new GeomagneticField with every heading event is going to be too expensive. - Calculating the distance between the last fix and latest fix is also somewhat expensive. - Might be sufficient to just check the age of the last location fix, which would be a cheap comparison. Recalculating declination every few minutes should be plenty accurate enough, and fairly cheap. Here was my attempt:
I'm guessing maybe the tiLocation.getLastKnownLocation() is not working if the user hasn't registered any location providers.
Weekend project.
Testing
Note that this code must be tested on device with compass and GPS support. It can't be tested on emulator. Use the following app.js:When testing _without_ the fix, note that the Mag value shows up (magnetic heading) but the True value (true heading) stays undefined, even if a location fix is available. (If no location fix is available, press the Get Location Fix button.) When you've satisfied yourself that true heading isn't showing up, press the Get Heading button, and note that the true heading shows up. When testing with the fix, start the application and note that if a location fix is available when the app starts, the true heading shows up immediately. If there is no location fix, press the Get Location Fix button (but NOT the Get Heading button). After the location label updates to "Have location fix", wait for true heading to show up. This should show up in one minute (or less).
Addressed in PR: https://github.com/appcelerator/titanium_mobile/pull/2373
Updated test code:
Updated testing instructions: - test on a device hooked up to DDMS. - To test without location fixes, turn airplane mode on and leave the app to run for 10 minutes. Updates will continue to show trueHeading, but a warning message will be logged 1/minute showing that location is stale. - If you start the app when no location fixes are available, you'll see trueHeading is undefined, and a warning message will be logged 1/minute showing that no location fix is available. - To test restoring location fixes, turn airplane mode back off and wait for a few minutes. You probably won't even need to request a location explicitly. If the device doesn't show a fix after a few minutes, you can press the Get Location Fix button. (Within ~1 minute of getting a fix, the device should start showing a true heading value.)
After discussions with Opie, updated the fix so that we use the stored location, even if it's stale, but we log a message for stale location/no location. Test instructions above are updated. Key points for this issue are that we get trueHeading values on 'heading' events (assuming that a location is available). Without the fix, you should see true heading == undefined.
Verified fixed with SDK 2.1.0.v20120618102300 using a droid 1
Reopening to update labels.