Can I get a GPS fix status on Android through NMEA - android

I'd like to display a GPS status icon in my application to indicate whether or not there's a valid fix to the user. There seem to be a few ways to do this, including using the API directly (which seems to have poor results based on some of the questions on SO) and guessing that a GPS fix has been dropped after a certain time has elapsed (How can I check the current status of the GPS receiver?)
Android apparently lets you grab NMEA strings directly as well:
http://developer.android.com/reference/android/location/GpsStatus.NmeaListener.html
One of the NMEA Tokens ($GPGGA) gives you fix quality information:
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
6 = estimated (dead reckoning)
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 *
It seems like I can just check that my fix status isn't 0,6,7, or 8 to see if I have a fix. But I have a few questions:
Is it reasonable to expect all Android GPS receivers provide NMEA strings?
If yes to 1, will all Android GPS receivers provide NMEA strings at regular intervals?
The separate/USB GPS receivers that I've played around with just broadcast NMEA strings at regular intervals (ie, even without a fix) so its easy to check whether or not there's a fix. I don't know if this behavior is defined by any kind of standard and is something I can rely on.
I know that not all GPS receivers broadcast NMEA strings and some transmit a closed protocol... but I don't know whether or not these kinds of receivers are used in typical retail Android devices.

Related

How does Apple or Android calculate speed in devices?

There are any documentation for this? I've checked many formulas and algorithms but didn't find an explicit definition how they get the speed provided in Geolocation object.
The GPS chipset provides the current velocity to the system along with the current location.
The chipset may compute the velocity by comparing location over time and correcting for the curvature of the Earth at the current location, or from the Doppler shift of the received satellite signals.
Whichever method is used, the operating system doesn’t need to do any processing to get the speed. The velocity data is provided along with location and altitude data directly from the GPS chip (actually chips in many newer devices support both GPS and GLONASS, but which system is used is not visible to the user).
Physics.org has a simple explanation of how GPS works
Wherever you are on the planet, at least four GPS satellites are ‘visible’ at any time. Each one transmits information about its position and the current time at regular intervals. These signals, travelling at the speed of light, are intercepted by your GPS receiver, which calculates how far away each satellite is based on how long it took for the messages to arrive.
Once it has information on how far away at least three satellites are, your GPS receiver can pinpoint your location using a process called trilateration.
But you can search for more detailed explanations of the mathematics and physics involved.
It basically scans your location (i.e. your latitude and longitude) and compares with the last check. Using euclidian distance, it can get the distance in the period of time. With the time (for example, if it scans your location every 2 seconds), it can easily estimate your speed by doing Speed = Distance/2.

How does some apps(wechat) ignore fake location and then detect the real one?

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.

Why does the Android GPS-Fix vary by 200 ms?

I am writing my Master thesis atm and analyzed about 400 different GPS-Trajectories (paths consisting of a list of longitude/latitude points and an according timestamp) recorded with the MediaQ-App (probably not important) for Android (about 310 trajectories) and iOS (about 90).
When analyzing the time intervals between the timestamps, I was expecting the inaccuracies around the 1 second frequency, in which the timestamps were supposed to be recorded, since neither Android or iOs are real-Time-OS from apps point of view. Still, why are there, what appears to be local peaks in about 200ms steps? Be nice, I do not know a lot about mobile operating systems :-)
(x-axis: seconds, y-axis: the relative probability that a timestamp will be recorded at this point in time. Ignore the exact values of the y-axis...)
The usual behavior is that an App takes the timestamp direct from the location delivered by the system. Most probably this is the case in that App, otheriwse this would be a heavy programming bug. (The delay between nominal GPS time and receiving system time of about 200ms is plausible, I saw that in my app, and in ios Map app, which makes a correction in their map api to extrapolate the location into the future, to try to compensate that delay)
Under android (and ios) it is import to know whether the location are determined exclusively by GPS. On both plattforms (ios, android) an App can set whether GPS only or combined GPS + WLAN + Cell Locationing is used.
For high quality recording is is highly recomended to use GPS only.
A GPS chip once having a location usually outputs a location with a timestamp exactly at 000. Exception can happen before the location is valid.
Under ios if the location was obtained by GPS the millisecond are always 0.
I have no experience with android, but usually the GPS chip itself sets the value to millis = 0. (However, some android phones are known to use a crippled cheap GPS chips, that are not able to get an intial position without the help of an internet conection)
It is possible to determine whether the location was obtained by GPS by looking at the course (or called heading) and speed value, which are invalid for non GPS locations (cell Tower locationing)
To know whether this time variations come from the Application (not using the GPS only mode) or if it is caused by Android, you can test that with another application on the same phone. (E.g Motion-X GPS) (Or by comparing both apps on another android phone)

Android diferentiation between GPS systems Navstar Glonass BeiDou

How can I determine the GPS signal which GPS systems comes from?
How can I differentiate between Navstar, Glonass and BeiDou GPS systems when I received a signal?
As I known there is a way to differentiation, which based on the PRN number of GpsStatus if this value is greater or equals than 200, the GPS system is BeiDou, if this value in range 65 and 88 is it Glonass. (The Navstar PRN range is 1-32 maybe.)
What is the upper limit of BeiDou PRN range?
Is there another way to determinate which GPS system signal received?
Thanks in advance.
BeiDou in its final configuration will consist of 35 satellites, 5 geostationary and 30 MEO (source). Some practical measurements (though not on Android) are here, showing values in the range 201–210. I have personally seen PRN 211 reported on a co-worker's Android phone.
Apparently the PRNs start at 200 or 201, hence the upper boundary is likely to be 234 or 235. Currently only 16 satellites are up, 2 of which are not operational, hence you will never encounter most of these numbers until more satellites are launched. 201–205 seems to be the range for the geostationary satellites, thus you might not encounter any of these unless you are within their coverage range.
Edit: NMEA seems to have created a de-facto standard for satellite IDs, which pretty much matches what has been seen on Android. I have tried to put together a list of all ranges currently in use here.

How can I read the GPS sensor data more frequently?

Even if I set requestLocationUpdates to 0 seconds and 0 meters, the GPS sensor data updates only about every second. I need the satellites SNR data more fequently; 10/s would be nice. Is there any possibility?
If you have direct access to the GPS chip, you can set the message interval for each message. On a smartphone you cannot set that message interval.
However for consumer GPS devices the maxmimum GPS message frequency is either 1/s or 2 messages per second.
So probably, as long as you don't use an specialized GPS chip with e.g 10/s msg frequency,
it does not make much sense, to raise from 1/s to 2/s.
No, the update frequency of the device is limited by the GPS hardware itself, usually to about 1hz. Android hardware seems to be mostly concerned with battery life being one reason. Also, most GPS hardware that produces an output frequency that is greater than 1hz is cheating somewhere in the background and interpolating points, which you can do in code if you want more points. This is because, in general, producing a higher output frequency means a sample of fewer points which means reduced accuracy. There are really no "easy" solutions around this problem. If you need more data and more accuracy you are looking at sensor fusions and and probably some sort of Bayesian filtering.
You set that when you start listening to the GPS. You pass it as a parameter.
requestLocationUpdates(Provider, TIME_INTERVAL, DISTANCE_INTERVAL, LISTENER)
TIME_INTERVAL is in milliseconds.

Categories

Resources