반응형

ㅎㅇ

 

앱을 개발하다보면 보이는 onDestroy, onStop과 같은 override 함수들을 쓰다보면 성에 안차는 경우가 많음
그냥 이 Activity나 Fragment가 종료될 때 내가 원하는 뭐 초기화 코드들이 동작했으면 좋겠는데
debugg모드에서는 안됨.

그러다보니까 최근 회사에서  앱의 보안 issue중에서 회원가입을 위해 firebase의 전화번호 인증 이후에 앱을 다시 키면 token이 남아있어 계정이 없는데 로그인이 되버리는 아이러니한 상황도 있었음

여기서 앱이 종료되거나 해당 Activity나 Fragment가 종료될 때, 이 FirebaseAuth.getInstance()의 토큰이나 SignOut()같은 메소드를 실행해주게끔 돼 있었는데 동작을 안해버리는 것.


따지고 보면 이 Activity나 Fragment가 "파괴" 되면 동작이 되는건데 뭐 디버깅모드는 그 범위 밖으로 이해했음.
그래서 아무튼 결과적으로

ViewModel의 동작을 보다보면 이게 Activity위에서만 값이 보존, 공유가 되는걸로 이해되는데, 그러다보면 Singleton을 사용하게 되고, 싱글턴을 사용하다보면 Application단위에도 접근을 하게 됨

우리는 이 Application단위에서 디버깅이든, 뒤로가기 무한 클릭, 작업목록창에서 모두 닫기 버튼 이든 전부 감지해서 앱이 종료되는 것을 감지하는 로직을 구현할 수 있음
바로 켜진 Activity갯수를 세는건데 ㅋㅋ

 

Application 클래스를 만들어주고 

class MyApplication : Application() {

전역변수로

private var startedActivities  = 0
private var isAppInBackground = false


두개를 놔두는 거임 ( 백그라운드로 가고 앱이 종료되지는 않았는지에 대한 flag 변수 )

 

그리고 startedActivities에 대해 실행되는 액티비티 갯수를 세서
0이 되고 false가 되면 앱이 종료되는 걸 감지하는 것.

Application단위에만 있는 registerActivityLifecycleCallbacks 은

  • override fun onActivityCreated
  • onActivityStarted
  •  onActivityResumed
  • onActivityPaused
  • onActivityStopped
  • onActivitySaveInstanceState 
  • onActivityDestroyed


가 있는데

그냥 조금만 기능구현해본사람이라면 다 알법한 익숙한 영단어들..
created, started, resumed, paused, stopped, destroyed 임.
다른건, activity가 아니라 앱 단위라는 것.

아무튼 이렇게 해서 로그를 찍어보면

class MyApplication : Application() {
    private var startedActivities  = 0
    private var isAppInBackground = false
    
    
    override fun onCreate() {
        super.onCreate()

        // activity들의 시작, 종료 갯수를 카운트해서 앱이 종료되는 시점 가져오기
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
            override fun onActivityStarted(activity: Activity) {
                startedActivities++
                Log.v("액티비티on", "현재 액티비티 갯수: $startedActivities")
                if (isAppInBackground) {
                    isAppInBackground = false
                    // 앱이 포그라운드로 돌아왔을 때의 로직
                }
            }
            override fun onActivityResumed(activity: Activity) {}
            override fun onActivityPaused(activity: Activity) {}
            override fun onActivityStopped(activity: Activity) {
                startedActivities--
                Log.v("액티비티off", "현재 액티비티 갯수: $startedActivities")
                if (startedActivities == 0) {
                    isAppInBackground = true
                    Log.v("액비티비 백그라운드", "현재 백그라운드인가요: $isAppInBackground")
                    // 앱이 백그라운드로 갔을 때
                }
            }
            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
            override fun onActivityDestroyed(activity: Activity) {
                if (startedActivities == 0 && isAppInBackground) {
                    Log.v("액티비티off", "현재 액티비티 갯수: $startedActivities 종료?")
                    // 앱이 완전히 종료되는 시점
                    clearDir()
                }
            }
        })
    }
    
    private fun clearDir() {
        ... 내가 앱 종료될 때 실행하고 싶은 로직 ...
    }
}
액티비티on                  com.example.finish                 V  현재 액티비티 갯수: 2
액티비티off                 com.example.finish                 V  현재 액티비티 갯수: 1
액티비티off                 com.example.finish                 V  현재 액티비티 갯수: 0
액비티비 백그라운드              com.example.finish                 V  현재 백그라운드인가요: false

앱 종료감지 log

꺼질 때이렇게 나오기도 하며

잘 동작하는 모습. 

ㅅㄱ

반응형