GPS monitor for Android "KidsTrack"

Task: here comes the summer, children are spending more time somewhere on the street, and I would like to know where they are. Ideal — I just give them an old Android phone and then watch them on the map on the home monitor.
In this article, I'll tell you why and how I wrote my first app for Android with GPS functions "KidsTrack", and what discoveries he can make. The article will be useful to those who recently started programming for Android.


Search on Google Play gave me hundreds of different applications with features of the GPS monitors. I started them was to sort out, but approximately 2-m ten I realized that the time for the choice can be quite comparable to the cost of development time. Because my functional requirements are very simple:
the
    the
  • the application must periodically send anonymous coordinates to the server
  • the
  • the server should display a map with a marker in the appropriate place.

It all!

There are more requirements that are not related to functionality but not least:
the
    the
  • absence of necessity of registration, and link the accounts
  • the
  • free of charge
  • the
  • no advertising
  • the
  • the lack of unnecessary features which are already there or the phone, or in other applications, like messaging, alarm buttons, notifications, erase data, lock phone, chat, etc.
And Yes, the coordinates will be stored on the server, which is not free. But hosting costs now are a penny, that I think it is wrong to charge people money for storing pairs of numbers (or even several kilobytes).

In short, after trying a few apps from Google Play, I decided to write the tracker itself.

Further, all trivial: installed Android Studio, drew a single screen with 3 buttons, written, as it seemed to me, the service, everything debugged in the emulator, then to the USB debugger, everything seems to work.
a Screen with 3 buttons



But as soon as I tried to run on a physical device — the surprises. Some of them I would like to share.

the

Surprises power management



Real Android devices tend to turn off their power at every opportunity. Constantly get food only a very primitive system clock (a mobile communication module it is not considered here). The watch is a register(s) by AlarmManager you can record the time of the next probudi processor phone. If the processor does not Wake up the watch, then he will continue to sleep without doing anything. This is done for a simple reason: included CPU will drain your battery in an hour. Therefore, if you need to service something done every minute, the desktop programming methods like Thread.sleep(60000) will not work, and instead need to use the AlarmManager, like this:

the
public class your service extends Service {

public int onStartCommand(Intent intent, int flags, int startId) {
/* Do something */
...
/* Planned next start */
Intent ai = new Intent("info.izhforum.kidstrack.START_ALARM");
Pai PendingIntent = PendingIntent.getBroadcast(mInstance, 0, ai, 0);
mAlarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+60000, pai);
...
}
}

In this example, we programmed AlarmManager to Wake up the phone after 1 minute, and send intent START_ALARM all applications who have it signed.

Receiving intents in all textbooks is the object of BroadcastReceiver, but if we need to:
    the
  1. phone is awakened from deep sleep
  2. the
  3. run the service
  4. the
  5. not filled to completion

the BroadcastReceiver is not suitable, and instead we should use WakefulBroadcastReceiver — this object is guaranteed not to allow its phone to sleep as long as the method is called completeWakefulIntent. In any case, I never managed to get BroadcastReceiver to work reliably on a physical device.
If your service can theoretically access the Internet through WiFi, then you need to take care that the Wi-Fi module during the connection was also included, as it had a separate. If this is not done, it is difficult to understand why the app is not running on a physical device: in fact, when debugging on an emulator or device connected to the debugger through USB power module does not turn off WiFi, and everything works fine. To prohibit power off Wi-Fi, you can:

the
private WifiManager mWifiManager = null;
private WifiManager.MWifiManagerLock WifiLock = null;
...
mWifiManagerLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWFL");
mWifiManagerLock.acquire();
/* Here carry network I/o */
mWifiManagerLock.release();


the

Surprises GPS


In the first version I made the determination of the coordinates of the device only using the provider "GPS". And it was very surprising to me to see on the server, as more than 90% of the devices are unable to determine the coordinates and sent them to zeros.
As it turned out, the GPS is very delicate technology with many limitations, low speed and unpredictable accuracy. When using a traditional GPS sensor receiver needs to obtain data about all GPS satellites (and their more than 2 dozen), among them all, select the most appropriate, and to calculate coordinates. Getting data and iterating can take 5 minutes or more, so the first "cold" start GPS always the slowest.
If the GPS receiver has a clock and remembers the previous coordinates and the position of the satellites, it can use this information to identify those satellites that can be tied at the moment. So re-starting the GPS usually is much faster.
In modern smartphones the initial rough determination of the coordinates can be carried out by a nearby transmitting cell towers, which allows you to speed up cold start GPS. To use this method requires permission to use the provider "network" in the Manifest-e, to determine the I coordinate of the towers can be used.
Another function of the provider network to determine the coordinates on visible Wi-Fi networks. The determination is performed by searching the coordinates of the currently visible networks by their names and MAC addresses on the Google servers via the Internet. Of course, in the background and without notification, there is a reverse traffic: the phone, when it is determined the coordinates by GPS, can quietly send data about the surrounding WiFi-networks to Google's servers, so as to maintain the current state of the database Wi-Fi networks. Sad reflection on the potential power of Google over Android and WiFi networks leave outside the scope of this article...
Clarifying all these details I am in an emergency order have tweaked the app so that it used not only the provider "GPS" and "network". After this a typical sequence of calls to onLocationChanged began to look like this:
the
1) 00:00.234 provider = “network”, precision = 1672m // the coordinates come from the cell towers
2) 00:00.933 provider = “network”, precision = 52m // came the coordinates via WiFi
3) 00:16.310 provider = “gps” precision = 28m // here the coordinates by GPS

I still really wanted to use the GPS so as usual it is the most accurate method, so I set the timeout signal from the GPS sensor 30 seconds, and if this is the first start — 2 minutes. And if the GPS sensor did not work, then used the coordinates from the provider "network". After this change, the device began to send to the server a normal, non-zero coordinates.
The GPS accuracy also proved to be very conditional. For example, often the accuracy of the coordinates obtained from the sensor stationary laying device might look like this:
the
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 to find a man in the crowd, or phone in the snow will not be easy.

We should also mention food GPS. The GPS module is very voracious, so the books recommend when you call requestLocationUpdates not to set too short a minimum interval in time and distance. But in my experiences with 3 different physical devices, it turned out that always-on GPS module battery drain the same way under various parameters. Then I found somewhere a mention that these settings only affect the frequency of method invocation onLocationChanged, but not necessarily on the energy consumption of the sensor.
the

other surprises



Google Play: the First version has been on Google Play two days, after which it was replaced by a new one with the corrected algorithm for determining the coordinates. Despite the fact that this happened two weeks ago, I'm on the server continue to see very often continue to occur activation of the old version. I've already added a message about the need to update web page monitor, but it does not always help. It is not clear where all people take the old version. I don't know how to explain it.

Users: Almost a third of users who installed the app never opened the page where the device can be monitored. Without page monitoring app is useless, therefore, to explain this phenomenon I can't either.
monitoring page



Yandex.Card: the monitoring was initially implemented with the use of API Yandex.Cards, as these don't require ID, and there is no limit to the number of downloads cards a day. But it turned out that on slower devices Yandex.Card or hinder, or do not open. Had this page to do in 2 versions: Yandex.Cards for desktop computers and Google Maps for weak mobile devices. Google Maps was significantly faster.

the

Results


From a practical point of view the results, of course, modest, as there are already many much more advanced GPS monitors. But judging by the reviews, it is easy KidsTrack and liked by many.
For me personally, the results are much more impressive. The main result is a priceless experience that cannot be obtained from articles or textbooks. The rake described above, have been forced to reconsider the feasibility and design of other larger projects I'm working on.
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

March Habrameeting in Kiev

PostgreSQL load testing using JMeter, Yandex.Tank and Overload

Monitoring PostgreSQL with Zabbix