{ "id": "77876", "key": "TIMOB-4779", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "12097", "description": "", "name": "Sprint 2012-05", "archived": true, "released": true, "releaseDate": "2012-03-11" }, { "id": "12593", "name": "Release 2.0.0", "archived": false, "released": true, "releaseDate": "2012-03-30" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2012-03-13T20:17:45.000+0000", "created": "2011-07-15T12:07:30.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "dr-list", "geolocation", "module_geolocation", "qe-port" ], "versions": [ { "id": "12580", "description": "Dual Runtime 1.8.0", "name": "Release 1.8.0.1", "archived": true, "released": true, "releaseDate": "2011-12-22" } ], "issuelinks": [ { "id": "15099", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "86154", "key": "TIMOB-7565", "fields": { "summary": "Android: refactor Geolocation module to support expanded Android functionality", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } } ], "assignee": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "updated": "2012-03-19T15:11:44.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "Behaviour reproducible in the KitchenSink [geolocation.js|https://github.com/appcelerator/KitchenSink/blob/master/Resources/examples/geolocation.js] example on Titanium 1.5 to 1.6+.\r\n\r\n\r\n\r\n{quote}\r\nSometimes the listener fails to return any location even after a few minutes. However, if I open a Ti.Map.MapView with the userLocation attribute set to true, my current location is pointed out on the map within 20 seconds. Other location-based apps installed on the Android phone also manage to successfully geolocate me.\r\n{quote}\r\n\r\n(From Q&A post at http://developer.appcelerator.com/question/118712/tigeolocation-on-android-seems-flaky)\r\n\r\nKey points from our conversation with Kevin Whinnery about this issue:\r\n\r\n* Accuracy level has been set to *Ti.Geolocation.ACCURACY_BEST*. Our code is more or less the same as the KS example code.\r\n* Reports of geolocation failure from a *wide range of devices*. We have seen nearly 60% of users dropping out because the app didn't geolocate them. Even our existing users keep asking us to improve geolocation - esp. because they see that the map within our app shows the current location, but our geolocation code fails to work.\r\n* The important thing is that this *doesn't happen all the time*. Single-shot GPS readings do come back at a reasonable rate when the geolocation is working. But when it isn't working, we have to wait for minutes together with no guarantee of success.\r\n* Opening & locating ourselves in Gowalla or *other location-based apps* ensures that the Kitchen Sink demo always works the next time we open it.\r\n\r\nWe *don't* run the geolocation call within the app.js context. We open a heavyweight window using a URL from app.js. From this heavyweight window, we open another window using a URL. It is in this window's context that the geolocation call occurs.\r\n\r\n", "attachment": [ { "id": "22643", "filename": "TaazzaGO.tar.bz2", "author": { "name": "kwhinnery", "key": "kwhinnery", "displayName": "Kevin Whinnery", "active": true, "timeZone": "America/Chicago" }, "created": "2011-08-23T13:16:26.000+0000", "size": 149037, "mimeType": "application/x-bzip2" } ], "flagged": false, "summary": "'location' event listener on Ti.Geolocation on Android is unreliable", "creator": { "name": "taazzago", "key": "taazzago", "displayName": "Taazza GO", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "taazzago", "key": "taazzago", "displayName": "Taazza GO", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "Android 1.6+, Titanium 1.4.2+", "comment": { "comments": [ { "id": "175420", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I have this EXACT same problem. It has something to do with [TiLocationHelper.java|https://github.com/appcelerator/titanium_mobile/blob/master/android/titanium/src/java/org/appcelerator/titanium/util/TiLocationHelper.java]. Essentially, the accuracy constants map to one of two different options (different behavior than iOS, where all 6 constants do something different), and your choices are either \"don't turn on the GPS ever\" or \"require a great satellite lock and ignore that there's a network location device in this phone\", even though Android technically supports a lot more choices than that.\r\n\r\nIt's less than ideal, but I edited the TiLocationHelper.java file to subscribe to updates from both the GPS and network providers, so that my app at least gets a fix in a reasonable amount of time (instead of never), though it doesn't follow the Android model of \"get crappy location and keep improving until app is satisfied\".\r\n\r\nIf you make this modification (I did it in registerListener and not updateProvider because I'd like to get something immediately and improve it), what fetchProvider does isn't really relevant. I'm working on distilling a patch to do what *I* want, but I'm sure it isn't going to do what you want. I'll post it here once my QA team beats it to death.", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-08T11:43:42.000+0000", "updated": "2011-12-08T11:43:42.000+0000" }, { "id": "175493", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Here is a patch that I wrote to halfway hack around this issue:\r\n\r\n{code:title=0001-Hack-the-location-helper-to-work-better-in-our-appli.patch}\r\nFrom 3d20822fcb9c4df2246b9189f463bf7e7324423b Mon Sep 17 00:00:00 2001\r\nFrom: Keith Gable \r\nDate: Thu, 8 Dec 2011 17:35:16 -0600\r\nSubject: [PATCH] Hack the location helper to work better in our application:\r\n\r\n* Don't require that the location provider support bearing, speed, etc.\r\n when using ACCURACY_BEST.\r\n* Initial event listener call will listen to both the GPS and network\r\n providers for location.\r\n* Additional debugging to figure out what step the geolocation process\r\n is reaching before dying.\r\n---\r\n .../titanium/util/TiLocationHelper.java | 55 +++++++++++++------\r\n 1 files changed, 37 insertions(+), 18 deletions(-)\r\n\r\ndiff --git a/android/titanium/src/org/appcelerator/titanium/util/TiLocationHelper.java b/android/titanium/src/org/appcelerator/titanium/util/TiLocationHelper.java\r\nindex 2d04b35..d1b930b 100644\r\n--- a/android/titanium/src/org/appcelerator/titanium/util/TiLocationHelper.java\r\n+++ b/android/titanium/src/org/appcelerator/titanium/util/TiLocationHelper.java\r\n@@ -48,11 +48,12 @@ public class TiLocationHelper\r\n \r\n \tprivate static int buildUpdateFrequency(Integer frequency)\r\n \t{\r\n-\t\tif (frequency != null) {\r\n-\t\t\treturn frequency.intValue() * 1000;\r\n-\t\t} else {\r\n-\t\t\treturn DEFAULT_UPDATE_FREQUENCY;\r\n-\t\t}\r\n+\t // Updated 2011-12-05 by Keith Gable :\r\n+\t // * Always return 0 so we get instant updates.\r\n+\r\n+ Log.i(LCAT, \"Update frequency: 0\");\r\n+\r\n+\t return 0;\r\n \t}\r\n \r\n \tprivate static float buildUpdateDistance(Integer accuracy)\r\n@@ -61,7 +62,10 @@ public class TiLocationHelper\r\n \r\n \t\tif (accuracy != null) {\r\n \t\t\tswitch(accuracy.intValue()) {\r\n-\t\t\t\tcase ACCURACY_BEST : updateDistance = 1.0f; break;\r\n+\t\t\t // Updated 2011-12-05 by Keith Gable :\r\n+\t\t\t // * ACCURACY_BEST's updateDistance is 0.0 now.\r\n+\r\n+\t\t\t\tcase ACCURACY_BEST : updateDistance = 0.0f; break;\r\n \t\t\t\tcase ACCURACY_NEAREST_TEN_METERS : updateDistance = 10.0f; break;\r\n \t\t\t\tcase ACCURACY_HUNDRED_METERS : updateDistance = 100.0f; break;\r\n \t\t\t\tcase ACCURACY_KILOMETER : updateDistance = 1000.0f; break;\r\n@@ -71,6 +75,8 @@ public class TiLocationHelper\r\n \t\t\t}\r\n \t\t}\r\n \r\n+ Log.i(LCAT, \"Update distance: \" + updateDistance);\r\n+\r\n \t\treturn updateDistance;\r\n \t}\r\n \r\n@@ -83,9 +89,15 @@ public class TiLocationHelper\r\n \t\t\tint updateFrequency = buildUpdateFrequency(frequency);\r\n \t\t\tfloat updateDistance = buildUpdateDistance(accuracy);\r\n \r\n-\t\t\tLog.i(LCAT, \"registering listener with provider [\" + provider + \"], frequency [\" + updateFrequency + \"], distance [\" + updateDistance + \"]\");\r\n+\t\t\tLog.i(LCAT, \"Registering location listener on network and GPS providers, frequency [\" + updateFrequency + \"], distance [\" + updateDistance + \"]\");\r\n+\r\n+ // Updated 2011-12-05 by Keith Gable :\r\n+ // * Instead of using the provider we detected, use both providers. When onLocationChanged fires in\r\n+ // TiLocation.java, updateProvider will be called and then we will use the best provider. This will\r\n+ // permit the app to at least get an instant location initially.\r\n+\t\t\tlocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, updateFrequency, updateDistance, listener);\r\n+\t\t\tlocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, updateFrequency, updateDistance, listener);\r\n \r\n-\t\t\tlocationManager.requestLocationUpdates(provider, updateFrequency, updateDistance, listener);\r\n \t\t\tlistenerCount.incrementAndGet();\r\n \t\t} else {\r\n \t\t\tLog.e(LCAT, \"unable to register, provider is null\");\r\n@@ -160,12 +172,16 @@ public class TiLocationHelper\r\n \t{\r\n \t\tString provider;\r\n \r\n-\t\tif ((preferredProvider != null) && isValidProvider(preferredProvider)) {\r\n-\t\t\tprovider = preferredProvider;\r\n-\t\t} else {\r\n-\t\t\tCriteria criteria = createCriteria(accuracy);\r\n-\t\t\tprovider = getLocationManager().getBestProvider(criteria, true);\r\n-\t\t}\t\t\r\n+ // Updated 2011-12-05 by Keith Gable :\r\n+ // * Always create criteria and get the best provider. We don't care about\r\n+ // the preferred provider.\r\n+\r\n+ Log.i(LCAT, \"Getting best provider...\");\r\n+\r\n+\t\tCriteria criteria = createCriteria(accuracy);\r\n+\t\tprovider = getLocationManager().getBestProvider(criteria, true);\r\n+\r\n+ Log.i(LCAT, \"...and it is \" + provider);\r\n \r\n \t\treturn provider;\r\n \t}\r\n@@ -179,13 +195,16 @@ public class TiLocationHelper\r\n \t\t\tint value = accuracy.intValue();\r\n \r\n \t\t\tswitch(value) {\r\n+\t\t\t // Updated 2011-12-05 by Keith Gable :\r\n+\t\t\t // * ACCURACY_BEST/NEAREST_TEN_METERS/HUNDRED_METERS no longer require\r\n+\t\t\t // altitude/bearing/etc.\r\n \t\t\t\tcase ACCURACY_BEST :\r\n \t\t\t\tcase ACCURACY_NEAREST_TEN_METERS :\r\n \t\t\t\tcase ACCURACY_HUNDRED_METERS :\r\n-\t\t\t\t\tcriteria.setAccuracy(Criteria.ACCURACY_FINE);\r\n-\t\t\t\t\tcriteria.setAltitudeRequired(true);\r\n-\t\t\t\t\tcriteria.setBearingRequired(true);\r\n-\t\t\t\t\tcriteria.setSpeedRequired(true);\r\n+\t\t\t\t\tcriteria.setAccuracy(Criteria.ACCURACY_FINE); // ACCURACY_HIGH preferred, but requires Android 2.3+\r\n+\t\t\t\t\tcriteria.setAltitudeRequired(false);\r\n+\t\t\t\t\tcriteria.setBearingRequired(false);\r\n+\t\t\t\t\tcriteria.setSpeedRequired(false);\r\n \t\t\t\t\tbreak;\r\n \t\t\t\tcase ACCURACY_KILOMETER :\r\n \t\t\t\tcase ACCURACY_THREE_KILOMETERS :\r\n-- \r\n1.7.3.4\r\n\r\n{code}\r\n\r\nThis works for us because now we get a more-or-less instant response to a location event handler (as in iOS), and then the location will eventually refine to something better (GPS). Theoretically; my custom SDK hasn't been tested by our QA team yet.\r\n\r\nI don't think this patch is worthy of anything other than to be a usecase-specific hack that may also work for the OP. My personal preference, given that geolocation works differently on iOS and on Android, is either to:\r\n\r\n# Implement the complete [W3C Geolocation|http://dev.w3.org/geo/api/spec-source.html] standard consistently on both platforms, or\r\n# Create an Android geolocation module and an iOS geolocation module, so that the handling specific to both mine and the OP's usecase can be implemented as if it were native.\r\n\r\nAlso sorry I couldn't actually attach this patch as a .patch. I guess as I'm not the reporter that I can't.", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-08T15:48:25.000+0000", "updated": "2011-12-08T15:48:25.000+0000" }, { "id": "175515", "author": { "name": "kwhinnery", "key": "kwhinnery", "displayName": "Kevin Whinnery", "active": true, "timeZone": "America/Chicago" }, "body": "Hi Keith,\r\n\r\nThanks for the comment and the patch - we'll leave it up here in case anyone would like to attempt to apply it. This is definitely a parity issue, where the behaviors for Geolocation tracking are not the same across platforms. We're probably not going to accept the patch as-is because we need to revisit this API and make sure it's uniformly implemented across all platforms, with unit tests that match the desired behavior.\r\n\r\nAlso, to accept any code at all for Titanium Mobile under any circumstances, we require a contributor agreement to be on file for the patch submitter. To register a CLA, you can visit http://developer.appcelerator.com/cla.\r\n\r\nThanks, and we'll get this scheduled ASAP.", "updateAuthor": { "name": "kwhinnery", "key": "kwhinnery", "displayName": "Kevin Whinnery", "active": true, "timeZone": "America/Chicago" }, "created": "2011-12-08T19:36:24.000+0000", "updated": "2011-12-08T19:36:24.000+0000" }, { "id": "175523", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "As I mentioned via Twitter... my patch is nothing more than a hack to support more quickly giving my app an instant location. While I think that the behavior somewhat matches ACCURACY_BEST on iOS, it doesn't do it exactly. Definitely the more appropriate behavior would be to subscribe to updates from both GPS and network and once a reliable GPS signal is picked up, ignore updates from the network (until GPS is lost, then go back to network). Right now, it picks one or the other, but that's not consistent with iOS.\r\n\r\nHonestly, it'll probably be easier to implement iOS geolocation and Android geolocation, because the APIs are very different. (Or, like I said, the W3C Geolocation API, which matches neither API.) Because, for example, my desired behavior is good for something where we need to get the best fix possible as soon as possible (like navigation), but I would sure hate to make that behavior apply to everyone.\r\n\r\nI will go ahead and register a CLA, but please don't take my patch as-is :).", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-08T21:58:11.000+0000", "updated": "2011-12-08T21:58:11.000+0000" }, { "id": "175524", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I will have to get my employer to OK filling out a CLA due to the patent licensing thing, which is well above my pay grade :)", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-08T22:05:41.000+0000", "updated": "2011-12-08T22:05:41.000+0000" }, { "id": "175807", "author": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Sorry, I can't sign the CLA... But my patch is a hack anyways.", "updateAuthor": { "name": "ziggythehamster", "key": "ziggythehamster", "displayName": "Keith Gable", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-12T12:45:09.000+0000", "updated": "2011-12-12T12:45:09.000+0000" }, { "id": "180183", "author": { "name": "bitshftr", "key": "bitshftr", "displayName": "Shawn Lipscomb", "active": true, "timeZone": "America/New_York" }, "body": "I agree with Keith's goals:\r\n\r\n1. Improve the current \"require a great satellite lock and ignore that there's a network location device in this phone\" method. If I \"prefer\" the GPS provider, but can't get a GPS lock, then network location is ok. preferredProvider should be just that...the preferred provider of locations. It may be usefull to offer a new minimumProvider property so that apps that need GPS-only locations can lock out network-based locations.\r\n\r\n2. Ability to get an instant location response as soon as the listener is activated, with continued 'location' event firings as the GPS comes on line and the location becomes more and more precise.\r\n\r\nAs far as parity goes, this process should behave the same way on Android and iOS, when all is said and done.", "updateAuthor": { "name": "bitshftr", "key": "bitshftr", "displayName": "Shawn Lipscomb", "active": true, "timeZone": "America/New_York" }, "created": "2012-01-23T11:04:43.000+0000", "updated": "2012-01-23T11:04:43.000+0000" }, { "id": "180194", "author": { "name": "bitshftr", "key": "bitshftr", "displayName": "Shawn Lipscomb", "active": true, "timeZone": "America/New_York" }, "updateAuthor": { "name": "bitshftr", "key": "bitshftr", "displayName": "Shawn Lipscomb", "active": true, "timeZone": "America/New_York" }, "created": "2012-01-23T11:14:22.000+0000", "updated": "2012-01-23T11:14:22.000+0000" }, { "id": "187220", "author": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing bug. Verified fix using code from TIMOB-7565 on:\r\n\r\nSDK build: 2.0.0.v20120319003254\r\nRuntime: v8, rhino\r\nTitanium Studio, build: 2.0.0.201203182248\r\nDevice: LG Slate (3.1)", "updateAuthor": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2012-03-19T15:11:21.000+0000", "updated": "2012-03-19T15:11:21.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }