Determining GPS Availability in Android
Greetings, habrasociety!
This article, I hope, will be a good help for beginners in the field of programming for Android. Or maybe even seasoned pros glean something.
So, I needed to somehow determine if a GPS fix is currently available. It would seem that LBS (location-based service) is a promising and popular thing, and Google, understanding this perfectly, will provide an easy-to-use tool for their development. Yeah, I ran away ... It's not so simple, so I have to refine myself to a certain extent.
Well, what is the problem here? The problem is determining the current location of the user. There are several types, but TK tells you to use GPS and positioning on cell towers. The task is to determine the current coordinates with maximum accuracy, i.e. ideally by GPS. If it is not available, then on the towers. If there is a GPS signal, then everything is easy and simple - we take the coordinates from the satellite and do anything with them. If there is no signal, then when processing the coordinates, you run the risk of running into null, which is very little good, and if the exceptions are not processed properly, there may also be something with sad consequences. So, we need to somehow determine whether we have a fix?
Well, the problem is visible - we will solve it!
Let's start by tapping the LocationManager. There is an interesting property isProviderEnabled () in it that returns a Boolean value. Hurrah? Sooner ... This value only characterizes whether the GPS receiver of your phone is on or not (in fact, you could guess by the name). The first pancake turned out as always, move on.
We climb into the insides of the LocationListener. What do we see? Bah, this is the onStatusChanged () handler! Ideally, it responds to a change in provider status by setting appropriate values. Ideally ... He does not respond to anything since android version 2.1! With sadness we pass by.
Continue? Of course we continue! The following feint with ears looks obvious - comparing the time of the last fixed fix with the current system time. It would seem logical - since the fix is old, then GPS is not available. Not quite so: fixes come only when driving, so you can confuse the inaccessibility of satellites with simple sitting in place. Agree, it will not be very nice if you sit yourself sitting, and then suddenly - oppa! - and your phone decided that you teleported at 400-500 meters. Again, not that, but we will remember the receiver - it will come in handy.
Now let's look towards GpsStatus.Listener that implements the onGpsStatusChanged (int event) method. The event variable can take several values, but we are interested in GPS_EVENT_SATELLITE_STATUS. The occurrence of such an event indicates that your receiver is analyzing GPS satellites. This is what we need! Then everything is simple and clear - we take the current GPS status and pull out available satellites from it. In the simplest case, we are simply interested in their number.
A small digression for beginners in the field of navigation. To determine the current coordinate, we generally need three satellites (for a three-dimensional coordinate). But this is if you have an atomic clock, which is very, very rare in the case of mobile devices. Therefore, to synchronize time, we need another satellite.
The status handler will look something like this:
The status variable contains information about all available satellites.
So, then everything is fine - we look at the number of satellites, if there are less than four, then there is no fix and cannot be, then we use other positioning methods (excuse me, but I won’t describe the specific implementation ) This method can be crossed with the time comparison described a couple of paragraphs above. So you can set a certain period of "trust" in the fixity of the
Similarity balance. All of the above does not give you exact guarantees for determining the availability of a fix. In fact, situations in which there is certainly no fix are simply cut off. This, of course, is not quite what I wanted, but already something!
UPD : Looks like a solution has been found! This happened thanks to r_ii .
So, your GPS-receiver, when it is on, constantly receives signals in accordance with the NMEA protocol . This is what we need!
To view these signals, add the following to the code:
For this code here thanks to this topography 2m0nd . A full description of the protocol is here (pdf).
Actually, the small thing is to parse the received string. In this case, we are interested in the lines with the key (first) field $ GPGGA, and in them the parameter number 6, which is smartly called GPS Quality Indicator. It takes the following values:
PS In no case do I claim authorship of these methods, because everything was found exclusively using google. The purpose of the article is to collect all the information in one heap and some structuring it so that the next ones traveling to the fabulous world of navigation and programming of mobile devices with a small green creature do not waste time and nerves.
PPS Obviously, the method is far from ideal, so its improvement continues. Any help and criticism (objective) is welcome!
This article, I hope, will be a good help for beginners in the field of programming for Android. Or maybe even seasoned pros glean something.
So, I needed to somehow determine if a GPS fix is currently available. It would seem that LBS (location-based service) is a promising and popular thing, and Google, understanding this perfectly, will provide an easy-to-use tool for their development. Yeah, I ran away ... It's not so simple, so I have to refine myself to a certain extent.
Well, what is the problem here? The problem is determining the current location of the user. There are several types, but TK tells you to use GPS and positioning on cell towers. The task is to determine the current coordinates with maximum accuracy, i.e. ideally by GPS. If it is not available, then on the towers. If there is a GPS signal, then everything is easy and simple - we take the coordinates from the satellite and do anything with them. If there is no signal, then when processing the coordinates, you run the risk of running into null, which is very little good, and if the exceptions are not processed properly, there may also be something with sad consequences. So, we need to somehow determine whether we have a fix?
Well, the problem is visible - we will solve it!
Let's start by tapping the LocationManager. There is an interesting property isProviderEnabled () in it that returns a Boolean value. Hurrah? Sooner ... This value only characterizes whether the GPS receiver of your phone is on or not (in fact, you could guess by the name). The first pancake turned out as always, move on.
We climb into the insides of the LocationListener. What do we see? Bah, this is the onStatusChanged () handler! Ideally, it responds to a change in provider status by setting appropriate values. Ideally ... He does not respond to anything since android version 2.1! With sadness we pass by.
Continue? Of course we continue! The following feint with ears looks obvious - comparing the time of the last fixed fix with the current system time. It would seem logical - since the fix is old, then GPS is not available. Not quite so: fixes come only when driving, so you can confuse the inaccessibility of satellites with simple sitting in place. Agree, it will not be very nice if you sit yourself sitting, and then suddenly - oppa! - and your phone decided that you teleported at 400-500 meters. Again, not that, but we will remember the receiver - it will come in handy.
Now let's look towards GpsStatus.Listener that implements the onGpsStatusChanged (int event) method. The event variable can take several values, but we are interested in GPS_EVENT_SATELLITE_STATUS. The occurrence of such an event indicates that your receiver is analyzing GPS satellites. This is what we need! Then everything is simple and clear - we take the current GPS status and pull out available satellites from it. In the simplest case, we are simply interested in their number.
A small digression for beginners in the field of navigation. To determine the current coordinate, we generally need three satellites (for a three-dimensional coordinate). But this is if you have an atomic clock, which is very, very rare in the case of mobile devices. Therefore, to synchronize time, we need another satellite.
The status handler will look something like this:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
GpsStatus.Listener lGPS = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
if( event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
GpsStatus status = lm.getGpsStatus(null);
Iterable sats = status.getSatellites();
doSomething();
}
}
};
lm.addGpsStatusListener(lGPS);
The status variable contains information about all available satellites.
So, then everything is fine - we look at the number of satellites, if there are less than four, then there is no fix and cannot be, then we use other positioning methods (excuse me, but I won’t describe the specific implementation ) This method can be crossed with the time comparison described a couple of paragraphs above. So you can set a certain period of "trust" in the fixity of the
Similarity balance. All of the above does not give you exact guarantees for determining the availability of a fix. In fact, situations in which there is certainly no fix are simply cut off. This, of course, is not quite what I wanted, but already something!
UPD : Looks like a solution has been found! This happened thanks to r_ii .
So, your GPS-receiver, when it is on, constantly receives signals in accordance with the NMEA protocol . This is what we need!
To view these signals, add the following to the code:
lm.addNmeaListener(new GpsStatus.NmeaListener() {
public void onNmeaReceived(long timestamp, String nmea) {
parseNMEA(nmea);
}});
For this code here thanks to this topography 2m0nd . A full description of the protocol is here (pdf).
Actually, the small thing is to parse the received string. In this case, we are interested in the lines with the key (first) field $ GPGGA, and in them the parameter number 6, which is smartly called GPS Quality Indicator. It takes the following values:
- 0-fix is not available
- 1-GPS fix
- 2 differential fix
PS In no case do I claim authorship of these methods, because everything was found exclusively using google. The purpose of the article is to collect all the information in one heap and some structuring it so that the next ones traveling to the fabulous world of navigation and programming of mobile devices with a small green creature do not waste time and nerves.
PPS Obviously, the method is far from ideal, so its improvement continues. Any help and criticism (objective) is welcome!