본문 바로가기

안드로이드

안드로이드 태스크 ( Android Tasks)

반응형

태스크란? (What is Task?)

 태스크는 액티비티 작업 묶음 단위라고 보면 됩니다. 앱과 태스크는 1:1 대응이 아닙니다. 여러 개의 앱이 하나의 태스크가 될 수도 있고, 필요하면 하나의 앱에서도 태스크를 여러개 가질 수 있습니다.

 A task is a collection of activities that users interact with when tying to do something in your app. Mutliple apps can be one task, and one app can have multiple tasks if necessary.

백스택 (Back Stack)

 액티비티는 백 스택(back stack)이라 불리는 스택에 차례대로 쌓인다. Intent.FLAG_ACTIVITY_REORDER_TO_FRONT 플래그를 사용하면 순서를 조정할 수 있다.

 Activitys are stacked in order on Back Stack. You can adjust the order using Intent flags like Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.

태스크 상태 (Task Status)

포그라운드에서  백그라운드로 (From Foreground  To Background)

 moveTaskToBack(boolean nonRoot) 메서드를 사용해 가능하다. 이 메서드를 사용할 일은 많지 않은데 반드시 필요할 때가 있다. 비밀번호 잠금을 이용할 때이다. 패스워드 액티비티가 떴을 때 백키를 눌러도 원래 액티비티가 보이지 않게 설정해야한다. 결론적으로 패스워드 액티비티에서 onBackPressed() 메서드를 오버라이드해서 moveTaskToBack(true)를 호출하면 된다.

 You can it using methods that called moveTaskToBack(boolean nonRoot).  You will rarely use this method, but there are times when it is necessary. You will use it when developing a ppasword lock application. In conclusion, you can override the onBackPressed() in the password Activity and call moveTaskToBack(true).

백그라운드에서 포그라운드 태스크로 이동 (From Background To Froground)

반대로 백그라운드에서 포그라운드로 상태를 변경하는 메서드는 ActivityManager에서 moveTaskToFront(int taskId, int flags) 메서드를 사용하면 된다. 이 메서드는 허니콤부터 사용 가능하고 android.permission.REORDER_TASKS 퍼미션이 필요하다.

dumpsys 명령어로 포커스된 액티비티 찾기

adb shell dumpsys activity a | grep mFocusedActivity

taskAffinity 속성

 태스크가 시작되면 어느 TaskRecord의 어느 ActivityRecord에 소속되는데 이 소속되는 기준 가운데 한가지가 바로 taskAffinity 문자열 속성이다. taskAffinity 속성은 액티비티가 '관련된' 태스크에 들어갈 때 참고하는 값이라고 보면된다. android:taskAffinity를 지정하지 않으면 앱의 패키지명이 액티비티의 taskAffinity 속성 값이되며, 태스크를 시작한 액티비티의 taskAffinity 속성을 따라간다.

 FLAG_ACTIVITY_NEW_TASK 플래그는 의미상으로 새로운 태스크를 생성하는 것으로 이해하기 쉽다. 하지만 taskAffinity에 따라서 결과가 달라진다. taskAffinity와 동일한 게 있다면 그 태스크에 액티비티가 포함되고 그렇지 않으면 새로운 태스크가 시작된다.

 android:taskAffinity 로 지정하지 않는다면 디폴트 값은 패키지명이다. android:taskAffinity 속성을 선언하지 않은 것끼리는 FALG_ACTIVITY_NEW_TASK 속성을 쓰더라도 같은 태스크에 있게 된다. 별도로 속성을 줄 때는 android:taskAffinity에 ':alarm' 과 같이 콜론(:) 뒤에 구분자를 적는 것이 권장된다. 'alarm'과 같이 단순한 이름을 쓰는 것은 허용되지 않는다.

 알람앱을 예를 들어보자. 알람 리스트 화면 (AlarmClock), 알람 설정 화면(AlarmSettings), 알람 화면 (AlarmAlert)과 같이 3개의 액티비티가 있다. taskAffinity 속성이 없다면, 알람이 뜨는 순간에 알람 앱의 태스크가 포그라운드나 백그라운드에 이미 있을 수 있다. 포그라운드에 이미 있었다면 AlarmAlert 화면이 그 위에 추가되어서 포커스될 것이고, 백그라운드에 있다면 태스크가 포그라운드되면서 그 위에 AlarmAlert화면이 뜰 것이다. 백그라운드에 있던 화면이 딸려 올라와서 상요자 입장에서는 화면의 흐름이 어색하게 느낄 수 있다. 이런 케이스를 막기 위해 AlarmAlert의 android:taskAffinity 속성을 별도로 지정하고 Intent에 FLAG_ACTIVITY_NEW_TASK 플래그를 포함해보자. 그러면 AlramAlert가 새로운 태스크로 뜨게 되고 배경에 다른 화면이 딸려올라올 일이 없다.

AlermAlert 화면이 최근 앱 목록에 보이는 것을 방지하기 위해 AndroidManifest.xml 의 AlarmAlert 선언에 android:excludeFromRecents 속성을 true로 하면 알람기능의 기본 형태를 갖추게 된다.

anroid:launchMode

standard

기본 값이다. 태스크의 topActivity에 매번 새로운 액티비티 인스턴스를 생성해 Intent를 전달한다.

SingleTop

이미 topActivity에 있다면 새로 생성하지 않고 onNEwIntent() 메서드로 Intent를 전달한다.

singleTask

태스크에 인스턴트는 1개 이다. taskAffinity 값을 참고해서 들어가게 되는 태스크가 존재하고 여기에 동일한 액티비티의 인스턴스가 이미 있다면 새로 생성하지 않고, onNewIntent() 메서드로 Intent를 전달한다.

 예를들어, ActivityB를 singleTask로 정하고, ActivityA > ActivityB > ActivityC > ActivityB를 호출해보자. 결과적으로 [ActivityA, AcitivityB]로 남는다. B가 올라갈 때 C가 스택에서 제거되면서 onNewIntent가 불린다. 

 이번에는 ActivityB의 taskAffinity를 변경하고 테스트해보자. A > B > C -> [A],[B,C] 로 두개의 태스크가 남는다. B의 taskAffinity가 없으니 새로 만들어진 것이다. A > B > C > B -> [A],[B] 와 같이 두개의 태스크로 남는다.

 별도의 태스크가 될 때는 딜레이가 있다. 따라서 태스크가 되어야 하는 케이스와 그렇지 않아야하는 케이스를 구분하는 것이 성능에 좋다.

singleInstance

 singleTask와 마찬가지로 태스크에 해당하는 액티비티 인스턴스가 1개뿐이며 태스크의 유일한 액티비티다. 

 Activity B의 launchMode가 singleInstance라고 해보자. A > B > C -> [B],[A,C] 로 묶인다. 따라서 C에서 백키를 누르면 B가 아닌 A로 간다.  최근 앱 목록도 taskAffinity 기준이다.

Intent 플래그

FLAG_ACTIVITY_SINGLE_TOP

singleTop launchMode 와 동일한 효과를 갖음

FLAG_ACTIVITY_NEW_TASK

singleTask launchMode와 동일한 효과를 갖는다.

FLAG_ACTIVITY_CLEAR_TOP

스택에서 피호출자보다 위에 있는 액티비티를 종료한다. 만일 [A, B, A, B]가 스택에 있을때 B에서 FLAG_ACTIVITY_CLEAR_TOP을 이용해서 A를 시작한다면? [A, B, A] 가 스택에 남는다. 해결하고 싶으면 <activity-alias>를 활용하면 된다.

FLAG_ACTIVITY_CLEAR_TASK

 피호출자가 시작되기 전 관려노딘 스택이 모두 제거되고, 피 호출자는 빈 태스크의 baseActivity가 된다. 이 플래그는 FLAG_ACTIVITY_NEW_TASK와 함께 사용된다.

FLAGE_ACTIVITY_REORDER_TO_FRONT

 스택에 동일한 액티비티가 이미 있으면 그 액티비티를 스택의 맨 위로 ㅇ로린다. 해당 액티비티가 스택의 맨 위에 1개만 있어야 하는 경우에 쓸 수 있다.
 1) FLAG_ACTIVITY_CLEAR_TOP 플래그와 함께 사용하면 옵션이 무시된다.
 2) 호출자가 액티비티일 때만 정상적으로 재배치(reorder)가 동작한다.

 

참고자료 : 안드로이드 프로그래밍 NextStep (노재춘 지음)

반응형