С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

Программирование Android

Войти
Регистрация
Восстановить пароль
 
msgusa
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 164
#1

Таймер, AlarmManager и Service на Android - Программирование Android

12.08.2016, 17:51. Просмотров 482. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.08.2016, 17:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Таймер, AlarmManager и Service на Android (Программирование Android):

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

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

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

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

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

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

6
vxg
Модератор
3188 / 1991 / 228
Регистрация: 13.01.2012
Сообщений: 7,712
13.08.2016, 06:50 #2
msgusa, почему плюс должен так странно работать?
0
msgusa
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 164
13.08.2016, 08:29  [ТС] #3
почему плюс должен так странно работать?
Чтобы узнать, когда нажимали эту кнопку в последний раз.
0
vxg
Модератор
3188 / 1991 / 228
Регистрация: 13.01.2012
Сообщений: 7,712
13.08.2016, 09:56 #4
msgusa, почему для этого просто не запомнить время нажатия?
0
msgusa
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 164
13.08.2016, 10:07  [ТС] #5
почему для этого просто не запомнить время нажатия?
А это как? Запомнить эту цифру и показывать в TextView? И она не будет обновляться, т.е. тикать?
И тогда, чтобы узнать сколько времени прошло, надо в уме производить вычисления, т.е. прикидывать сколько прошло времени и отталкиваться от той сохраненной цифры? Ну, это не очень удобно.
0
vxg
Модератор
3188 / 1991 / 228
Регистрация: 13.01.2012
Сообщений: 7,712
14.08.2016, 10:12 #6
msgusa, какой в этом физический смысл? Показывать время с прошлого нажатия именно увеличения времени?
0
msgusa
6 / 6 / 3
Регистрация: 29.06.2011
Сообщений: 164
15.08.2016, 09:31  [ТС] #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'а начинают вести себя неадекватно. Я не знаю почему.
0
15.08.2016, 09:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.08.2016, 09:31
Привет! Вот еще темы с ответами:

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

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

Android Studio таймер, картинка, как? - Программирование Android
Добрый день. 1) Как сделать так что бы TextView менялся каждую секунду? 2) Как сделать так что бы ImageView по клику увеличивался в 1.5...

AlarmManager - Программирование Android
Добрый вечер, как задать время вручную ? alarmManager.set(AlarmManager.RTC, System.currentTimeMillis(), pendingIntent);


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.