월별 글 목록: 2019년 11월월

안드로이드 화면에 실행중인 앱 확인하는 방법

안드로이드 5(롤리팝) 이후부터는 안드로이드 기기에 실행중인 앱을 알 수 없게 되었습니다. 그래서, 안드로이드 5 이후 버전에서는 기기에 저장하고 있는 통계 데이터를 기반으로 완전히 정확하지는 않지만, 대략적으로 정확한 정보를 가져올 수 있습니다. UsageStatsManager를 사용해서 현재 안드로이드 기기의 화면에 실행중인 앱을 검색하는 방법을 살펴보자.

아래는 UsageStatsManager를 사용해서 안드로이드 기기에 저장되어 있는 이벤트 데이터를 검색하고, 이벤트가 포그라운드(Event.MOVE_TO_FOREGROUND 또는 Event.ACTIVITY_RESUMED)인 것을 확인해서 마지막 포그라운드 이벤트에 해당하는 패키지 이름을 가져온다. 이 정보는 대체로 정확하고, 아래 코드로 가져온 패키지가 현재 화면에서 실행중인 것을 확인 할 수 있다.

1. 앱의 AndroidManifest.xml에 아래의 권한을 추가


2. 안드로이드 기기에서 실행중인 앱 가져오기

public static String getTopPackageName(@NonNull Context context) {
  UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);

  long lastRunAppTimeStamp = 0L;

  final long INTERVAL = 1000 * 60 * 5;
  final long end = System.currentTimeMillis();
  // 1 minute ago
  final long begin = end - INTERVAL;

  LongSparseArray packageNameMap = new LongSparseArray<>();
  final UsageEvents usageEvents = usageStatsManager.queryEvents(begin, end);
  while (usageEvents.hasNextEvent()) {
    UsageEvents.Event event = new UsageEvents.Event();
    usageEvents.getNextEvent(event);

    if(isForeGroundEvent(event)) {
      packageNameMap.put(event.getTimeStamp(), event.getPackageName());
      if(event.getTimeStamp() > lastRunAppTimeStamp) {
        lastRunAppTimeStamp = event.getTimeStamp();
      }
    }
  }

  return packageNameMap.get(lastRunAppTimeStamp, "");
}

3. 이벤트가 포그라운드 이벤트인지 확인

private static boolean isForeGroundEvent(UsageEvents.Event event) {
  if(event == null) {
    return false;
  }

  if(BuildConfig.VERSION_CODE >= 29) {
    return event.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED;
  }

  return event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND;
}

위 코드를 사용해서 완전히 정확하지는 않지만, 대체로 정확하게 안드로이드 화면에서 실행중인 앱을 알 수 있다.

안드로이드 컨텍스트(Context)

안드로이드 컨텍스트(Context)는 리소스에 접근하는 인터페이스이고, 이 인터페이스는 크게 애플리케이션(Application), 액티비티(Activity), 컨텍스트 래퍼(ContextWrapper)의 베이스 컨텍스트(BaseContext)로 3가지 형태를 가진다. 안드로이드를 개발하는 데 있어 특정 상황에서 어떤 컨텍스트를 사용해야 하는지 아는 것은 매우 중요하다. 그래서, 개별 컨텍스트에 대해서 살펴보자.

애플리케이션 컨텍스트
– 애플리케이션은 컨텍스트는 앱 프로세스 자체라고 생각하면 쉽다. 애플리케이션 클래스 자체가 애플리케이션이기 때문에 안드로이드 앱 전반에 걸쳐서 사용할 수 있다. 그리고, 애플리케이션 클래스가 애플리케이션 컨텍스트이기에 라이프 사이클이 애플리케이션하고 같다. getApplicationContext()나 Application 클래스를 상속한 클래스 객체를 사용하면 된다.

액티비티
– 액티비티 컨텍스트도 액비티비 자체라고 생각하면 쉽다. 프레그먼트(Fragment)나 뷰에서 사용할 수 있는 컨텍스트이다. 일반적으로 안드로이드 뷰와 관련된 작업을 하는 데 사용한다. 액티비티 컨텍스트로 액티비티 자체이기에 라이프 사이클이 액티비티와 같다. 보통 액티비티에서는 this, 프레그먼트에서는 getContext()나 getActivity(), 그리고 뷰에서는 getContext()로 컨텍스트를 사용하면 된다.

베이스 컨텍스트
– 자신의 컨텍스트가 아닌 다른 컨텍스트를 접근하기 위해서 사용한다. 보통 getBaseContext()로 컨텍스트를 사용하면 된다.  [ 그림 1. 컨텍스트 클래스 다이어그램 ]

위 그림은 컨텍스트를 어떤 안드로이드 구성요소가 구현하고 있는지 알 수 있고, 위에서 설명한 컨텍스트 객체가 왜 애플리케이션, 액티비티, 컨텍스트 래퍼의 베이스 컨텍스트인지 알 수 있다.

스택오버플로어 사이트에서, 안드로이드 컨텍스트와 사용할 수 있는 기능들을 정리한 이미지를 살펴보면 다음과 같다.


[ 그림 2. 컨텍스트 ]


[ 그림 3. 개별 컨텍스트에서 사용할 수 있는 기능들 ]

안드로이드에서 제공하는 컨텍스트에 대해서 살펴봤다. 그리고 개별 컨텍스트가 제공할 수 있는 기능별 제약이 있기에, 잘 알아서 여러 상황에 맞는 컨텍스트를 사용해야 한다.

레퍼런스
https://stackoverflow.com/questions/3572463/what-is-context-on-android