오늘은 서비스를 이어서 공부했다.
API 26레벨 이후, 백그라운드 작업에 제약이 존재한다.
리시버같은 경우는 매니페스트에 등록한 리시버를 암시적으로 실행할 때, 같은 앱이든 외부 리시버든 실행되지 않는다.
서비스는 앱이 백그라운드 상태일 때, 인텐트를 전달하면 오류가 발생한다.(몇몇 예외상황이 있긴있다)
포그라운드(foreground) 상태 (이외는 다 백그라운드 상태)
startForegroundService()
함수로 인텐트를 시작하면 앱이 백그라운드 상태이더라도 서비스가 실행할 수는 있다. 하지만 결국 오류가 발생하므로 서비스를 정상으로 유지할 수는 없다.
따라서 위의 함수가 호출된다면 빨리 startForeground()를 호출해 포그라운드 상황으로 만들라는 의도이다.
단, 이 함수를 정상적으로 호출하려면 매니페스트에 android.permission.FOREGROUND_SERVICE 퍼미션을 등록해야 한다.
val norification = builder.build()
startForeground(1, notification)
앱이 백그라운드 상황일 때 작업처리에 제약을 덜 받기위해 잡 스케줄러를 이용한다.
잡스케줄러는 개발자가 만드는 서비스이므로 어떤 상황에서 실행해야하는지 조건을 명시해줘야 백그라운드에서 작업이 가능하다.
백그라운드에서 처리할 작업을 구현한 서비스
<service
android:name=".MyJobService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
class MyJobService : JobService() {
override fun onCreate() {
super.onCreate()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onStartJob(params: JobParameters?): Boolean {
// 백그라운드에서 처리할 작업을 구현
TODO("Not yet implemented")
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
// 작업이 정상으로 처리되지 않았을 때 호출
TODO("Not yet implemented")
return false
}
}
onStartJob() 함수에는 백그라운드에서 처리할 작업을 구현한다.
함수의 반환값은 Boolean으로 작업이 완벽히 종료되면 false, 작업이 아직 끝나지 않았으면 true를 반환한다.
따라서 false면 onStopJob()을 건너뛰고 바로 onDestroy()를 호출해 서비스를 종료한다. true면 스레드 종료까지 서비스가 종료되지 않고, 명시적으로 jobFinished() 함수가 호출되어야 onDestroy()가 호출되어 서비스가 종료된다.
onStopJob()도 반환값이 Boolean인데 false면 잡스케줄러 등록을 취소하고, true면 잡스케줄러를 재등록 한다. 이 함수는 작업이 정상적으로 처리되지 않았을때 호출된다.
잡서비스의 실행 조건을 정의
var jobScheduler: JobScheduler? = getSystemService<JobScheduler>()
JobInfo.Builder(1, ComponentName(this, MyJobService::class.java)).run {
setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
jobScheduler?.schedule(build())
}
setPersisted(true): 기기를 재부팅해도 작업 등록을 유지해야 하는지를 설정
setPeriodic(long intervalMillis): 작업의 실행 주기를 설정
setMinimumLatency(long minLatencyMillis): 작업의 실행 지연 시간을 설정
setOverrideDeadline(long maxExecutionDelayMillis): 다른 조건에 만족하지 않더라도 작업이 이 시간 안에 실행되어야 함을 설정
setRequiredNetworkType(int networkType): 네트워크 타입을 설정
setRequiresBatteryNotLow(boolean batteryNotLow): 배터리가 낮은 상태가 아님을 설정
setRequiresCharging(boolean requiresCharging): 배터리가 충전 상태인지를 설정
잡서비스를 JobInfo 객체를 이용해 시스템에 등록하면 조건에 만족될 때 실행된다.
잡서비스에 데이터를 전달하려면 JobInfo.Builder의 setExtras() 함수를 이용한다.
val extras = PersistableBundle()
extras.putString("extra_data", "hello world")
val builder = JobInfo.Builder(1, componentName)
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
builder.setRequiresCharging(true)
builder.setExtras(extras)
val jobInfo = builder.build()
override fun onStartJob(params: JobParameters?): Boolean {
params.extras.getString("extra_data")
return false
}