Форум программистов, компьютерный форум CyberForum.ru

Таймер, AlarmManager и Service на Android - Android

Войти
Регистрация
Восстановить пароль
 
msgusa
5 / 5 / 3
Регистрация: 29.06.2011
Сообщений: 115
12.08.2016, 17:51     Таймер, AlarmManager и Service на Android #1
Добрый вечер.
Я уже создавал тем(ы) про таймер. И мне очень здорово помогли разобраться с Андроидом, особенно OlegJV, powowstal. Собственно, нижеприведенный код отчасти будет состоять из их примеров. Так как с Андроидом познакомился относительно недавно (чуть больше недели), мне сложно довести самому дело до конца.

Я хочу сделать свой первый таймер, который бы отсчитывал время в обратную сторону. В коде, который приведу, это CountDownTimer с AlarmManager. Почему с AlarmManager? Благодаря OlegJV, я выяснил, что таймер довольно потребная вещь, а мне бы желательно, чтобы он, мой таймер, работал на длительные промежутки и при отключении экрана (выхода из приложения), таймер (а вернее AlarmManager) продолжал бы свою работу, но сам CountDownTimer останавливался бы, чтобы не расходовать мне мою батарею. Узнал, что для такой задачи существуют сервисы, отчаянно пытался вкурить как они работают, но не смог. Слишком много всего и даже не знаю за что и как ухватиться. И тем более как реализовать.

Также, есть проблема с кнопками "+" и "-" - они отвечают за добавление и вычитание времени к основному таймеру. Есть одна особенность кнопки, отвечающей за добавление. При нажатии должен включиться новый таймер (неосновной), тикающий в прямом порядке, должно добавляться значение из TextView к значению CountDownTimer-а, и новом нажатии "+" добавление по прежнему должно быть, а неосновной таймер бы обнулялся.
При нажатии "-" должно происходить только вычитание.

Кое-как реализовал, но очень криво. Неправильно все работает.
К тому же надо как-то придумать, чтобы все таймеры не обнулялись при сворачивании, при длительной неактивности приложения, или чтобы сама система не позакрывала приложение из-за нехватки памяти.

activity_main.xml
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.gmail.test.myapplication.MainActivity"
    android:transitionGroup="false">
    <!--  -->
 
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="START"
        android:id="@+id/startBtn"
        android:layout_centerInParent="true"
        android:nestedScrollingEnabled="true"
        android:visibility="visible" />
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/timeView"
        android:gravity="center"
        android:textSize="60sp"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="55dp"
        android:typeface="monospace" />
 
    <Button
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="+"
        android:id="@+id/addTimeBtn"
        android:layout_above="@+id/startBtn"
        android:layout_toLeftOf="@+id/startBtn"
        android:layout_toStartOf="@+id/startBtn"
        android:visibility="invisible"
        android:textAlignment="center" />
 
    <Button
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="-"
        android:id="@+id/subtractTimeBtn"
        android:layout_above="@+id/startBtn"
        android:layout_toRightOf="@+id/startBtn"
        android:layout_toEndOf="@+id/startBtn"
        android:visibility="invisible"
        android:textAlignment="center" />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/timeUpView"
        android:layout_alignTop="@+id/subtractTimeBtn"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="13dp"
        android:width="60dp" />
 
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:id="@+id/addTimeEdit"
        android:layout_alignBottom="@+id/addTimeBtn"
        android:layout_toLeftOf="@+id/addTimeBtn"
        android:layout_toStartOf="@+id/addTimeBtn"
        android:visibility="invisible"
        android:textAlignment="center" />
 
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:id="@+id/subtractTimeEdit"
        android:layout_above="@+id/startBtn"
        android:layout_toRightOf="@+id/subtractTimeBtn"
        android:layout_toEndOf="@+id/subtractTimeBtn"
        android:visibility="invisible"
        android:textAlignment="center" />
 
</RelativeLayout>
Main Activity
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package com.noob.wissen.timerapp;
 
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import java.util.Calendar;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
 
import java.util.Timer;
import java.util.TimerTask;
 
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 
    private Button startBtn;
    private Button addTimeBtn;
    private Button subtractTimeBtn;
    //
    private TextView timeView;
    private TextView timeUpView;
    //
    private EditText addTimeEdit;
    private EditText subtractTimeEdit;
 
    //private Timer timer;
    private Timer timerUp;
 
    private int countdown = 1200;
    private boolean timerIsStarted;
    private int countup = 0;
    AlarmManager manager;
    Long preTime;
    Long postTime;
    Long delay;
    CountDownTimer timer;
    Calendar calendar;
 
 
    @TargetApi(Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Находим элементы на разметке
        startBtn = (Button) findViewById(R.id.startBtn);
        addTimeBtn = (Button) findViewById(R.id.addTimeBtn);
        subtractTimeBtn = (Button) findViewById(R.id.subtractTimeBtn);
        //
        timeView = (TextView) findViewById(R.id.timeView);
        timeUpView = (TextView) findViewById(R.id.timeUpView);
        //
        addTimeEdit = (EditText) findViewById(R.id.addTimeEdit);
        subtractTimeEdit = (EditText) findViewById(R.id.subtractTimeEdit);
        // Назначаем слушатель для кнопок
        startBtn.setOnClickListener(this);
        addTimeBtn.setOnClickListener(this);
        subtractTimeBtn.setOnClickListener(this);
        //
        addTimeEdit.setText("0");
        subtractTimeEdit.setText("0");
        //
        setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 
        calendar = Calendar.getInstance();
        preTime = calendar.getTimeInMillis();
        calendar.add(Calendar.MINUTE, 5);
        postTime = calendar.getTimeInMillis();
        delay = postTime - preTime;
        manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        manager.set(AlarmManager.RTC_WAKEUP, postTime, null);
 
 
    }
 
    @Override
    public void onClick(View view) {
        if (view == startBtn) {
            timerIsStarted = !timerIsStarted;
            startTimer(timerIsStarted);
            startBtn.setVisibility(View.VISIBLE);
            addTimeBtn.setVisibility(View.VISIBLE);
            subtractTimeBtn.setVisibility(View.VISIBLE);
            addTimeEdit.setVisibility(View.VISIBLE);
            subtractTimeEdit.setVisibility(View.VISIBLE);
        }
        else if (view == addTimeBtn) {
            timerIsStarted = !timerIsStarted;
            addTime(timerIsStarted);
        }
        else if (view == subtractTimeBtn) {
            timerIsStarted = !timerIsStarted;
            subtractTime(timerIsStarted);
        }
    }
 
    @TargetApi(Build.VERSION_CODES.N)
    private void startTimer(boolean started) {
        if (started) {
            CountDownTimer timer = new CountDownTimer(delay, 1) {
                @Override
                public void onTick(long millisUntilFinished) {
                    final int seconds = (int)(millisUntilFinished / 1000) % 60;
                    final int minutes = (int)(millisUntilFinished / (1000 * 60)) % 60;
                    final int hours = (int)(millisUntilFinished / (1000 * 3600)) % 60;
 
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            timeView.setText(String.format("%02d:%02d:%02d", hours,
                                    minutes, seconds));
                        }
                    });
                }
 
                @Override
                public void onFinish() {
 
                }
            };
            timer.start();
        }
        //timer = new Timer();
        //timer.schedule(new TimerTask() {
        // @Override
        //public void run() {
        //h.sendEmptyMessage(1);
        // нюанс: таймер запускается в отдельном потоке
        // из него нет доступа к элементам интерфейса, в т.ч. к TextView
        // поэтому используем класс Handler, посылая в него сообщение, в данном случае "1",
        // цифра с потолка, можно любую
        // }
        //}, 0, 1000);
 
        else {
            if (timer != null) {
                try {
                    timer.cancel();
                }
                catch (Exception e) {
                }
            }
        }
    }
 
    private void addTime (boolean started) {
        if (started) {
            timerUp = new Timer();
            timerUp.schedule(new TimerTask() {
                @Override
                public void run() {
                    h.sendEmptyMessage(2);
                }
            }, 0, 1000);
        }
        else {
            if (timer != null) {
                try {
                    timer.cancel();
                }
                catch (Exception e) {
                }
            }//end if
        }
    }//end addTime()
 
    private void subtractTime (boolean started) {
        if (started) {
 
            h.sendEmptyMessage(3);
 
        }
        else {
            if (timer != null) {
                try {
                    timer.cancel();
                }
                catch (Exception e) {
                }
            }
        }
    }
    //Полагаю, что здесь реализовано неверно. При нажатии кнопки "+" или "-"
    //возникает откровенная дичь. Все не то, что не работает, но и ломает основный таймер в timeView.
    //В java-коде там, где был swing.timer, находился обработчик события TimerTick, куда можно было занести
    //countdown--. А арифметические операции были вынесены в отдельный обработчик соответствующих кнопок.
    Handler h = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                //case 1: // если получили сообщение с нашей цифрой (сообщения могут быть из разных источников)
                    //countdown--;
                    //timeView.setText(String.format("%02d:%02d:%02d", countdown/3600,
                            //countdown/60%60, countdown%60)); // из Handler есть доступ к TextView
                    //break;
                case 2:
                    countup++;
                    timeUpView.setText(String.format("%02d:%02d:%02d", countup/3600,
                            countup/60%60, countup%60));
                    int addcountdown = Integer.parseInt(addTimeEdit.getText().toString());
                    delay += 60 * addcountdown;
                    //countup = 0;
                case 3:
                    int subtractcountdown = Integer.parseInt(subtractTimeEdit.getText().toString());
                    countdown -= 60 * subtractcountdown;
 
            }
        };
    };
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.08.2016, 17:51     Таймер, AlarmManager и Service на Android
Посмотрите здесь:

Таймер для Android Android
Android Android и Web Service
AlarmManager Android
Android AlarmManager после перезагрузки
Android AlarmManager + Notification
Не работает AlarmManager Android
Android AlarmManager
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
vxg
Модератор
 Аватар для vxg
2739 / 1750 / 174
Регистрация: 13.01.2012
Сообщений: 6,544
13.08.2016, 06:50     Таймер, AlarmManager и Service на Android #2
msgusa, почему плюс должен так странно работать?
msgusa
5 / 5 / 3
Регистрация: 29.06.2011
Сообщений: 115
13.08.2016, 08:29  [ТС]     Таймер, AlarmManager и Service на Android #3
почему плюс должен так странно работать?
Чтобы узнать, когда нажимали эту кнопку в последний раз.
vxg
Модератор
 Аватар для vxg
2739 / 1750 / 174
Регистрация: 13.01.2012
Сообщений: 6,544
13.08.2016, 09:56     Таймер, AlarmManager и Service на Android #4
msgusa, почему для этого просто не запомнить время нажатия?
msgusa
5 / 5 / 3
Регистрация: 29.06.2011
Сообщений: 115
13.08.2016, 10:07  [ТС]     Таймер, AlarmManager и Service на Android #5
почему для этого просто не запомнить время нажатия?
А это как? Запомнить эту цифру и показывать в TextView? И она не будет обновляться, т.е. тикать?
И тогда, чтобы узнать сколько времени прошло, надо в уме производить вычисления, т.е. прикидывать сколько прошло времени и отталкиваться от той сохраненной цифры? Ну, это не очень удобно.
vxg
Модератор
 Аватар для vxg
2739 / 1750 / 174
Регистрация: 13.01.2012
Сообщений: 6,544
14.08.2016, 10:12     Таймер, AlarmManager и Service на Android #6
msgusa, какой в этом физический смысл? Показывать время с прошлого нажатия именно увеличения времени?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.08.2016, 09:31     Таймер, AlarmManager и Service на Android
Еще ссылки по теме:

Android AlarmManager и Service or Receiver?
Android Service, работающий даже после выключения пользователем приложения Android
Android AlarmManager и TextView
Android Studio таймер, картинка, как? Android
Неубиваемый Service Android Android

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
msgusa
5 / 5 / 3
Регистрация: 29.06.2011
Сообщений: 115
15.08.2016, 09:31  [ТС]     Таймер, AlarmManager и Service на Android #7
какой в этом физический смысл? Показывать время с прошлого нажатия именно увеличения времени?
Да, именно так. Чтобы показывать время с прошлого нажатия кнопки увеличения времени. Например, есть аукцион. Идет время - до конца закрытия осталось - 5 мин. Тут появился желающий поднять ставку. Нажимаем "+". Добавляется время и обнуляется неосновной счетчик, время которого можно будет в дальнейшем уже сохранить.

Добавлено через 22 часа 35 минут
Что мне делать, не подскажете?
Пытался вывести обработчик добавления отдельно, т.е. добавлял слушателя что-то вроде этого:

Java
1
2
3
4
5
6
7
8
9
View.OnClickListener addTimeBtnListener = new View.OnClickListener() {
        @Override
        public void onClick (View v) {
            int addcountdown = Integer.parseInt(addTimeEdit.getText().toString());
            countup = 0;
            writeTime(addcountdown);
            startTimer(timerIsStarted);
        }
    };
Во writeTimer'е у меня как раз создается календарь и будильник. Хотя, наверное, это неправильно, так как будильник заново пересоздается. А нужно всего лишь добавить к нему другое время. Но даже так, после добавления секунды с CountDownTimer'а начинают вести себя неадекватно. Я не знаю почему.
Yandex
Объявления
15.08.2016, 09:31     Таймер, AlarmManager и Service на Android
Ответ Создать тему
Опции темы

Текущее время: 10:32. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru