код, определяющий «таймер» (Handler и Runnable):
Код: Выделить всё
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
@Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
seconds = (millis / 1000) + PrefUtil.getTimerSecondsPassed();
timerHandler.postDelayed(this, 500);
}
};
Код: Выделить всё
@Override
public void onPause() {
super.onPause();
if (timerState == TimerState.Running) {
timerHandler.removeCallbacks(timerRunnable);
//TODO: start background timer, show notification
}
PrefUtil.setTimerSecondsPassed(seconds);
PrefUtil.setTimerState(timerState);
}
Изменить
Я' Мне удалось создать службу переднего плана, которая запускает мой таймер, но у меня есть две проблемы:
- Когда я запускаю приложение примерно через 5 минут, уведомление появляется с задержкой в 10 секунд.
- уведомление перестает обновляться примерно через 30 секунд с момента запуска/возобновления (таймер продолжает работать в фоновом режиме, но уведомление не работает). не буду продолжать обновляться по таймеру).
Код: Выделить всё
public class TimerService extends Service {
Long startTime = 0L, seconds = 0L;
boolean notificationJustStarted = true;
Handler timerHandler = new Handler();
Runnable timerRunnable;
NotificationCompat.Builder timerNotificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
public static final String TIMER_BROADCAST_ID = "TimerBroadcast";
Intent timerBroadcastIntent = new Intent(TIMER_BROADCAST_ID);
@Override
public void onCreate() {
Log.d(TAG, "onCreate: started service");
startForeground(1, new NotificationCompat.Builder(this, CHANNEL_ID).setSmallIcon(R.drawable.timer).setContentTitle("Goal In Progress").build());
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String goalName = intent.getStringExtra(PublicMethods.getAppContext().getString(R.string.timer_notification_service_current_goal_extra_name));
startTime = System.currentTimeMillis();
notificationJustStarted = true;
timerRunnable = new Runnable() {
@Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
seconds = (millis / 1000) + PrefUtil.getTimerSecondsPassed();
updateNotification(goalName, seconds);
timerHandler.postDelayed(this, 500);
}
};
timerHandler.postDelayed(timerRunnable, 0);
return START_STICKY;
}
public void updateNotification(String goalName, Long seconds) {
try {
if (notificationJustStarted) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
timerNotificationBuilder.setContentTitle("Goal In Progress")
.setOngoing(true)
.setSmallIcon(R.drawable.timer)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_MAX);
notificationJustStarted = false;
}
timerNotificationBuilder.setContentText(goalName + " is in progress\nthis session's length: " + seconds);
startForeground(1, timerNotificationBuilder.build());
} catch (Exception e) {
Log.d(TAG, "updateNotification: Couldn't display a notification, due to:");
e.printStackTrace();
}
}
@Override
public void onDestroy() {
timerHandler.removeCallbacks(timerRunnable);
PrefUtil.setTimerSecondsPassed(seconds);
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Код: Выделить всё
private void startTimerService() {
Intent serviceIntent = new Intent(getContext(), TimerService.class);
serviceIntent.putExtra(getString(R.string.timer_notification_service_current_goal_extra_name), "*Current Goal Name Here*");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Objects.requireNonNull(getContext()).startForegroundService(serviceIntent);
}
}
Когда я запускаю приложение на эмуляторе пикселей Google, я не сталкиваюсь ни с одной из перечисленных проблем.
Подробнее здесь: https://stackoverflow.com/questions/717 ... d-for-30-s