In this part we will finish the application “Time Manager” from the first part .
Immediately express my deep gratitude to Belkin and to all those who pushed the first part, you helped me with the invite)
I want to draw your attention to the fact that I refused to use the service, as originally intended.Judge for yourself, to start the process only to increase the timer every second - stupidity.The solution is simple: before each program stop, we save time, and after starting, we subtract it from the current time, getting the number of seconds.
')
Action plan:
Bugfixes of the previous version.
Code modification, for the application to work permanently, and not just for the running Activity
Notifications
Leave this whole thing to the market
I just want to apologize and praise) I apologize for making you wait a long time, and to praise that the other day Android brought me the first well, ooooochen good money and I bought myself xbox myself and lost it all weekend, so I was delayed)
I repent, but it just flew out of my head that the string with the counter can be set via String.format (); which I did.
To do this, we go to TimerTask, delete all Strings from the list of variables, delete portions of the code where, before seconds and minutes, zeroes are added, and
We remove the need to keep the application running.
As I said earlier, it’s not advisable to fence the service in this case. I do not argue, I really wanted to write something about it, but the fact that I did not do it, to some extent, howto). In addition, on Habré there is a wonderful article "Good night"3fonov 'a, in which it is perfectly told about services, namely about the fact that there are two types of them:
1. Created, it worked, stopped.
2. Connected, executed the code under the command of the connecting activity, stopped.
3fonov described in detail the second part, there are very subtle points with the interface and the aidl file, on which I once spent a day of working time. In the first type, everything is quite simple. Take as a basis, for example, our class, namely its methods onCreate () and onDestroy. All work in this service takes place in them.
A little ad-libbing.And where should I use what type of service?
The second type of service is very convenient for applications that imply quite active user interaction with the server, for example, the same Google Talk, the service is constantly hanging in memory.By calling the onBind command, the Activity connects to this service and asks, say, who is online, to which the service responds with the data loaded at the time of the last update.In the same team, for sure there are methods that allow you to send messages, set statuses.The advantage is that we have one socket, one connection, which is implemented just in this service, for background work and for a user.
The first type, in my opinion, is much more convenient for applications where the user has much less impact on the server, I mean, let's say, the content search function.At the moment I am writing an application, whose service has just TimerTask for content updates, when updating, it stores all the information in a local database, and sends a broadcast message (popularly Broadcast) about updating the interface.At the same time, if the Activity is started, then it will pick up this message and re-read the database, displaying all new elements, otherwise Broadcast will simply not do anything.The plus of this type of service is, according to my observations, the time for its development and implementation, well ... I think there are 3 times less than the services in the ability to connect to them Activity.
So, after the retreat, let's continue our re-coding)
In order for the application to continue to count the time, even when it is not active, I came up with such an algorithm.
When an application is closed, it saves the current time in settings, two work and rest timers and two boolean values whether these timers are running. Then, when we start, we read these parameters, and we subtract the current time value from the settings from the actual current time (It was more correct to call this parameter the date of the last run, or something like that).
All this is done in a few lines of code.
Add this line to the onStop () method (remember, the method called when an activity is killed and once again refer to Activity lifecycle ) before the method that saves the settings.
I will refresh in memory.stats_editor is a variable of the SharedPreferences.Editor class that saves the settings of the application, but we use it as data storage.There is also the SharedPreferences class, but it is only for reading these settings.The putLong method is reported with two String variables, a settings key and a long value.There are also methods putString, putInt and so on, they, respectively, the second parameter will be String, int ... They are read by the getString method, getInt, etc., also with two parameters: key and default value, for example, if the settings are If the system does not find it, it will return the default value.
System.currentTimeMillis () - returns the long value of the current time in milliseconds.
To all the variables that we created in the first part, we add the int last_time variable; to get the difference between the current time and the time of the last launch (or rather stop) of the application.
Then go to the onCreate () method and add it there:
Attention! IMHO is worth mentioning, although I hope everyone understands that you need to add this line after we initialize the saved_stats variable, otherwise we will catch a NullPointerException.
Chew: The current time is the last run time (more precisely, the stop) and all this is divided into 1000, to get a millisecond second, the whole structure has a return type int.
Division?This is an integer variable! - you say, in Java, when you divide an integer into an integer, the whole part of the division will return.
It remains to add these seconds to the active counter. We are looking for the same onCreate () construction, which, depending on the Boolean variables, resting and working increases the size of the text of the counters and appends this increase there.
if (resting)
{
rest_timer.startAnimation (magnify_rest);
rest_time + = last_time;
}
if (working)
{
work_timer.startAnimation (magnify_work);
work_time + = last_time;
}
We start, we try, everything works for me, so it should be with you.
Notifications
The algorithm is as follows: if the counter is on, then we display a notification when the applet is stopped, and send the command to hide notifications in any case when the program starts.
We declare and initialize the NotificationManager class variable, which just controls the notifications.
With this variable, we will need two methods cancel () and notify (). The first, as you may have guessed, removes the notification. One parameter is passed to it - id, in case the application has several notifications, in order to remove some concrete one, we use this identifier. Notify () has two parameters — id and a variable of the Notification class.
Since my application has only one notification, feel free to put 0 or any other number instead of id. It is important that they have been created and canceled the same.
After initializing the variable notificationManager, you can immediately use the cancel () method to kill the notification when the application starts.
2. We describe it - which lines and image to use, as well as what should be launched when clicking on this notification.
3. Make notify ();
intent - variable of the PendingIntent class - just here it is indicated which class should be launched when pressed. Also pay attention to the last parameter, the flags for the running intent are sent there, I have a flag set for the new intent to update the old one.
The constructor of the notification is the picture, the text that will be shown when creating the notification, when it is the full width of the notification bar, the notification time.
setLatestEventInfo is two lines: the first is what is displayed in large print, the second is the signature in small print and Intent to run.
notification.flags - as you know, android has two types of notifications. A vivid example of this is the calendar and the mounting of a flash drive. One is forthcoming, the other is current. Notification.FLAG_ONGOING_EVENT - sets the current status to the notification.
By the way, you can use another flag - Notification.FLAG_AUTO_CANCEL, and remove the line that removes the notification from the onCreate () method.In general, read the explanations, there are a lot of interesting things)
notify - actually apply this notification.
Here is how it all looks.
We collect applet, we try to start. Everything should turn out wonderfully, but for every fireman I share source codes.
versionCode - needed for the market. It compares the current installed code with the code in the market and if it offers less update.
versionName is a “readable” version number.
Since after writing the first part of the application was available in the market, it's time to update it. I increment versionCode by 1, and in versionName I put 1.1, although this is all up to you, even though you have been collecting all your life, 0.cht and a little little more than one and onenew.cht and a bit more.
Save the project and right-click on it. Android tools - Export Signed Application Package. Enter the name of the project for export, usually everything is already stamped and just click next. Then you have to choose an existing one or create a new key.
Enter the path to the key and two times the password.
Fill something like this. Regarding the period of validity, Google recommends setting it up almost until 2030, so we unscrew it to the maximum)
Click next and sign, getting the apk file with the application.
Just in case, I recommend to execute the adb install TimeManager_2.apk command, which will install the already signed version on the phone and check the functionality again.
Go to the admin area of the market and fill in our application. In principle, everything is also clear there, you just have to explain how to take screenshots.
Need an installed SDK.
In the terminal we do ddms, select our receiver or emulator on the left, Device - Screen Capture.
And do not forget to write a description of the program and its name in Russian)
Creating an activity without threads, we mean that all code will be executed in one thread, so-called. UI Thread, because it draws the entire interface. Why does the interface slow down when performing long calculations? That's right, because everything works in one thread, and until the calculations end, the interface will not continue to be drawn. For this purpose, they use threads, although this is far from their main purpose. But not in the UI Thread interface can not draw. For these tasks, there are Handlers that are called from the thread. In them there is a drawing. In general, they provide a lot of utilities, as for example, you can make one thread at the end call another, well, this is an example. But they are very cumbersome, and it is much easier to make the runOnUiThread () method, which has the Runnable class in its parameters, where the run () method describes everything that needs to be done exactly in the interface stream. I apologize in advance, yes I am a shitty speaker, but something like this in general)