본문 바로가기
개발/Android

[Android] 앱이 종료되더라도 작업을 진행해야 하는 경우, WorkManager, BroadcastReceiver, ForegroundService 사용 후기

by 준그래머 2023. 12. 14.
반응형

이번 게시물에서

DB에 데이터 저장과 같은 앱이 종료되더라도 작업을 보장해야 하는 경우가 있는데, 이 작업을 위해 각 각 WorkManager, BroadcastReceiver, ForegroundService를 구현해 보고 어떤 결과가 있는지 확인해보려 한다.

 

내가 해볼 것:

  1. 메시지 앱의 메시지 리스트 화면으로 이동
  2. 첨부 또는 메시지를 입력
  3. Overview(Recent) 버튼 클릭
  4. 스와이프로 앱 종료
  5. 앱을 다시 실행

 

결과 확인:

  1. 임시보관함에 데이터가 잘 저장됐는지 얼마나 걸리는지 확인

 

WorkManager, BroadcastReceiver, ForegroundService를 1부터 5까지 경로를 진행해 보고 결과를 확인해 볼 예정이다.

 

WorkManager를 이용하기

먼저 WorkManager를 이용해 보자. WorkManager에 대해 간단히 설명해 보자면 앱이 종료되거나 심지어 디바이스가 종료되더라도 작업을 보장해 주는 엄청난 API다.

DB에 데이터를 저장하고 업데이트하는 것까지 대략 25초 정도 걸렸다.

 

로그를 살펴보면

12-14 10:59:15.000 D 13572 13625 CtbMms : doWork
12-14 10:59:27.471 I 1085 1150 ActivityTaskManager: Activity reported stop, but no longer stopping: ActivityRecord{... ComposeMessageActivity t603 f}} DESTROYING
12-14 10:59:28.523 I 1085 4660 ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=...ConversationListActivity bnds=[291,1506][540,1689]} from uid 10096
12-14 10:59:57.422 D 13738 13824 CtbMms : SaveDraftWorker -> doWork
12-14 10:59:57.855 D 13738 13738 CtbMms : ConversationListActivity -> onReceive

처음 앱이 종료되면서 doWork를 10시 59분 15초에 요청한다. 액티비티가 파괴되는 시간은 12초 후인 27초다.

 

문제는 다시 앱을 실행하고 대화 리스트가 실행되는 시간은 28초인데, 저장 작업을 실행하고 업데이트 한 시간은 57초로 29초나 걸렸다. 이걸 보면 알 수 있듯이 WorkManager는 작업을 보장해 주는 거지 작업 시간을 보장해 주지는 않는 것 같다. 그리고 작업은 앱이 종료되면 보류하고 있다가 앱이 다시 실행되면 그때 메모리 우선 순위에 따라 작업을 처리하는 것으로 보인다.

 

그렇다면 WorkManager로는 즉시 작업을 처리해주지 못하는 것인가? 하면 StackOverFlow에 따르면 Foreground로 처리해 주면 된다고 한다. 근데, 직접 해보니 똑같이 문제가 발생해 내가 잘못하고 있는 건지 잘 모르겠다… (오히려 채널의 중요도 높여주면 앱 위로 알림 떠서 더 신경 쓰임) (예제) (참고)

 

BroadcastReceiver 이용하기

이번에는 액티비티가 종료될 때, BroadcastReceiver로 저장할 데이터와 액션을 날려 처리해 보았다.

영상을 자세히 보면 임시보관함에 저장할 때까지 액티비티가 잠깐 멈춰 있는 현상이 발생하는 것을 볼 수 있다. 또 액티비티 종료 후 바로 다시 시작할 때 잠깐 메시지 리스트 화면이 보이는 현상이 발생한다.

 

로그를 살펴보면

12-14 13:46:14.240 D 21903 21903 CtbMms : SaveDraftReceiver -> onReceive: action=com.ctb.mms.action.savedraft
12-14 13:46:15.180 I 1085 5570 ActivityTaskManager: Activity reported stop, but no longer stopping: ActivityRecord{6797ed4 u0 ...ComposeMessageActivity t630 f}} DESTROYING

1시 46분 14초에 액션을 받아 데이터를 입시 저장하고 약 1초 후 액티비티가 종료된 것을 확인할 수 있다. 이 로그를 토대로 임시 저장 시 1초 정도 멈춘 뒤 화면을 빠져나가거나 액티비티를 날리고 1초 안에 앱을 다시 시작하면 잠깐 액티비티가 보일 수 있다는 것이다.

 

좋은 방법은 아닌 것 같다.

 

ForegroundService 이용하기

마찬가지로 앱이 종료될 때, ForegroundService로 처리해 보았다.

테스트해 보니 이게 가장 무난한 것 같다. 앱이 종료되면서 포그라운드 서비스를 실행하고 데이터가 저장되는 모습이 보이는데, 포그라운드 특성상 알림이 살짝 뜨고 지워지는 건 어떻게 할 수 없을 것 같다. 그래도 유저가 불편해할 정도는 아닌 것 같아 이 방법으로 수정하는 것이 가장 좋아 보인다.

 

로그를 살펴보면

12-14 16:01:27.413 I 1085 5572 ActivityTaskManager: Activity reported stop, but no longer stopping: ActivityRecord{b571eb4 u0 ...ComposeMessageActivity t720 f}} DESTROYING
12-14 16:01:27.636 D 7173 7173 CtbMms : SaveDraftService -> onStartCommand: onPostExecute result=true

액티비티가 종료되고 나서 서비스가 시작되었고 저장까지 0.2초 정도 걸린 것으로 보인다.

 

결론

Android 12 기준 ForegroundService가 가장 괜찮은 것 같다.

반응형