Things take time

[Android] 최근 실행중인 앱 목록(Recent App)에서 앱을 실행함을 감지하는 방법 본문

Android(기능)

[Android] 최근 실행중인 앱 목록(Recent App)에서 앱을 실행함을 감지하는 방법

겸손할 겸 2018. 5. 11. 14:19

fffff[현상]


앱 하나가 외부로부터 실행한다. 무슨 말이냐면, 외부의 커스텀 스키마를 통해 웹에서 앱을 호출하거나.. 공유하기를 통해 앱으로 전달된다거나 하는 등의 작업이 있다고 가정하자.


이럴 때 앱이 하는 동작은 넘겨받은 데이터(이미지, 텍스트, 파라미터 등)를 분리/감별하여 원하는 작업을 수행한다.

예를 들어, 유튜브에서 본 동영상을 카카오톡으로 공유하기를 누르면 카카오톡 앱이 켜지면서 채팅방을 선택하거나, 공유할 대상을 선택하는 액티비티가 호출되고 공유된다.


안드로이드의 경우, 공유 받는 액티비티를 인텐트 필터를 통해 설정하여 받게 되어있고, 아이폰의 경우에는 공유 익스텐션이란 영역에서 처리하게 되어있다.


여기서 안드로이드는 공유 액티비티를 보통 처음 시작되는 액티비티로 하는 경우가 많다. 그래야 이후에 실행될 액티비티를 띄우면서 데이터를 전달하거나 하는 작업 등을 할 수 있다. 카카오톡의 경우 처음 인트로 화면이 나오고, 친구&대화방 목록이 나오는 것처럼 말이다.


문제는 여기서 공유하기작업을 마쳤고, 앱을 종료했다 가정하자. 여기서 앱 종료는 사용자가 직접 실행중인 앱 목록을 켜서 스와이프, 옆으로 밀어 완전 제거한 것이 아니라 백버튼을 눌러 앱을 종료했다는 것을 의미한다. 즉, 개발자가 지정한 finish() 혹은 finishAffinity()를 통해 앱이 종료되었다는 것이다. 

이 작업을 수행한 뒤에 하드웨어의 ㅁ 버튼을 눌러서 최근 앱들 목록을 확인할 수 있는데.. 여기서 앱을 실행시키면 다시 데이터를 있는 것으로 인식하여 해당 작업을 또 반복하게 된다.


내가 원한 것은 처음 데이터 작업을 마쳤으면, 이후에 들어왔을 땐 그 작업을 하지 말아야한다는 것이다. 물론 완전 종료하게 되면 문제는 없지만, 개발자가 앱을 그렇게 종료시킬수는 불가능하다.


[해결 과정]


1) 외부 앱에서 실행될 경우 flag 변수를 shared로 저장한다. 그리고 앱이 finish될 때 shared를 초기화 시킨다.

문제 : 앱을 finish()하지 않고, 사용자가 직접 완전 종료시키게 된다면 해당 이벤트를 감지할 수 없다. (* onDestroy는 다른 액티비티에 의해 가려질 때 호출된다.)


2) 기존 넘겨받은 데이터를 저장하여 prior값으로 저장 및 이후 실행 시 비교하여 동일할 경우, 호출하지 않는다.

문제 : 동일한 작업을 반복하지 못하는 것 자체가 문제


3) 코드



[코드]

    protected boolean wasLaunchedFromRecents() {
        return (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0;
    }

앱을 최근 목록에서 호출했을 때를 감지한다.


간단히 말해서, 최근 목록에서 앱을 실행하면 안드로이드 내부에서 자체적으로 액티비티를 호출하며 플래그를 심는다. 그것이 FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY 플래그다. 이 플래그를 검사하여 최근 앱 목록에서 호출되었는지를 감지한다.


조건 : 앱의 모든 액티비티가 finish() 되었을 때 호출된다.


이 함수를 공유 액티비티에 넣어 감지하게 하면 깔끔하게 해결된다.