firebase_messaging 백그라운드 작업 통제 android, part 1

flunge·2021년 12월 30일
0

시계는 와치

목록 보기
3/5

앱의 중요 기능 중 하나인 알람은 서버에서 fcm메시지를 수신 받으면 사용자가 미션을 완수할 때 까지 알람이 꺼지지 않고 반복해야한다.
백그라운드 처리
노티피케이션을 통한 화면 이동
이 두가지를 적절히 조합하면 쉽게 될 줄 알았다.

계획

처음 생각한 방법은 NotificationController라는 싱글톤 객체를 만들어 앱 전체에서 상태를 공유할 수 있게 하는 것이다.

Future<void> onBackgroundHandler(RemoteMessage message) async {
  NotificationController nc = NotificationController();
  
  Timer.periodic(const Duration(seconds: 5), (timer) async{
    nc.showNotification();
    if(nc.isSelected) timer.cancel();
  });

  return Future.value();
}

설명하자면 fcm메시지를 수신받으면 onBackgroundHandler가 호출되는데 그 안에서 Timer를 통해 원하는 로직을 반복하고 미션을 완수하면 NotificationController의 isSelected를 true로 바꿀 생각이었다.

결과

미션 페이지가 없기 때문에 notification을 클릭 했을 시 true로 바꾸게 설정했는데 결과가 처참한게

이런 식으로 화면 이동까지 했는데 notification은 계속 나타난다. 그 말은 Timer가 계속 돌고 있고 if문안의 조건이 충족되지 않는다는 뜻이다.

원인

이유를 아무리 생각해도 모르겠어서 이것저것 시도해 봤다.
1. Timer형의 전역 변수를 생성해 핸들러 안에서 생성되는 타이머 변수에 대입해서 앱 내에서 timer.cancel을 호출한다.
2. SharedPreference나 Hive같은 로컬 db를 이용해 값 저장 후 반복 루프 안에서 검사한다.

그러던 중 디버그 콘솔에 찍힌 로그가 눈에 띄었는데

핸들러를 실행하는 Isolate를 따로 실행한다는걸 알게 되었다.


개발자가 작성한 백그라운드 로직이 실행되는 과정을 간단하게 설명하자면
1. 앱의 상위 레벨에서 메시지를 수신했을 때 실행해야 하는 Dart코드를 등록을하면
2. MethodChannel을 통해 Native에서 핸들러 메소드를 수신받는다.
3. Native영역에서 FlutterEngine객체를 만들고 전달 받은 Dart 코드를 넘겨주고
4. 생성된 FlutterEngine객체가 로직을 실행한다.

이어서 계속

사실 이런 패키지가 native코드로 작성된 걸 MethodChannel을 통해 flutter단에서 사용하는 걸 알고는 있었는데 백그라운드 핸들러가 Dart코드로 어떻게 가능한지 의문이긴 했었다.

0개의 댓글