I am working on gps tracking apps in android. Here is my code architecture:
BackgroundSyncService : A service class that is used for getting location update. Here GoogleApiClient is initialized and implements others Location related methods.
AppRunCheckerReceiver : A BroadcastReceiver class that will check if my BackgroundSyncService is running or not in a time interval. If it stopped then it start.
GpsEnableReceiver : A BroadcastReceiver it will fire if gps status changed. It will check if my BackgroundSyncService is running or not in a time interval. If it stopped then it start.
InternetConnectionStateReceiver : A BroadcastReceiver it will fire when internet status changed. It will check if my BackgroundSyncService is running or not in a time interval. If it is stopped, then it start.
In my BackgroundSyncService service I initialize the GoogleApiClient using this way:
public void setLocationLocationRequest() {
try {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(com.google.android.gms.location.LocationServices.API).build();
locationRequest = new LocationRequest();
locationRequest.setInterval(3000);
locationRequest.setFastestInterval(3000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
googleApiClient.connect();
} catch (Exception e) {
}
Here accuricy is LocationRequest.PRIORITY_HIGH_ACCURACY and interval is
locationRequest.setInterval(3000)
here is the GoogleApiClient implementation code.
This application GPS info section contains Latitude longitude and Accuracy parameter
My Findings: in onLocationChanged(Location location) method I check the accuracy of Location object in this way : location.getAccuracy(). Here if accuracy is less than 50 meter, then I accept it.
In 85% of the cases it working like a charm. It sending me exact location from GPS. But in 15% cases, it sending me inaccurate location like more >300 meter.
The 15% device are low cost China brand mobile.
My Questions:
How can i make accuracy level near 99%. Is there any problem on my code architecture?
Does GPS accuracy depends on device configuration? if YES then what can I do for low configuration device?
How Uber, Go-JEK etc. ride sharing apps works for all device? Is they have extra coding for GPS only?
My application is for Bangladesh. Here internet is slow. Is it has negative impact on GPS accuracy?
Thanks in advance for this thread. And also sorry for bad english.
How can i make accuracy level near 99%. Is there any problem on my code architecture?
This is real life scenario. You cannot ensure that all the location providers will work as expected. You should ask for best available position.
a) Does GPS accuracy depends on device configuration?
YES. Some devices may have older GPS chipsets which can only track GPS signals (USA) since there are other positioning systems like Galileo (Europe), GLONASS (Russia), QZSS (Japan) and Beidou (China). The more the chipset support for these types the more chance you get to track more satellite hereby position fix. Also TTFF (time to first fix) depends on how many channels do the gps receiver has.
b) If YES then what can i do for low configuration device?
Since this is a hardware issue, you cannot do anything here. But other location sources can compensate the lack of GPS data such as AGPS (aided gps), wifi and cellular positioning. Also there are some paid options which provides a database to locate your device using wifi access points and cellids (they claim that they provide best solution on wifi but i m not sure as I dont use it. you can check it out http://combain.com). Wifi and cellid also depends on how many wifi access point and cell tower available around and how far they are (signal strength). If you need 50m accuracy, cellular positioning has nothing to do but wifi has a chance to get closer to this value.
Some study results from 2009 [3]
3G iPhone w/ A-GPS ~ 8 meters
3G iPhone w/ wifi ~ 74 meters
3G iPhone w/ Cellular positioning ~ 600 meters
How Uber, Go-JEK etc. ride sharing apps works for all device? Is they have extra coding for GPS only?
They may have specific Location strategies but it will based on using other sources during GPS outage.
My application is for Bangladesh. Here internet is slow. Is it has negative impact on GPS accuracy?
Other answers claims that internet is not related to GPS. Yes it is true it is not related to GPS but location. AGPS uses internet to fetch 3 types of data (Satellite signals, almanac and ephemeris) which assist GPS to provide position fix faster. If ephemeris and almanac are outdated or the device moved several hundred km from the previous position fix then it is called cold start and takes around 12-15min without AGPS.
Fused location provider already knows how to provide best solution with these configurations, so you should bless it.
References:
[1] http://gpssystems.net/agps/
[2] http://gpsinformation.net/main/almanac.txt
[3]
https://communityhealthmaps.nlm.nih.gov/2014/07/07/how-accurate-is-the-gps-on-my-smart-phone-part-2/
First, (and second)
How can I make accuracy level near 99%. Is there any problem on my code architecture?
Does GPS accuracy depends on device configuration? If YES then what can I do for low configuration device?
Both - device configuration and code architecture, are important here. If you are already at an 85% success rate, the code architecture is alright I think.
As far as GPS goes, line-of-sight is an important factor when it comes to device configurations and accuracy.
Although a low cost mobile could return an accurate location with a clear line-of-sight. You can try running 2 cycles more/waiting to attain higher accuracy.
In a worst case scenario and for what its worth, you can also try retrieving location using the LocationManager and GPS provider technique which works as a fallback in the 15% just to compare and ensure you are using the most accurate location you can get.
Location Strategies put it as
In most cases, you'll get better battery performance, as well as more
appropriate accuracy, by using the Location Services API.
How Uber, Go-JEK etc. ride sharing apps works for all device? Is they have extra coding for GPS only?
They do work but not always with highest of accuracy for locations received within the app. If there are any location hacks for us developers, we need to find them, maybe a 5th page google search result :) or benefit from the open source environment. For me, best practices and android repo links suffice. You have already followed posts like Receive location updates
My application is for Bangladesh. Here Internet is slow. Is it has negative impact on GPS accuracy?
No relation between Internet and LocationManager + GPS_PROVIDER
I have installed a fake location app and set my location different. Then opened Google Maps and Wechat app,
Google Maps shows my location as what i set(fake)
Wechat app ignores fake location and detects real location (how?)
Then i wanted to prevent wechat analyze my previously received real locations and new fake location.
Uninstalled Wechat
Restarted my device
Set my location as fake
Installed Wechat again
But same result, it detects my real location.
I really want to understand how they do this. Any ideas?
What i have tried
Gps provider spoof
Network provider spoof
Fused location provider spoof
IP geolocation spoof
Gps provider spoof + IP geolocation spoof
UPDATE
Uses GPS even when disabled.
07-02 11:46:15.504 2346-2356/? D/LocationManagerService: request 434a7e28 gps Request[ACCURACY_FINE gps requested=+1s0ms fastest=+1s0ms] from com.tencent.mm(10173)
CONCLUSION
You can fake location on older versions of wechat(lower than 6.0)
Uses something like BaiduLocationSDK. It's not affected from any mock attempt through LocationManager and Fused provider.
I'm not sure but, seems like BaiduLocationSDK uses GPS through hardware level.
To check for fake location most applications look for GGA and GSV sentences in the NMEA (National Marine Electronics Association) data received by them. The fake location providers do not send NMEA sentences along with location, so this parameter can be used to If they haven't received and GGA and GSV sentences in a threshold amount of time, say 100 seconds they red flag the current location provider.
This process is repeated till a valid set of NMEA sentences has been received and then the corresponding location is selected.
To retreive NMEA data LocationManager#addNmeaListener(GpsStatus.NmeaListener listener) is called and then in the listener
void onNmeaReceived(long timestamp, String nmea) {
Log.d("Nmea Data",nmea);
}
for more info see adding a NmeaListener
the NMEA sentences, GGA and GSV look as follows
GGA - essential fix data which provide 3D location and accuracy data.
Sample : "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"
Where:
GGA Global Positioning System Fix Data
123519 Fix taken at 12:35:19 UTC
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
1 Fix quality: 0 = invalid
1 = GPS fix (SPS)
2 = DGPS fix
3 = PPS fix
4 = Real Time Kinematic
5 = Float RTK<br/>
6 = estimated (dead reckoning) (2.3 feature)
7 = Manual input mode>
8 = Simulation mode
08 Number of satellites being tracked
0.9 Horizontal dilution of position
545.4,M Altitude, Meters, above mean sea level
46.9,M Height of geoid (mean sea level) above WGS84 ellipsoid
(empty field) time in seconds since last DGPS update
(empty field) DGPS station ID number
*47 the checksum data, always begins with *
GSV - Satellites in View shows data about the satellites that the unit might be able to find based on its viewing mask and almanac data. It also shows current ability to track this data. Note that one GSV sentence only can provide data for up to 4 satellites and thus there may need to be 3 sentences for the full information. It is reasonable for the GSV sentence to contain more satellites than GGA might indicate since GSV may include satellites that are not used as part of the solution. It is not a requirement that the GSV sentences all appear in sequence. To avoid overloading the data bandwidth some receivers may place the various sentences in totally different samples since each sentence identifies which one it is.
Sample:"$GPGSV,2,1,08,01,40,083,46,02,17,308,41,12,07,344,39,14,22,228,45*75"
Where:
GSV Satellites in view
2 Number of sentences for full data
1 sentence 1 of 2
08 Number of satellites in view
01 Satellite PRN number
40 Elevation, degrees
083 Azimuth, degrees
46 SNR - higher is better
for up to 4 satellites per sentence
*75 the checksum data, always begins with *
Source : NMEAData
Some 3rd party location sdk like BaiduLocationSDK doesn't reflect the fake location setup by system.
It's for safety purpose.
The reason I was asking the questions in the comments is that I was hoping you tested how Wechat responds to different conditions.
There are a couple of other ways to detect device location which TestProvider shouldn't affect AFAIK. This needs testing but here are some ideas:
LocationManager.getLastKnownLocation(String provider) - this allows you to force using for example a GPS provider and get cached data.
GPS NMEA listener, and a new one in API 24 - these APIs allow listening for low-level events from GPS hardware using NMEA 0183 protocol.
IP address geolocation.
You can get country-level geolocation via Telephony Manager.
Edit: added Telephony manager option.
#Bona Fide
Then you can remove the TestProvider from the LocationManager and get
the actual location.
Even wechat would use this approach before requesting location updates, to avoid providers being spoofed by other applications, like something below
// HERE WECHAT APP
// WECHAT REMOVES THEM IF ANY (just supposition)
locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
// WECHAT REQUESTING LOCATION UPDATES
// ....
So this approach causes throwing a IllegalArgumentException on the location faker app. Even in that case, i can easily handle this issue and continue spoofing GPS and NETWORK providers again,
// HERE LOCATION FAKER APP
// LOCATION FAKER APP SETS FAKE LOCATIONS
while (mRunning){
try {
locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, gpsLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
}
try {
locationManager.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, networkLocation);
} catch (IllegalArgumentException e){
locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, false, false, false, false, false, true, true, 1, 1);
locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
}
gpsLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
gpsLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
networkLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
networkLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
try {
Thread.sleep(500);
} catch (Exception e) {}
}
Everything works perfectly but out of WECHAT
Fake locations are possible if ALLOW_MOCK_LOCATION is set and a TestProvider is added to the LocationManager. To get the real location you need to do these two steps:
Detect if MockSettings are enabled and whether there are Apps installed how could fake the location.
Then you can remove the TestProvider from the LocationManager and get the actual location.
Checkout Jambaaz answer to get an example how this works in code.
Note: To remove an TestProvider you need the Permission android.permission.ACCESS_MOCK_LOCATION and ALLOW_MOCK_LOCATION is now deprecated since API 23. You can now check if the Location is from a TestProvider directly from Location.isFromMockProvider()
I have managed to spoof location with wechat and zalo, both seem just as difficult.
I would load a mock location and fake gps app. set my location. check maps and see it's correct, can even move around the world and it's working.
But wechat and zalo don't agree, they say I am in my basement lol.
THEN I uninstall fake gps app (might be able to force stop and disable) and go to wechat and clear location etc and try again and often it will move me to faked gps location. It won't stay that way after closing the wechat app though. it is temporary.
It might not be easy to do but might give someone a hint or path to look at.
I have the following code implemented to retrieve location values on Android:
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
On Android 2.3 and 4.1 this works great and returns updates at 180 samples per hour with a resolution down to 100m or less.
However, on Android 4.3 something has changed so this only provides updates at 5 samples per hour and a resolution at 2km. I haven't tested on later versions.
What has changed? Is it possible to return to the old accuracy levels again? I don't want to force GPS for power reasons. The app has ACCESS_COARSE_LOCATION permissions.
I have been testing this on a Samsung S3 if it makes a difference.
Use Google's LocationServices API instead:
https://developer.android.com/training/location/receive-location-updates.html
LocationManager.NETWORK_PROVIDER do not provide accurate location it provides you the location according to the cell tower you connected,sometimes it provides location with accuracy of 100m sometimes with 2-3km,if you do not want to get the location from gps due to power reasons i would suggest you to use fused location provides as this is an efficient and effective way to get the location on android and Google also recommends this,you can read more here in this example http://www.kpbird.com/2013/06/fused-location-provider-example.html
I'm writing a simple GPS based app for location awareness. Whenever GPS is enabled, the app requests location updates and prints latitude and longitude in a TextView. If GPS is disabled, the location provider fall-backs to LocationManager.NETWORK_PROVIDER for triangulating device position relative to neighboring cell-towers. The aim is whenever device movement is detected, it should start populating the TextView with lat/long. When there is no movement, the process should stop. In order to do so, I've implemented the location update rate as:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, this);
The above line causes very frequent location updates (even when there is no movement, I keep getting lat/long values). I read somewhere that putting minTime=0 is not a good idea (battery drains faster). When I change it to 2 or 3 seconds, the update becomes very slow (even if the device moves more than 50 meters). Changing minDistance doesn't seem to work either! I want to know what settings does Google Maps application use? Power consumption is not a limiting factor for me as I'm developing the app for some network drive test equipment (which gets constant power from vehicle's on-board lead acid battery).
The frequency of updates is highly dependent on the hardware. Good gps chips send very frequent updates(Samsung Galaxy S3) while some struggle even to show lat-lan position. The gist here is normalize the the frequency for receiving updates on the basis of distance and time. Use various time and distance configuration and test them and use the most appropriate values. For my project I used following values:
//for walking user
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5, 10, this);
//for user in a car
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2, 50, this);
Prologue:
I have seen many posts regarding improving the GPS performance and accuracy in android devices.
But i am just curios and a little embarrassed at the result that my GPS tracking app gives. Especially when i compare it with the result i get from Google latitude.
Here is MY problem:
Why am i not able to get as accurate result as Google latitude on same device at the same time.
I used the 'Criteria' facility to customize my result and provider as follows
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_HIGH);
provider = locmgr.getBestProvider(criteria, true);
I am able to GPS location results with an accuracy of 800-900 meters in a testing Device : LG Optimus pro .
The Google latitude app shows a much finer result as the location of the device.
Is there any sort of caching being done by the app.. or any more finer criteria tweaks.
I really love to see my app giving an accuracy of 20 to 30 meters or more ;-)
Use Android's native location framework, it all depends on your GPS chipset and weather conditions at the time, but through LocationManager I'm usually able to get at least a 20m accuracy. Check this tutorial out.
You can specify whether or not to work with network provided location for example, which when provided by Cell-ID might be highly inaccurate but by WiFi highly misleading, both of them can help you get approximate locations when GPS satellites are not an option.