HOME > android > feature

안드로이드 Q - Background Activity 실행 제한

By JS|19 Jul 2019

안드로이드 Q에서 백그라운드에서 액티비티를 실행하지 못하도록 제한합니다. Q 이전에는 백그라운드에서 액티비티를 실행할 수 있었습니다. 하지만 알지 못하는 액티비티가 갑자기 실행되거나, 광고 등의 악성 앱의 액티비티가 실행되는 문제들이 있었습니다.

구글은 Q에서 사용자와 상호작용하지 않는 앱이 백그라운드에서 액티비티를 실행하지 못하도록 제한하였습니다. 백그라운드에서 액티비티를 실행해야 하면 노티피케이션으로 사용자에게 알림을 주어 실행하도록 할 수 있습니다.

이런 제한사항은 앱의 SDK API와 무관하게 안드로이드 Q 디바이스에 실행되는 모든 앱에 적용됩니다. 따라서 자신의 앱이 백그라운드에서 액티비티를 실행시킨다면 새로운 정책에 맞게 수정이 되어야 합니다.

액티비티 실행 조건

사용자와 상호작용을 하는 앱은 백그라운드에서 액티비티를 실행할 수 있습니다. 앱이 사용자와 상호작용하고 있다고 인식되는 조건은 어떤 것들이 있는지 알아보겠습니다.

앱의 화면이 Foregrond에 있을 때

Foreground에 화면이 실행 중이라면 상호작용을 하고 있다고 생각합니다.

앱의 액티비티가 백스택에 남아있을 때

액티비티에서 finish() 등으로 종료한지 얼마 안되었거나, 최근에 실행한 액티비티가 백스택에 남아있는 경우 사용자와 상호작용을 했다고 인식합니다.

시스템이 앱의 서비스에 바인드 했을 때

이 조건은 다음과 같은 서비스에만 적용됩니다.

  • AccessibilityService
  • AutofillService
  • CallRedirectionService
  • HostApduService
  • InCallService
  • TileService
  • VoiceInteractionService
  • VrListenerService

PendingIntent를 받았을 때

앱이 시스템으로부터 PendingIntent를 받거나, Foreground에서 실행 중인 앱으로부터 PendingIntent를 받았다면, 몇초간은 백그라운드에서 액티비티를 실행할 수 있습니다.

시스템 브로드 캐스트를 받았을 때

예를 들어 ACTION_NEW_OUTGOING_CALL, SECRET_CODE_ACTION 처럼, 앱이 인텐트를 브로드캐스트로 받았을 때 UI를 실행할 것이라고 예상되는 인텐트들이 있습니다. 이런 인텐트들을 브로드캐스트로 받으면 몇초간은 백그라운드에서 액티비티를 실행할 수 있습니다.

CompanionDeviceManager API

CompanionDeviceManager를 통해 앱이 하드웨어와 페어링되었을 때, 특정 상황에서 백그라운드 액티비티를 실행시킬 수 있습니다.

SYSTEMALERTWINDOW

사용자가 앱에 SYSTEM_ALERT_WINDOW 권한을 부여하면, 이 앱은 항상 백그라운드에서 액티비티를 실행할 수 있습니다.

Notification으로 액티비티 실행

알림이나 전화가 왔을 때 처럼 갑자기 다른 화면으로 전환해야 하는 경우가 있습니다. 백그라운드 서비스는 액티비티를 실행하지 못하기 때문에 노티피케이션을 만들어 사용자가 앱을 실행할 필요가 있다고 알려야 합니다.

아래 예제는 GoogleDeveloper에 소개된 예제입니다. 예제는 Full Screen Intent를 사용하며, 불필요하다면 이 코드를 제거하면 됩니다.

val fullScreenIntent = Intent(this, CallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Incoming call")
    .setContentText("(919) 555-1234")
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setCategory(NotificationCompat.CATEGORY_CALL)

    // Use a full-screen intent only for the highest-priority alerts where you
    // have an associated activity that you would like to launch after the user
    // interacts with the notification. Also, if your app targets Android Q, you
    // need to request the USE_FULL_SCREEN_INTENT permission in order for the
    // platform to invoke this notification.
    .setFullScreenIntent(fullScreenPendingIntent, true)

val incomingCallNotification = notificationBuilder.build()

노티피케이션을 만들었다면 startForeground()로 사용자에게 알림을 보여줄 수 있습니다.

// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, notification)

노티피케이션이 발생하고 사용자가 누르면 설정한 액티비티가 실행됩니다.

백그라운드 실행 허용

백그라운드에서 액티비티 실행 제한이라는 기능으로 앱의 기능을 테스트하기 어려울 수 있습니다. 테스트를 위해, 다음과 같이 개발자모드 또는 abb 명령어로 이런 제한사항들을 비활성화 할 수 있습니다.

  • [설정 > 개발자모드]에서 'Allow background activity starts' 옵션을 비활성화
  • adb shell settings put global background_activity_starts_enabled 1

참고