백그라운드 작업에 대한 시스템 제한사항

백그라운드 프로세스는 메모리와 배터리를 많이 사용할 수 있습니다. 예를 들어 암시적 브로드캐스트는 프로세스가 많은 작업을 하지 않더라도 수신 대기하도록 등록된 많은 백그라운드 프로세스를 시작할 수 있습니다. 이는 기기 성능과 사용자 환경에 모두 상당한 영향을 미칠 수 있습니다.

시스템 제한을 방지하려면 백그라운드 작업에 적합한 API를 사용해야 합니다. 백그라운드 작업 개요 문서는 필요에 맞는 올바른 API를 선택하는 데 도움이 됩니다.

사용자 시작 제한사항

앱이 Android vitals에 설명된 비정상적인 동작을 보이면 시스템은 사용자에게 시스템 리소스에 대한 앱의 액세스를 제한하라는 메시지를 표시합니다.

시스템에서 앱이 과도한 리소스를 사용하고 있음을 알면 사용자에게 알리고 앱의 작업을 제한하는 옵션을 사용자에게 제공합니다. 알림을 트리거할 수 있는 동작은 다음과 같습니다.

  1. 불필요한 wake lock: 화면이 꺼져 있을 때 한 시간 동안 유지되는 부분적인 wake lock 1회
  2. 불필요한 백그라운드 서비스: 앱이 API 수준 26 미만을 타겟팅하고 과도한 백그라운드 서비스가 있는 경우

적용되는 정확한 제한사항은 기기 제조업체에서 결정합니다. 예를 들어 AOSP 빌드에서는 앱이 포그라운드에 있는 경우를 제외하고 제한된 앱이 작업을 실행하거나 알람을 트리거하거나 네트워크를 사용할 수 없습니다.

네트워크 활동 브로드캐스트 수신에 관한 제한사항

앱은 매니페스트에서 CONNECTIVITY_ACTION 브로드캐스트를 수신하도록 등록한 경우 이 브로드캐스트를 수신하지 않으며 이 브로드캐스트에 종속되는 프로세스는 시작되지 않습니다. 이는 기기가 무제한 네트워크에 연결될 때 네트워크 변경사항을 수신 대기하거나 대량 네트워크 활동을 실행하려는 앱에 문제가 될 수 있습니다. 이러한 제한사항을 해결하기 위한 여러 솔루션이 Android 프레임워크에 이미 있지만 올바른 솔루션을 선택하는 것은 앱에서 달성하려는 목적에 따라 다릅니다.

무제한 연결에서 작업 예약

WorkRequest를 빌드할 때 NetworkType.UNMETERED Constraint를 추가합니다.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

작업의 조건이 충족되면 앱은 지정된 Worker 클래스의 doWork() 메서드를 실행하기 위한 콜백을 수신합니다.

앱이 실행되는 동안 네트워크 연결 모니터링

실행 중인 앱은 등록된 BroadcastReceiverCONNECTIVITY_CHANGE를 계속 수신 대기할 수 있습니다. 그러나 ConnectivityManager API는 지정된 네트워크 조건이 충족될 때만 콜백을 요청하는 더 강력한 메서드를 제공합니다.

NetworkRequest 객체는 NetworkCapabilities의 관점에서 네트워크 콜백의 매개변수를 정의합니다. NetworkRequest.Builder 클래스를 사용하여 NetworkRequest 객체를 만듭니다. 그러면 registerNetworkCallbackNetworkRequest 객체를 시스템에 전달합니다. 네트워크 조건이 충족되면 앱은 ConnectivityManager.NetworkCallback 클래스에 정의된 onAvailable() 메서드를 실행하기 위한 콜백을 수신합니다.

앱은 앱이 종료되거나 unregisterNetworkCallback()을 호출할 때까지 콜백을 계속 수신합니다.

이미지 및 동영상 브로드캐스트 수신에 관한 제한사항

앱은 ACTION_NEW_PICTURE 또는 ACTION_NEW_VIDEO 브로드캐스트를 송수신할 수 없습니다. 이 제한사항은 여러 앱이 새로운 이미지나 동영상을 처리하기 위해 절전 모드를 해제해야 할 때 성능 및 사용자 환경에 미치는 영향을 완화하는 데 도움이 됩니다.

어떤 콘텐츠 권한이 작업을 트리거했는지 확인

WorkerParameters를 사용하면 앱에서 어떤 콘텐츠 권한과 URI가 작업을 트리거했는지에 관한 유용한 정보를 수신할 수 있습니다.

List<Uri> getTriggeredContentUris()

작업을 트리거한 URI 목록을 반환합니다. 작업을 트리거한 URI가 없거나 (예: 작업이 기한 또는 기타 이유로 인해 트리거된 경우) 변경된 URI 수가 50보다 크면 비어 있습니다.

List<String> getTriggeredContentAuthorities()

작업을 트리거한 콘텐츠 권한의 문자열 목록을 반환합니다. 반환된 목록이 비어 있지 않으면 getTriggeredContentUris()를 사용하여 변경된 URI의 세부정보를 검색합니다.

다음 샘플 코드는 CoroutineWorker.doWork() 메서드를 재정의하고 작업을 트리거한 콘텐츠 권한과 URI를 기록합니다.

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

시스템 제한의 앱 테스트

메모리가 부족한 기기나 조건에서 실행되도록 앱을 최적화하면 성능과 사용자 환경을 개선할 수 있습니다. 백그라운드 서비스와 매니페스트에 등록된 암시적 broadcast receiver의 종속 항목을 삭제하면 앱이 이러한 기기에서 더 잘 실행될 수 있습니다. 이러한 백그라운드 프로세스를 완전히 사용하지 않고 앱이 실행되도록 최적화하는 것이 좋습니다.

몇 가지 추가적인 Android 디버그 브리지 (ADB) 명령어를 사용하면 이러한 백그라운드 프로세스를 사용 중지한 상태에서 앱 동작을 테스트할 수 있습니다.

  • 암시적 브로드캐스트와 백그라운드 서비스를 사용할 수 없는 조건을 시뮬레이션하려면 다음 명령어를 입력합니다.

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • 암시적 브로드캐스트 및 백그라운드 서비스를 다시 사용 설정하려면 다음 명령어를 입력합니다.

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

앱의 추가 최적화

백그라운드 작업의 동작을 최적화하는 다른 좋은 방법은 작업 예약 API의 배터리 사용량 최적화 문서를 참고하세요.