👉 문제 원인 및 해결 방안
- 문제 1 : 타이머 실행 중 화면이 꺼지면 알림이 울리지 않음
- 백그라운드 실행을 적용 해야 정상적으로 작동
- ⇒ 백그라운드로 실행하기 위해서는 Foreground Service를 적용 해야 함
- 문제 2 : 백그라운드 적용 후에 PAUSE와 RESTART 제대로 작동하지 않음
- 기존에는 모든 로직을 Activity에 적용했는데 Service와 Activity로 분리
- Activity의 RESTART 메서드에서 Service를 호출할 때, intervalTime을 전달해주지 않아 intervalTime이 0으로 전달됨
- 위의 이유 때문에 RESTART 시, 남은 SET들의 intervalTime이 0으로 호출되어 정상적으로 작동되지 않음
- Activity의 RESTART 메서드에서 Service를 호출할 때, currentSet에 executionSet(최초에 지정한 SET)이 대입되어 SET가 이어서 실행되지 않음
- ⇒ Activity의 RESTART 메서드에서 Service를 호출할 때, currentSet과 intervalTime 전달해야 함
👉 수정한 코드
- TimerActivity에서 onCreate 시, Service 호출
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
textViewTimer = findViewById(R.id.textViewTimer);
pauseButton = findViewById(R.id.pauseButton);
selectedOption = getIntent().getIntExtra("selectedOption", 0);
intervalTime = getIntent().getIntExtra("intervalTime", 0);
executionSet = getIntent().getIntExtra("executionSet", 0);
pauseButton.setOnClickListener(view -> {
if (isPaused) {
sendControlCommand("ACTION_RESTART");
} else {
sendControlCommand("ACTION_PAUSE");
}
});
startTimerService();
}
- TimerActivity의 sendControlCommand에서 intervalTime과 currentSet도 Service로 전달
private void sendControlCommand(String action) {
Intent serviceIntent = new Intent(this, TimerService.class);
serviceIntent.setAction(action);
serviceIntent.putExtra("currentSet", currentSet);
serviceIntent.putExtra("isPaused", isPaused);
serviceIntent.putExtra("isSendControlCommandCall", true);
serviceIntent.putExtra("intervalTime", intervalTime);
startService(serviceIntent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
intervalTime = intent.getIntExtra("intervalTime", 0);
selectedOption = intent.getIntExtra("selectedOption", 0);
boolean isSendControlCommandCall = intent.getBooleanExtra("isSendControlCommandCall", false);
if ( isSendControlCommandCall ) {
currentSet = intent.getIntExtra("currentSet", executionSet);
} else {
executionSet = intent.getIntExtra("executionSet", 0);
currentSet = executionSet;
}
startForeground(1, getNotification("타이머 실행 중"));
String action = intent.getAction();
if ("ACTION_PAUSE".equals(action)) {
pauseTimer();
} else if ("ACTION_RESTART".equals(action)) {
restartTimer();
} else {
startTimer();
}
return START_STICKY;
}
private void startTimer() {
timeLeftInMillis = intervalTime * 1000L;
Log.d("onFinish", "startTimer의 timeLeftMillis : " + timeLeftInMillis);
setupAndStartTimer();
}
private void pauseTimer() {
if (countDownTimer != null) {
countDownTimer.cancel();
isPaused = true;
broadcastTimerUpdate(timeLeftInMillis);
}
}
private void restartTimer() {
if (isPaused) {
isPaused = false;
broadcastTimerUpdate(timeLeftInMillis);
setupAndStartTimer();
}
}
private void broadcastTimerUpdate(long millisUntilFinished) {
Intent intent = new Intent(ACTION_UPDATE_BROADCAST);
intent.putExtra("timeLeftInMillis", millisUntilFinished);
intent.putExtra("currentSet", currentSet);
intent.putExtra("isPaused", isPaused);
sendBroadcast(intent);
}
private Notification getNotification(String contentText) {
Intent notificationIntent = new Intent(this, TimerActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("InTime")
.setContentText(contentText)
.setSmallIcon(R.drawable.in_logo)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
}