Форум программистов, компьютерный форум, киберфорум
Программирование Android
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 183

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

12.08.2016, 17:51. Показов 3274. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер.
Я уже создавал тем(ы) про таймер. И мне очень здорово помогли разобраться с Андроидом, особенно 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;
 
            }
        };
    };
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.08.2016, 17:51
Ответы с готовыми решениями:

AlarmManager и Service or Receiver?
Целый день искал, но нифига не нашел( то что нашел помогло тоолько частично). Суть вот в чем, у меня есть AlarmManeger как уже всем и так...

Alarmmanager +Service пропуск запусков
Каждые 20 сек. запускается сервис с помощью AlarmManager . На одном смартфоне работает абсолютно идеально а на втором запусков servike...

Неубиваемый Service Android
Добрый день. В общем хочу написать приложение, которое мониторит заряд батареи и в случае определенного уровня заряда, присылает...

6
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,450
13.08.2016, 06:50
msgusa, почему плюс должен так странно работать?
0
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 183
13.08.2016, 08:29  [ТС]
почему плюс должен так странно работать?
Чтобы узнать, когда нажимали эту кнопку в последний раз.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,450
13.08.2016, 09:56
msgusa, почему для этого просто не запомнить время нажатия?
0
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 183
13.08.2016, 10:07  [ТС]
почему для этого просто не запомнить время нажатия?
А это как? Запомнить эту цифру и показывать в TextView? И она не будет обновляться, т.е. тикать?
И тогда, чтобы узнать сколько времени прошло, надо в уме производить вычисления, т.е. прикидывать сколько прошло времени и отталкиваться от той сохраненной цифры? Ну, это не очень удобно.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,450
14.08.2016, 10:12
msgusa, какой в этом физический смысл? Показывать время с прошлого нажатия именно увеличения времени?
0
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 183
15.08.2016, 09:31  [ТС]
какой в этом физический смысл? Показывать время с прошлого нажатия именно увеличения времени?
Да, именно так. Чтобы показывать время с прошлого нажатия кнопки увеличения времени. Например, есть аукцион. Идет время - до конца закрытия осталось - 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'а начинают вести себя неадекватно. Я не знаю почему.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.08.2016, 09:31
Помогаю со студенческими работами здесь

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

Android Service, работающий даже после выключения пользователем приложения
Столкнулся со следующей проблемой: нужно чтобы Service работал даже после выключения пользователем приложения. имеется public class...

Таймер Android
Всем привет. У меня вот такая проблема, что криво работают пауза и возобновление. При нажатии на паузу таймер как бы приостанавливается, но...

Таймер для Android
есть функция которую необходимо вызывать через каждые 60 сек, пока приложение находится в фокусе как узнать что приложение в фокусе?...

Таймер Android Studio
Не могу сделать кнопку возобновления. Помогите пожалуйста. package app.coundowntimer; import android.os.CountDownTimer; import...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru