📜 ⬆️ ⬇️

GPS-monitor for android "KidsTrack"

Task: summer is coming, children spend more time somewhere on the street, and I would like to know where they are. Ideal - I just give them an old android phone with me, and then watch them on the map on a large home monitor.
In this article, I will tell you why and how I wrote my first Android application with GPS functions “KidsTrack”, and what discoveries I made. The article will be useful to those who recently started programming for Android.


Searches on Google Play have given me hundreds of different applications with GPS monitor features. I already started to sort through them, but at about the 2nd decade I realized that the time spent on the choice may turn out to be quite comparable with the time spent on development. After all, my functional requirements are very simple:

It's all!

There are also requirements that are not related to functionality, but which are no less important:
And yes, the coordinates will be stored on a server that is not free. But hosting now costs such a penny that I consider it wrong to take money from people for keeping a pair of numbers (or even a few kilobytes).

In short, having tried several applications from Google Play, I decided to write the tracker myself.
')
Further, everything is trivial: installed Android Studio, drew a single screen with 3 buttons, wrote, as it seemed to me, the service, debugged everything in the emulator, then in a USB debugger, everything seemed to work.
Screen with 3 buttons



But as soon as I tried to run on a physical device, surprises began. I would like to tell about some of them.

Power Management Surprises



Real android devices tend to turn off their power whenever possible. Only very primitive system clocks are constantly receiving power (the mobile communication module is not considered here). The clock has a register (s) where, using the AlarmManager, you can record the time of the next wake-up of the telephone processor. If the processor is not awakened by the clock, then it will continue to sleep without doing anything. This is done for a simple reason: the included processor will discharge the battery in an hour. Therefore, if it is necessary for the service to do something once a minute, then desktop programming techniques like Thread.sleep (60000) will not work, but instead use the AlarmManager , something like this:

public class YourService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { /* -  */ ... /*    */ Intent ai = new Intent("info.izhforum.kidstrack.START_ALARM"); PendingIntent pai = PendingIntent.getBroadcast(mInstance, 0, ai, 0); mAlarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+60000, pai); ... } } 

In this example, we program the AlarmManager to wake up the phone in 1 minute, and send an intent START_ALARM to all applications who subscribe to it.

Reception of intents in all textbooks is carried out by the object BroadcastReceiver, however, if we need to:
  1. the phone was waking from deep sleep
  2. started our service,
  3. did not fall asleep until completion

then BroadcastReceiver will not work, and WakefulBroadcastReceiver should be used instead - this object is guaranteed not to let the phone go to sleep until the completeWakefulIntent method is called. Anyway, I never managed to get the BroadcastReceiver to work reliably on a physical device.

If your service can theoretically access the Internet via WiFi, then you need to take care that the WiFi module also has power on during the connection, since it has a separate one. If this is not done, it is difficult to understand why the application does not work on a physical device: after all, when debugging on an emulator or device connected to a debugger via USB, the WiFi module power does not turn off, and everything works fine. To prohibit turning off the power of WiFi, you can:

 private WifiManager mWifiManager = null; private WifiManager.WifiLock mWifiManagerLock = null; ... mWifiManagerLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWFL"); mWifiManagerLock.acquire(); /*    / */ mWifiManagerLock.release(); 


GPS Surprises


In the first version of the application, I made the determination of the coordinates of the device only using the provider "GPS". And it was very surprising to me to observe on the server, as more than 90% of the devices could not determine the coordinates and sent zeros.
As it turned out, GPS is a rather capricious technology with a lot of limitations, low speed and unpredictable accuracy. When using a traditional GPS, the receiver's sensor should receive data on all GPS satellites (there are more than 2 dozens of them), among all of them, choose the most suitable ones and calculate the coordinates from them. Data acquisition and brute force can take 5 minutes or more, so the first “cold” GPS start is always the slowest.
If the GPS receiver has a clock and remembers the past coordinates and positions of the satellites, then it can use this data to determine which satellites you can attach to at the moment. Therefore, restarting GPS is usually much faster.
In modern smartphones, the initial coarse determination of coordinates can be carried out using the nearby transmitting cell towers, which also makes it possible to accelerate the GPS cold start. To use this method, permission is required to use the “network” provider in Manifest, so the Internet can be used to determine the coordinates of the towers.
Another function of the “network” provider is to determine coordinates using visible WiFi networks. The definition is performed by searching for the coordinates of the currently visible networks by their names and MAC addresses on Google servers via the Internet. Of course, reverse traffic also goes in the background and without unnecessary notifications: the phone, when it has determined its GPS coordinates, can quietly send data about the WiFi networks surrounding it to Google servers, in order to maintain the current state of the WiFi network base. Sad thoughts about the potential power of Google over the owners of Androids and WiFi networks will be left out of this article ...
Having clarified all these nuances, I have corrected the application in an emergency way, so that it uses not only the GPS provider but also the “network”. After this, the typical sequence of calls to the onLocationChanged method began to look like this:
   1) 00: 00.234 provider = “network”, accuracy = 1672m // send coordinates to cell towers
   2) 00: 00.933 provider = “network”, accuracy = 52m // send coordinates via WiFi
   3) 00: 16.310 provider = “gps”, accuracy = 28m // GPS coordinates were sent

Still, I really wanted to use GPS, as this is usually the most accurate way, so I set the waiting time for the signal from the GPS sensor to 30 seconds, and if this is the first start, to 2 minutes. And if the GPS sensor did not work, then the coordinates from the provider “network” are used. After this change, devices began to send normal, non-zero coordinates to the server.
The accuracy of the GPS was also very conditional. For example, the accuracy of the coordinates received from the sensor of a stationary lying device can often look like this:
	 05:13:05 76m
	 05:14:36 ​​68m
	 05:15:58 37m
	 05:17:20 79m
	 05:19:00 116m

From these data it is clear that GPS is good for finding buildings or other large objects, but finding a person in a crowd, or a phone in a snowdrift will not be easy.

Separately worth mentioning is the power of GPS. The GPS module is quite voracious, so the textbooks recommend that calling requestLocationUpdates not to set too short parameters for the minimum time and distance interval. But in my experiments with 3 different physical devices, it turned out that the constantly-on GPS module sits the battery in the same way with different parameters. Later I found somewhere mentioning that these parameters affect only the frequency of calling the onLocationChanged method, but not necessarily the power consumption of the sensor itself.

Other surprises



Google Play : The first version lay on Google Play for two days, after which it was replaced by a new one, with a corrected coordinate determination algorithm. Despite the fact that this happened already two weeks ago, I continue to see on the server that very often the activation of the old version continues to occur. I have already added a message about the need for updating on the monitoring webpage, but this does not always help. It is not clear where in general people take the old version. I do not know how to explain it.

Users : Almost a third of the users who installed the application never opened the page where the device can be monitored. Without the monitoring page, the application is useless, so I can not explain this phenomenon either.
monitoring page



Yandex.Maps : The monitoring page was initially implemented using the Yandex.Maps API, since the ID is not required there, and there are no restrictions on the number of map downloads per day. But it turned out that on weak devices, Yandex.Maps either inhibit or do not open at all. I had to do this page in 2 versions: Yandex.Maps for desktops, and Google Maps for weak mobile devices. Google Maps were much faster.

Results


From a practical point of view, the results are, of course, modest, since there are already many, much more advanced GPS monitors. But judging by the reviews, it was the simplicity of KidsTrack that appealed to many.
For me personally, the results are much more impressive. The main result is an invaluable experience that could not be obtained from articles or textbooks. The rake, described above, forced to revise the realism and design of other larger projects that I work on.

Source: https://habr.com/ru/post/257443/


All Articles