안드로이드 18) Background Limit
Concepts of Background Limit
1. Background Limit
- 안드로이드 앱은 액티비티, 서비스, 브로드캐스트 리시버, 컨텐츠 프로바이더로 구성되어 있고 액티비티를 제외한 나머지는 화면과 상관없는 백그라운드 작업을 목적
- 백그라운드 제약은 안드로이드 8버전(API Level 26버전)부터 앱의 화면이 출력되지 않은 상황에서 백그라운드 업무를 처리하는 것에 제약이 가해진 것이다.
- 정확히 말하자면, 시스템이 부팅 완료되자마자 브로드캐스트 리시버를 실행시키고 이를 이용하여 서비스를 실행시켜 어떤 업무(백그라운드 업무)를 처리하는 것이 불가능해졌다는 것이다.
Broadcast Limit
- 브로드캐스트 리시버에는 제약이 가해지긴 했지만 다른 방법으로 얼마든지 실행시킬 수 있기 때문에 문제가 발생하지는 않을 것이다.
1. Broadcast Limit
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="ACTION_RECEIVER"/>
</intent-filter>
</receiver>
val intent = Intent("ACTION_RECEIVER")
sendBroadcast(intent)
- 브로드캐스트 리시버를 실행시키기 위해서는 인텐트를 sendBroadcast() 함수로 발생시킨다.
- 브로드캐스트 리시버를 암시적 인텐트에 의해 실행시키는 것 금지되었다.
- 그럼 위의 코드는 실행이 안되냐?
- 위의 그림과 같이 같은 앱에서 액티비티가 암시적 인텐트로 실행시키는 것은 안되지만, 다른 앱에서 액티비티가 암시적 인텐트로 실행시키는 것은 가능하다.
- 즉 내부에서 브로드캐스트 리시버를 암시적 인텐트로 실행시키는 것이 금지된 것이다.
- 내부에서는 브로드캐스트 리시버를 실행시키려면 명시적 인텐트로 실행시켜야 한다.
receiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("broadcast limit", "outer app dynamic receiver")
}
}
registerReceiver(receiver, IntentFilter("ACTION_OUTER_DYNAMIC_RECEIVER"))
- 하지만 코드에서 regosterReceiver()로 등록시킨 경우는?
- 이 경우에는 암시적 인텐트로 실행이 가능하다.
2. Broadcast Limit 정리
Service Limit
1. Service Limit
- 앱이 백그라운드 상태에 있을 때 서비스를 실행시키기 위해서 명시적 혹은 암시적 인텐트를 발생시키면 에러 발생
- Service Limit이 발생하지 않는 경우
- 앱이 포그라운드 상황이라면 정상 실행
- 우리 앱의 Activity가 화면에 출력되는 경우
- 우리 앱의 여러 서비스 중 하나가 포그라운드 서비스로 동작하는 경우
- 우리 앱의 서비스 중 하나가 다른 앱의 bind되어 다른 앱이 포그라운드로 실행하는 경우
- 우리 앱의 콘텐츠 프로바이더 중 하나를 포그라운드로 실행되는 다른 앱에서 사용하는 경우
- 앱이 백그라운드 상황이어도 아래의 경우 정상 실행
- 우선 순위가 높은 Firebase 클라우드 메시징(FCM) 메시지 처리
- SMS/MMS 메시지와 같은 브로드캐스트 수신
- 알림(notification)에서 PendingIntent 실행
- VPN 앱이 포그라운드로 승격되기 전에 VpnService 시작
- 앱이 포그라운드 상황이라면 정상 실행
2. Service Limit 해결 방법
- 백그라운드 상황에서 서비스가 정상 실행되게 할 수 있는 방법
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
- startForegroundService() 함수에 의해 인텐트를 발생시키면 앱의 백그라운드 상황이라고 하더라도 정상적으로 서비스가 실행
- startForegroundService() 함수에 의해 서비스가 정상 실행되기는 하지만 얼마 후 에러가 발생
val notification = builder.build()
startForeground(1, notification)
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
- startForegroundService()에 의해 실행된 서비스 내에서 빠른 시간내에 startForeground() 함수(매개변수 : 알림 객체)를 호출해줘서 notification을 띄워줘야 한다.
- 유저 입장에서는 쓸데 없는 notification을 띄우는 것이 불편할 수 있음
JobScheduler
1. JobScheduler
- JobScheduler을 이용하면 앱이 백그라운드 상황에서도 업무처리 가능
- JobScheduler는 일종의 서비스
- 하지만 인텐트로 실행시키지 않고 시스템에 등록을 하면 시스템에서 특정 상황이 됐을 때 실행
- 조건을 명시하고 그 조건에 맞는 경우에만 백그라운드 업무 처리 가능
- 네트워크 타입
- 배터리 충전 상태
- 특정 앱의 컨텐츠 프로바이더의 갱신
- 실행 주기
- 최소 지연 시간
2. JobScheduler 사용 방법
1) android.permission.BIND_JOB_SERVICE 퍼미션이 등록
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
2) JobService 구현
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class MyService: JobService() {
override fun onCreate() {
super.onCreate()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onStartJob(params: JobParameters?): Boolean {
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
- onStartJob() : 백그라운드에서 처리되어야 하는 업무를 가지는 함수
- 리턴값에 따라 다르게 동작
- false : Job이 완벽하게 종료되었다는 의미 → onStopJob이 호출되지 않음
- true : Job이 아직 끝나지 않았음을 의미
- 리턴값에 따라 다르게 동작
- onStopJob()
- 리턴값에 따라 다르게 동작
- false : JobScheduler 등록이 취소, 조건을 만족해도 다시 실행되지 않음
- true : 다시 JobScheduler 등록, 조건을 만족하면 다시 실행될 수 있음
- 리턴값에 따라 다르게 동작
3) 실행되는 조건을 JobInfo 객체에 담아 시스템에 등록
JobInfo.Builder(1, ComponentName(this, MyService::class.java)).run {
setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
jobScheduler?.schedule(build())
}
- 어떤 JobService를 실행할 건지를 지정해주고 몇몇 setter 함수로 조건을 준다.
- setter 함수 종류
- setPersisted(true) : 단말을 재부팅해도 Job 등록 유지해야 하는지 설정
- setPeriodic(long intervalMillis) : Job의 실행 주기 설정
- setMinimumLatency(long minLatencyMillis) : Job 실행의 지연 시간 설정
- setOverrideDeadline(long maxExecutionDelayMillis) : 다른 조건이 만족하지 않는다고 하더라도 이 시간 안에 Job이 실행되어야 함을 설정
- setRequiredNetworkType(int networkType) : 네트워크 타입 설정
- setRequiresBatteryNotLow(boolean batteryNotLow) : 배터리가 낮은 상태가 아님을 설정
- setRequiresCharging(boolean requiresCharging) : 배터리가 충전 상태인지를 설정
Author And Source
이 문제에 관하여(안드로이드 18) Background Limit), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@alsgk721/안드로이드-18-Background-Limit저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)