IT_Programming/Android_Java

Intent Action & Category

JJun ™ 2014. 5. 27. 16:33


 출처: http://blog.naver.com/smpc2958/30128684862


 : 찾았는데 빨리 안 나올 때를 대비해서 작성...

   원본은 위 출처입니다.


 



Intent Action

 

#Action 종류 

수행되어야 할 작업 내용으로 Intent Action은 Activity Action과 Broadcast Action으로 나누는데 용어가 

그런것이고 실제로는 구분이 없습니다. 인텐트 액션은 인텐트 필터와 밀접한 연관관계가 있습니다.

예로 ACTION_MAIN은 인텐트 필터에서 "android.intent.action.MAIN"으로 

그리고 ACTION_VIEW는 "android.intent.action.VIEW"로 해석됩니다.

안드로이드에서 제공하는 액션명 이외에 애플리케이션에 있는 컴포넌트를 활성화하기 위해 "com.android.sample.START"와 같이 개발자만의 액션 문자열을 정의 할 수 있다.

 

 액션상수

액션종류 

 설명 

 ACTION_AIRPLANE_MODE_CHANGED

 Broadcast 

 스마트폰을 "Airplane Mode"로 전환하는 액션

 ACTION_ALL_APPS

 Activity

 모든 애플리케이션을 리스트하라는 액션 

 ACTION_ANSWER

 Activity

 수신전화를 받는 액션

 ACTION_ATTACH_DATA

 

 특별한 데이터나 메일등에 데이터를 첨부하는 액션

 ACTION_BATTERY_CHANGED

 Broadcast

 배터리 변화를 알리는 액션

 ACTION_BATTERY_LOW

 Broadcast

 배터리가 낮은 상태임을 알리는 액션

 ACTION_BATTERY_OKAY

 Broadcast

 배터리 상태가 정상으로 회복되었음을 알리는 액션

 ACTION_BOOT_COMPLETED

 Broadcast

 부팅 완료 액션

 ACTION_BUG_REPORT

 Activity

 버그 리포트 액션

 ACTION_CALL

 Activity

 데이터에 있는 사람에게로 전화 액션

 ACTION_CALL_BUTTON

 Activity

 전화통화를 위해 통화버튼을 누른 상태 액션

 ACTION_CAMERA_BUTTON

 Broadcast

 카메라 버튼을 누른 액션

 ACTION_CHOOSER

 Activity

 액티비티를 선택하기 위한 액션

 ACTION_CLOSE_SYSTEM_DIALOGS

 Broadcast

 다이얼로그가 순간적으로 dismiss되었음을 알리는 액션

 ACTION_CONFIGURATION_CHANGED

 Broadcast

 디바이스의 설정 파일이 변경되었음을 알리는 액션

 ACTION_CREATE_SHORTCUT

 Activity

 "shortcut"이 생성되었음을 알리는 액션

 ACTION_DATE_CHANGED

 Broadcast

 데이터 변화 액션

 ACTION_DEFAULT

 

 "ACTION_VIEW"와 같음

 ACTION_DELETE

 Activity

 자료가 삭제되었음을 알리는 액션

 ACTION_DEVICE_STORAGE_LOW

 Broadcast

 시스템에서 보호용 인텐트 액션으로 디바이스의 메모리 부족을 알리는 액션

 ACTION_DEVICE_STORAGE_OK

 Broadcast

 시스템에서 알라는 액션으로 디바이스의 메모리가 정상임을 알리는 액션

 ACTION_DIAL

 

 데이터에 있는 다이얼넘버로 전화토오하 요청 액션

 ACTION_DOCK_EVENT

 Broadcast

 디바이스가 Lock또는 Unlock를 알리는 액션

 ACTION_EDIT

 Activity

 주어진 데이터의 Edit를 원하는 액션

 ACTION_FACTORY_TEST

 Activity

 생산 테스트를 위한 메인 액션

 ACTION_GET_CONTENT

 Activity

 사용자가 선택한 특별한 종류의 데이터 선택과 데이터의 리턴을 원하는 액션

 ACTION_GTALK_SERVICE_CONNECTED

 Broadcast

 GTalk 연결되었음을 알리는 액션

 ACTION_GTALK_SERVICE_DISCONNECTED

 Broadcast

 GTalk 연결이 끊어짐을 알리는 액션

 ACTION_HEADSET_PLUG

 Broadcast

 헤드셋(Wired Headset) 플러그 또는 언플러그드를 알리는 액션

 ACTION_INPUT_METHOD_CHANGED

 Broadcast

 Input방식의 변경을 알리는 액션

 ACTION_INSERT

 Activity

 저장장소에 빈 아이템이 입력됨을 알리는 액션

 ACTION_INSERT_OR_EDIT

 Activity

 존재하는 아이템을 선택하거나 새로운 아이템을 입력하고 수정하라는 액션

 ACTION_LOCALE_CHANGED

 Broadcast

 Locale이 변경됨을 알리는 액션

 ACTION_MAIN

 Activity

 메인 액티비티의 스타트 액션

 ACTION_MANAGE_PACKAGE_STORAGE

 Broadcast

 사용자에 의한 낮은 메모리를 알리는 경고 액션으로 패키지 매니저를 호출시킴

 ACTION_MEDIA_BAD_REMOVAL

 Broadcast

 SD카드로부터 미디어가 삭제되었음을 알리는 액션

 ACTION_MEDIA_BUTTON

 Broadcast

 "Media Button"이 눌려졌음을 알리는 액션

 ACTION_MEDIA_CHECKING

 Broadcast

 외장 미디어가 연결되었으며 마운트 포인트는 "Intent.mData field"있음을 알리는 액션

 ACTION_MEDIA_EJECT

 Broadcast

 외장 미디어 장치의 제거를 원하는 사용자 액션

 ACTION_MEDIA_MOUNTED

 Broadcast

 외장 미디어의 마운트됨을 알리는 액션

 ACTION_MEDIA_NOFS

 Broadcast

 외장 미디어가 부착되었으나 파일 포멧이 다르다는 것을 알리는 액션으로 마운트포인트는 "Intent.mData field"있음을 알리는 액션

 ACTION_MEDIA_REMOVED

 Broadcast

 외장 미디어가 제거됨을 알리는 액션

 ACTION_MEDIA_SCANNER_FINISHED

 Broadcast

 디렉터리에 미디어 스캔이 완료되었다는 것을 알리는 액션

 ACTION_MEDIA_SCANNER_SCAN_FILE

 Broadcast

 미디어를 스캔하고 새로운 미디어를 미디어 데이터베이스에 등록하라는 액션

 ACTION_MEDIA_SCANNER_STARTED

 Broadcast

 디렉터리에 미디어스캔을 시작한다는 액션

 ACTION_MEDIA_SHARED

 Broadcast

 USB 스토리지에 의하여 외장 미디어가 언마운트 되었음을 알리는 액션

 ACTION_MEDIA_UNMOUNTABLE

 Broadcast

 외장 미디어는 존재하나 아직 마운트 할수 없음을 알리는 액션

 ACTION_MEDIA_UNMOUNTED

 Broadcast

 외장 미디어는 존재하나 아직 마운트는 되지 않았음을 알리는 액션

 ACTION_NEW_OUTGOING_CALL

 Broadcast

 새로운 송신할 예정임을 알리는 액션

 ACTION_PACKAGE_ADDED

 Broadcast

 디바이스에 새로운 패키지가 설치되었음을 알리는 액션

 ACTION_PACKAGE_CHANGED

 Broadcast

 존재하는 패키지에 변화가 발생했다는 것을 알리는 액션

 ACTION_PACKAGE_DATA_CLEARED

 Broadcast

 사용자가 패키지의 데이터를 지웠음을 알리는 액션

 ACTION_PACKAGE_INSTALL

 Broadcast

 다운로드하고 패키지를 설치하라는 액션

 ACTION_PACKAGE_REMOVED

 Broadcast

 존재하는 패키지 삭제를 알리는 액션

 ACTION_PACKAGE_REPLACED

 Broadcast

 기존 패키지의 새로운 버전이 설치되었음을 알리는 액션

 ACTION_PACKAGE_RESTARTED

 Broadcast

 모든 프로세스를 Kill하고 새로운 패키지를 스타트하라는 액션

 ACTION_PICK

 Activity

 데이터로부터 아이템을 선택하고 선택한 아이템을 리턴시키라는 액션

 ACTION_PICK_ACTIVITY

 Activity

 액티비티를 선택하고 선택한 액티비티를 리턴시키라는 액션

 ACTION_POWER_CONNECTED

 Broadcast

 외장 파워가 부착되었음을 알리는 액션

 ACTION_POWER_DISCONNECTED

 Broadcast

 외장 파워가 디바이스에서 제거되었음을 알리는 액션

 ACTION_POWER_USAGE_SUMMARY

 Activity

 사용자에게 파워의 사용량을 보여달라는 액션

 ACTION_PROVIER_CHANGED

 Broadcast

 새로운 이벤트 또는 아이템을 컨텐트 프로바이더가 갖고 있음을 알리는 액션

 ACTION_REBOOT

 Broadcast

 디바이스가 reboot되었음을 알리는 액션

 ACTION_RUN

 Activity

 데이터를 작동시키라는 액션

 ACTION_SCREEN_OFF

 Broadcast

 화면이 꺼짐을 알리는 액션

 ACTION_SCREEN_ON

 Broadcast

 화면이 켜짐을 알리는 액션

 ACTION_SEARCH

 Activity

 검색을 요청하는 액션

 ACTION_SEARCH_LONG_PRESS

 Activity

 검색키의 누름과 함께 액션을 시작하라는 액션

 ACTION_SEND

 Activity

 해당 메시지를 누군가에게 보내라는 액션

 ACTION_SENDTO

 Activity

 데이터에 표시된 누군가에게 메시지를 보내라는 액션

 ACTION_SEND_MULTIPLE

 Activity

 누군가에게 다수의 데이터를 보내라는 액션

 ACTION_SET_WALLPAPER

 Activity

 wallpaper를 선택하고 세팅하라는 액션

 ACTION_SHUTDOWN

 Broadcast

 디바이스가 닫혀졌음을 알리는 액션

 ACTION_SYNC

 Activity

 데이터를 동기화하라는 액션

 ACTION_SYSTEM_TUTORIAL

 Activity

 플래폼에 정의된 교육자료를 시작하라는 액션. Input 정보로 아래 메소드가 필요 getStringExtra(SeachManager.QUERY)

 ACTION_TIMZONE_CHANGED

 Broadcast

 Timzone이 변경되었음을 알리는 액션

 ACTION_TIME_CHANGED

 Broadcast

 시간설정이 변경되었음을 알리는 액션

 ACTION_TIME_TICK

 Broadcast

 현재시간이 변경되었음을 알리는 액션

 ACTION_UID_REMOVED

 Broadcast

 시스템에서 사용자 ID가 제거되었음을 알리는 액션

 ACTION_UMS_CONNECTED

 Broadcast

 대용량 USB 스토리지가 연결되었음을 알리는 액션

 ACTION_UMS_DISCONNECTED

 Broadcast

 대용량 USB 스토리지가 제거되었음을 알리는 액션

 ACTION_USER_PRESENT

 Broadcast

 디바이스가 꺠어났음을 알리는 액션

 ACTION_VIEW

 Activity

 사용자에게 데이터를 보여달라는 액션

 ACTION_VOICE_COMMAND

 Activity

 보이스 명령어를 시작하라는 액션

 ACTION_WALLPAPER_CHANGED

 Broadcast

 현 시스템의 wallpaper가 변경되었음을 알리는 액션

 ACTION_WEB_SEARCH

 Activity

 웹서치를 시행하라는 액션

 

 

 

#Category 종류 

인텐트를 제어해야하는 컴퍼넌트 종류에 대한 추가적인 정보를 포함하는 문자열로 주로 선택하고자 하는 액티비티와 관련되어 있습니다. 

 

 카테고리 상수

 설명 

 CATEGORY_ALTERNATIVE

 데이터와 관련된 액티비티들을 의미

 CATEGORY_ BROWSABLE

 타겟 액티비티는 링크에 참조되는 데이터를 보여 주기 위해 브라우저에 의해 호출될 수 있음

 CATEGORY_CAR_DOCK

 카 Dock에 넣었을 때 필요한 액티비티를 의미

 CATEGORY_DEFAULT

 디폴트 카테고리

 CATEGORY_DESK_DOCK

 카 Dock에 넣었을 때 액티비티를 작동시키라는 의미로 ACTION_MAIN과 같이 사용

 CATEGORY_DEVELOPMENT_PREFERENCE

 지정한 액티비티가 개발용 패널임을 의미

 CATEGORY_EMBED

 임베디드 액티비티를 작동

 CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST

 프레임워크 테스트 목적으로 사용

 CATEGORY_HOME

 디바이스가 부팅 완료 후 처음 작동하는 액티비티

 CATEGORY_INFO

 애플리케이션 리스트에 "CATEGORY_LAUNCHER"가 아닌 패키지에 대한 정보를 공급해 달라는 의미

 CATEGORY_LAUNCHER

 호출되고 보여줄수 있는 액티비티

 CATEGORY_MONKEY

 테스트 도구(몽키-monkey)에 의해 작동하는 액티비티

 CATEGORY_OPENABLE

 GET_CONTENT액션의 인텐트로 ContentResolver.openInputstream와 함께 사용

 CATEGORY_PREFERENCE

 선호하는 패널(panel)의 액티비티

 CATEGORY_SAMPLE_CODE

 샘플코드 예제로서 사용

 CATEGORY_SELECTED_ALTERNATIVE

 사용자가 선택한 데이터에 또 다른 선택액션으로 고려되는 액티비티

 CATEGORY_TAB

 TabActivity를 갖는 Tab으로써 사용

 CATEGORY_TEST

 테스트용

 CATEGORY_UNIT_TEST

 단위 테스트로 사용

 

 

 

 

 

 

 

 

 


 

 

 

 


 

 출처: http://theeye.pe.kr/archives/1298

 


 

 

 

[Android] Activity 생성시에 사용되는 Intent Flag 정리

 

안드로이드 엑티비티에 대해 이해하기 위해 필요한 지식은 3가지 정도가 아닐까 생각합니다. 바로 Activity Lifecycle, Task, Intent 입니다. 모두 어느정도 이해를 하시고 계신 상태라고 생각하고 글을 적어보겠습니다.

 

인텐트를 이용하여 새로운 엑티비티를 띄우기 위해서는 일반적으로 다음과 같은 방법으로 새로운 엑티비티를 실행하게 됩니다.

 

 

  Intent intent = new Intent(this, MyActivity.class);
  startActivity(intent); 

 

위의 코드는 다음과 같은 순서로 실행이 됩니다.

1. 새로운 MyActivity 인스턴스가 생성됩니다.
2. 이 인스턴스가 현재 태스크 스택의 최상단에 푸시가 됩니다.
3. 엑티비티가 시작되며(onStart) 포그라운드로 가져옵니다.

 

하지만 위와 같은 인텐트 생성에 관련된 기본적인 실행 방법을 인텐트 플래그를 사용하여 임의로 조정할 수 있습니다.

 

 intent.addFlag(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 

 

위와 같은 방법을 통해 특정한 플래그 옵션값을 startActivity(intent)가 수행될때 같이 넘겨줄 수 있습니다. 지금부터 이러한 플래그 옵션값들을 좀더 상세기 적어보도록 하겠습니다.

 

 

FLAG_ACTIVITY_BROUGHT_TO_FRONT

이 플래그는 사용자가 설정하는것이 아닌 시스템에 의해 설정되는 값입니다. 엑티비티의 실행모드가 singleTask이고 이미 엑티비티스택에 존재하고 있는 상태라고 가정을 할 때 다시 그 엑티비티가 호출되고 재활용 되었을 경우 자동으로 설정이 됩니다.

 

 

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

 

이 플래그를 사용하면 태스크가 리셋될때 플래그가 사용된 엑티비티부터 최상단의 엑티비티까지 모두를 삭제합니다. 리셋은 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 플래그에 의해 실행이 되는데 시스템에 의해 홈스크린에서 사용자에 의해 백그라운드에 있던 태스크가 포그라운드로 전환될때에 항상 붙게 됩니다.

 

위의 그림에서 볼 수 있듯이 백그라운드와 포그라운드 전환관계에서 CLEAR_WHEN_TASK_RESET 플래그가 설정된 엑티비티와 이후의 엑티비티 모두가 삭제되는것을 알 수 있습니다. 백그라운드로 넘어갔을때 유지를 안해도 될 일회성 엑티비티들은 해당 플래그를 사용하면 도움이 될것이라 봅니다.

 

 

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

이 플래그는 인텐트를 이용하여 새로운 태스크를 생성하거나 존재하고 있는 태스크를 포그라운드로 가져오는 경우가 아닌경우에는 사용하여도 아무런 효과가 없습니다. 적절한 경우라면 태스크를 리셋 합니다. 이때에 태스크의 affinity 설정에 맞추어 리셋이 일어나게 되며

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET과 같은 플래그 설정에 맞추어진 특정 처리가 일어나게 됩니다.

 

 

FLAG_ACTIVITY_CLEAR_TOP

 

 

만약에 엑티비티스택에 호출하려는 엑티비티의 인스턴스가 이미 존재하고 있을 경우에 새로운 인스턴스를 생성하는 것 대신에 존재하고 있는 엑티비티를 포그라운드로 가져옵니다. 그리고 엑티비티스택의 최상단 엑티비티부터 포그라운드로 가져올 엑티비티까지의 모든 엑티비티를 삭제합니다.

예를 들면 현재 ABCDE순서로 엑티비티가 스택에 들어있다고 할때 엑티비티E에서 C를 호출하게 되면 D와 E는 스택에서 삭제되고 ABC만이 남아있게 됩니다. 여기서 AB 역시 남는다는 것을 이해하셔야 합니다.

 

 

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

엑티비티가 새로운 태스크안에서 실행될때에 일반적으로 타겟 엑티비티는 ‘최근 실행된 엑티비티’ 목록에 표시가 됩니다. (이 목록은 홈버튼을 꾹 누르고 있으면 뜹니다) 이 플래그를 사용하여 실행된 엑티비티는 최근실행된엑티비티 목록에서 나타나지 않습니다.

 

 

FLAG_ACTIVITY_FORWARD_RESULT

기본적으로 엑티비티A가 엑티비티B를 호출하였다고 할 경우 startActivity(intent) 대신에 startActivityForResult(intent) 메서드를 이용하여 호출을 함으로써 엑티비티B의 결과값을 엑티비티A로 전달할 수 있습니다.

엑티비티B에서는 setResult(int resultCode)를 정의한 뒤에 종료를 하게 되며 엑티비티B를 호출하였던 엑티비티A는 콜백메서드인 onActivityResult()를 통해 결과값을 전달받게 됩니다.

 

 

 

 

이제 엑티비티B가 또다른 엑티비티C를 호출하였다고 가정해 봅시다. 그리고 이렇게 호출된 엑티비티C에서 엑티비티A까지 전달할 결과값을 정의하였습니다. 이 결과값을 B에서 A로 또다른 코드를 통해서 프로그래머의 코드를 통해서 값을 전달하는 번거로움을 피하기 위해 안드로이드에서는 이 인텐트 플래그값을 제공합니다.

 

위에 나와있는 그림의 예를 통해 보면 엑티비티B가 엑티비티C를 호출하기위해 단순히 startActivity()를 이용하는 것을 알 수 있습니다. 그리고 지금 설명중인 플래그를 붙이도록 합니다. 이후에 엑티비티C에서는 setResult()를 통해 결과값을 정의를 한후에 finish()를 통해 엑티비티를 종료하도록 합니다.

엑티비티B에서는 단순히 마찬가지로 finish()를 통해 엑티비티를 종료하시기만 하면 됩니다. 이후에 startActivityForResult()를 통해 엑티비티B를 호출했던 엑티비티A는 onActivityResult() 콜백 메서드로 결과값을 받아보시면 엑티비티C에서 정의한 값을 받을 수 있다는것을 알 수 있습니다.

 

 

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

이 엑티비티 플래그는 시스템에 의하여 자동으로 설정되는 플래그입니다. 홈스크린화면에서 홈버튼을 롱클릭함으로써 뜨게 되는 “최근실행목록”을 통해 실행되었을 경우 자동으로 설정됩니다.

 

 

FLAG_ACTIVITY_MULTIPLE_TASK

이 엑티비티 플래그는 FLAG_ACTIVITY_NEW_TASK와 함께 사용하지 않으면 아무런 효과가 없는 플래그입니다. 두개의 플래그를 동시에 사용할 경우 새로운 태스크는 재활용되지 않고 무조건 새로 생성되며 피호출되는 엑티비티는 이 새로운 태스트의 최상위 엑티비티가 됩니다. (당연히 하나밖에 없을테니-_-a)

 

 

FLAG_ACTIVITY_NEW_TASK

이 엑티비티 플래그를 사용하여 엑티비티를 호출하게 되면 새로운 태스크를 생성하여 그 태

스크안에 엑티비티를 추가하게 됩니다. 단, 기존에 존재하는 태스크들중에 생성하려는 엑티비티와 동일한 affinity를 가지고 있는 태스크가 있다면 그곳으로 새 엑티비티가 들어가게됩니다.

하나의 어플리케이션안에서는 모든 엑티비티가 기본 affinity를 가지고 같은 태스크안에서 동작하는것이 기본적(물론 변경이 가능합니다)이지만 FLAG_ACTIVITY_MULTIPLE_TASK 플래그와 함께 사용하지 않을경우 무조건적으로 태스크가 새로 생성되는것은 아님을 주의하셔야 합니다.

 

 

FLAG_ACTIVITY_NO_ANIMATION

안드로이드 OS가 2.0으로 올라오면서 새로 추가된 엑티비티 플래그입니다. 이 플래그를 사용할 경우 엑티비티가 스크린에 등장할시에 사용될 수 있는 다양한 애니메이션 효과를 사용하지 않습니다.

 

 

FLAG_ACTIVITY_NO_HISTORY

이 플래그를 사용할 경우 새로 생성되는 엑티비티는 어떤 태스크에도 보존되지 않게 됩니다. 예를 들면 로딩화면과 같이 다시 돌아오는것이 의미가 없는 화면이라면 이 플래그를 사용하여 태스크에 남기지 않고 자동적으로 화면이 넘어감과 동시에 제거할 수 있습니다.

 

 

FLAG_ACTIVITY_NO_USER_ACTION

이 플래그가 설정되면 자동적으로 엑티비티가 호출될 경우에 자동 호출되는 onUserLeaveHint()가 실행되는것을 차단합니다. onUserLeaveHint() 콜백 메서드는 어플리케이션 사용중에 전화가 온다거나 하는등의 사용자의 액션없이 엑티비티가 실행/전환되는 경우에 호출되는 메서드입니다.

 

 

FLAG_ACTIVITY_REORDER_TO_FRONT

 

 

호출하려던 엑티비티가 이미 엑티비티 스택에 존재하고 있다면 이 플래그를 사용하여 스택에 존재하는 엑티비티를 최상위로 끌어올려줍니다. 결과적으로 엑티비티 스택의 순서가 재정렬되는 효과를 가집니다. 위의 예를 볼 경우에 엑티비티E가 C를 호출하게 됨으로써 엑티비티C가 최상단으로 이동하는 결과를 확인하실 수 있습니다.

 

 

FLAG_ACTIVITY_SINGLE_TOP

이 플래그는 말그대로 하나의 탑(?)을 의미하는 설정입니다. 엑티비티를 호출할 경우 호출된 엑티비티가 현재 태스크의 최상단에 존재하고 있었다면 새로운 인스턴스를 생성하지 않습니다. 예를 들어 ABC가 엑티비티 스택에 존재하는 상태에서 C를 호출하였다면 여전히 ABC가 존재하게 됩니다.

 

 

 

 

 

 


 

 

 


 

출처: http://hungry-developer.blogspot.kr/2013/11/intentflagactivityforwardresult.html

 


 

 

 

Intent.FLAG_ACTIVITY_FORWARD_RESULT 를 활용한 사례

(setResult() 를 이용한 결과 처리 위임)

 

프로젝트를 진행하다 보면 남의 코드를 보게 되는 일이 일상 다반사다.


남의 코드를 왜 보게 될까

보통 좋은 코드라서 참고하려고 보는 경우와 
Legacy코드를 떠맡아서 자신이 책임져야 하는 상황에 놓인 경우가 있는데

나의 경우 후자의 상황이였다.


QA팀에서 발견한 버그였는데 
그 버그를 수정하다보니 또다른 버그가 발견되었다

문제는 뭐냐하면 앱이 특정화면에서 Background로 진입 후 
프로세스 강제종료한 뒤에 다시 실행 했을 경우 정상동작하지 않는 다는 것이었다.


코드를 뒤져봤더니 Activity클래스에서 화면 복구시에 별다른 처리하는 부분이 없어서 발생하였다. 
일단 해당 이슈는 수정!

그런데 수정하고나서 테스트를 하다보니 이상한 동작이 감지되었다.
복구로직을 넣어 기능이 정상동작하게 처리하였는데 Back키를 눌러서
이전화면으로 가려고 했더니 

이게 왠걸 다시 보고 있던 화면을 실행시키는게 아닌가..ㅡㅡ 

잠시 멘붕상태였다가 코드를 잔잔히 살펴보니 이런 코드가 있었다.

private void startRedirectActivity() {
   Intent intent = getIntent();
   if (intent.hasExtra(IntentExtraConstants.REDIRECT_ACTIVITY)) {
       intent.setClassName(this, intent.getStringExtra(IntentExtraConstants.REDIRECT_ACITIVITY));
       if (intent.getExtras() != null) {
           startActivityForResult(intent, intent.getExtras().getInt("requestCode"));
       } else {
           startActivityForResult(intent, 0);
       }
   } else {
     finishActivityAgree();
   } 
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   setResult(resultCode, data);
   finish();
}

코드를 보아하니


저 코드가 존재하는 Activity를 B라 가정했을 때

A -> B -> C 이런식으로 호출을 하고
C에서 setResult를 통해 데이터를 A에게 전달하고자,
B라는 중간화면에서 onActivityResult에서 다시 setResult를 수행하고 자신은 종료.


정상적인 케이스에선 문제가 발견되지 않는다.

하지만 킬러앱들에 의해서 종료되거나 시스템에 의해 강제종료 된 상태로 다시 앱 실행시 화면을 복구하게 되는데 이 때 문제가 발생하게 된다.


C화면을 보고 있는 상태에서 강제 종료시 C화면을 다시 복구 하는데
여기서 Back을 하게 되면 B Activity의 onActivityResult를 타는 게 아니라
B Activity가 다시 onCreate부터 수행하게 된다.


왜냐하면 B Activity도 강제 종료되었기 때문 이건 개발자가 예상하지 못했던 동작이다.


위와 같은 문제를 해결하기 위해 안드로이드에선 진작부터 FLAG_ACTIVITY_FORWARD_RESULT라는 옵션을 제공하고 있다.
물론 API 1부터 제공하니 호환성 걱정은 없다.


FLAG_ACTIVITY_FORWARD_RESULT라는 옵션을 언제 사용하느냐면
위와 같은 요구사항을 처리할때

A에서 B를 호출할 때 startActivityForResult를 호출하고
B에서 C를 호출할 때 startActivity를 호출하면서 저 flag를 사용한다.
그리고 B는 finish()
그럼 C에서는 setResult를 통해 A에게 결과 값을 전달하게 된다.

옵션의 이름만 봐도 어떤 기능인지 대략적으로 짐작이 된다.

변경된 코드는 다음과 같다.

private void startRedirectActivity() {
   Intent intent = getIntent();
   if (intent.hasExtra(IntentExtraConstants.REDIRECT_ACTIVITY)) {
       intent.setClassName(this, intent.getStringExtra(IntentExtraConstants.REDIRECT_ACITIVITY));
       intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
       startActivity(intent);
       finish();
   } else {
     finishActivityAgree();
   } 
}

기존 코드에서 B에 존재하던 onActivityResult도 필요가 없으니 삭제.