우선 가장 간단한 방법으로는 ActivityManager 를 사용하는 방법이다. 그러나 이 것으로 현재 메모리상에 생성된 Activity 의 객체들을 가져올수도 없고 매니페스트에 퍼미션도 줘야 하는데 영 찜찜하다.

   다른 개발자들은 동적으로 ActivityStack 에 있는 액티비티의 인스턴스를 어떻게 가져오나 궁금하여 스택 오버플로우를 찾아봤는데, 많은 개발자들이 Application 클래스를 상속받아 이 곳에 Activity를 관리하는 별도의 리스트를 만들어 사용하고 있었다.

   하지만 프로젝트마다 이렇게 구현하면 여간 귀찮은 것이 아니라서, 그냥 각 Task 내의 Activity 의 래퍼런스들을 담고있는 리스트를 갖고 있는 싱글톤 객체를 이용하여 ActivityStack 을 구현해 보았다. 

  우선 코드는 다음과 같다.


이 곳에서 최신 코드를 보거나 다운로드 받을 수 있다. 

  사용법은 ItemActivity 를 사용 하려는 Activity 에서 상속받아 사용하거나, StackActivity 코드처럼 ActivityStack 클래스의 메소드를 호출하여 사용하면 된다. 다만, 각 이벤트 메소드에 맞는 ActivityStack 의 메소드 호출을 실수로 빠뜨리거나 잘못 호출하면 메모리 누수가 일어날 수도 있으니 주의하자. 

   
  만약 아래 그림(?) 처럼 두 개의 Task 가 있고 이 곳에 Activity 가 실행되고 있다고 가정한다.
  각 박스의 윗 부분은 Application 의 패키지 명을 타나내고 밑은 Activity 이름을 나타낸다. 그리고 com.xx.xx 패키지의 ActivityC 가 화면에 보여지는 상태다. (onResume 이 호출된 상태)



TaskID:12  | com.yy.yy       | com.yy.yy       | com.yy.yy         | com.xx.xx      |
                     | ActivityA       | ActivityB         | ActivityC          | ActivityC        | 
                                                                                                        (Foreground) 
                                                                        

TaskID:13  | com.xx.xx    | com.xx.xx       | com.xx.xx      |                
                     | ActivityA       | ActivityB        | ActivityC        |                

  우선 아까도 언급했지만, 사용하려는 대상 Activity 에서는 StackActivity  를 상속받거나 onCreate, onDestroy, onResume, onPause 에서 ActivityStack 의 각 메소드들을 호출해야 한다. (StackActivity 내부 코드 참고)

- com.xx.xx 패키지의 앱 내부에서 같은 패키지의 Activity 가 실행되고 있는 TaskID 들 가져오기.
ActivityStack activityStack =  ActivityStack.getInstance(); 
Integer[] taskIds = activityStack.getAliveTaskIDs();

- 결과 :  [12,13]


- 현재 화면에 보여지고 있는 Activity 인스턴스 가져오기 

ActivityStack activityStack =  ActivityStack.getInstance(); 
Activity foregroundActivity = activityStack.getForegroundActivity();

- 결과 : task ID 12 에 올라간 ActivityC 의 인스턴스를 가져온다.


- 현재 어플리케이션이 실행중인지 알아보기

ActivityStack activityStack =  ActivityStack.getInstance(); 
boolean isRun = activityStack.isRunning();

- 결과 : true


  나머지 사용법은 ActivityStack.java 파일의 주석을 참고하자.

  


  마지막으로, 이 방법은 좋지 않은 방법이다. 잘못 사용하면 어떤 결과를 초래할지 모르고 메모리 누수의 위험도 있다. 게다가 이름만 ActivityStack 이다. 실제 Task 위에 있는 액티비티 스택과 혼동하면 안 된다.

  Service 내부에서 유지보수 하기 귀찮은 Broadcastreceiver 와 ActivityManager 를 쓰지 않고 액티비티가 살았는지 죽었는지, 또는 Foreground 인지 확인할때와 Task 상에 쌓여있는 Activity 들을 정리할 때, 유용하게 사용할 수 있지만 그 외의 경우에는 조심해서 사용하자. 만약에 Activity 가 Background 에 있는 상태에서 Fragment 를 붙이거나 Dialog 를 띄운다면 Runtime Exception 이 발생하기 때문이다. 

Posted by 범 범2

댓글을 달아 주세요