앱이 백그라운드 상황일때 서비스를 이용하는 것은 제약을 받지만, 잡 스케줄러를 이용하면 이를 보완할 수 있다. 안드로이드 버전 8부터 서비스 백그라운드 제약이 생기면서 잡 스커줄러의 역할이 더욱 중요해졌다.
잡 스케줄러를 이용한다고 해서 모든 상황의 백그라운드 처리를 할 수 있는 것은 아니다. 잡 스케줄러도 개발자가 만드는 서비스이므로 이 서비스를 어떤 상황에서 실행해야 하는지 조건을 명시해 줘야한다. 이렇게 조건을 명시할 수 있는 상황에서만 백그라운드에서 처리할 수 있다.
잡 스케줄러에 조건을 명시할 수 있는 상황은 다음과 같다.
네트워크 타입이 변경되거나 배터리 충전 상태가 변경되었을 때, 또는 특정 앱의 콘텐츠 프로바이더가 변경되었을 때를 조건으로 명시할 수 있으며 해당 조건에 부합하면 시스템이 잡 스케줄러를 실행한다. 또한 아래의 조건을 명시할 수 있다.
개발자가 만드는 서비스이므로 메니페스트에 등록해야 한다.
<service android:name=".MyJobService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"/>
Service 가 아니라 JobService 객체를 상속해야한다.
class MyJobService : JobService(){
override fun onCreate() {
super.onCreate()
Log.d("JOB", "Create")
}
override fun onDestroy() {
super.onDestroy()
Log.d("JOB", "Destroy")
}
override fun onStartJob(params: JobParameters?): Boolean {
Log.d("JOB", "Start")
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
Log.d("JOB", "Stop")
return false
}
}
onStartJob() 에 처리할 작업을 구현한다. 이 함수의 반환값은 Boolean 인데 true 는 작업이 끝나지 않았음을, false 는 작업이 끝났음을 의미한다. 여기서 false 를 반환하면 시스템이 더 처리할 필요가 없다고 판단하여 바로 onStopJob() 을 건너뛰고 onDestroy() 함수를 호출해서 서비스를 종료한다.
onStartJob() 함수가 true 를 반환하면 백그라운드에서 처리할 작업이 아직 끝나지 않았다는 것을 의미하며 onDestroy() 함수는 호출되지 않는다, 오랜 시간 살아있는 서비스가 된다. 따라서 올래 걸리는 작업을 스레드 등에서 처리하고 끝날 때 jobFinish() 함수를 호출하는 식으로 onStartJob() 함수를 구현한다.
onStopJob() 함수가 호출되는 경우는 onStartJob() 함수에서 true 를 반환해 서비스가 오랜 시간 살아있는 상황에서 갑자기 잡 스케줄러를 실행하는 조건이 변경되거나 어디선가 cancel() 함수로 취소했을 때이다. 시스템은 이러한 상황을 잡 스케줄러가 비정상으로 종료된 것으로 인지하고 서비스를 종료하기 전에 처리할 로직을 실행하고자 onStopJob() 함수를 호출한다.
onStopJob() 이 false 를 반환하면 잡 스케줄러 등록을 취소하는 것이고, true 를 반환하면 잡 스케줄러를 재등록한다.
var jobScheduler: JobScheduler? = getSystemService<JobScheduler>()
JobInfo.Builder(1, ComponentName(this, MyJobService::class.java)).run {
setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
jobScheduler?.schedule(build())
}
JobInfo.Builder 생성자의 첫 번째 매개변수는 등록할 작업의 식별자값이다. 나중에 cancel() 함수로 작업을 취소할 때 이 값을 이용한다. 두번째 매개변수는 등록할 잡 서비스이다. 이 서비스르 시스템에 등록하겠다는 의미이다. 그리고 빌더의 세터 함수를 이용해 조건을 명시한다. 이렇게 만든 JobInfo 객체를 JobScheduler 의 schedule() 함수로 시스템에 등록하면 된다.
JobInfo.Builder 에 지정한 잡 서비스가 실행되는 조건을 명시할 때는 다음과 같은 세터 함수를 이용한다.
이 중에서 setPersisted() 함수를 true 로 전달하려면 메니페스트에 anroid.permission.RECEIVE_BOOT_COMPLETED 를 퍼미션을 선언해야한다. setPeriodic() 함수로 실행주기를 설정할 때는 최소 15분 이상이어야 한다. 이 함수로 실행 주기를 설정하더라도 정확한 시간을 보장하지 않는다. 주어진 시간 내에 한번은 반복된다.
잡 서비스에 데이터를 전달하려면 JobInfo.Builder 의 setExtras() 함수를 이용한다.
val jobScheduler: JobScheduler? = geySystemService<JobScheduler>()
val extras = PersistableBundle()
extras.putString("extra data", "hello")
val builder = JobInfo.Builder(1, componentName)
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
builder.setRequiresCharging(true)
builder.setExtra(extras)
val jobInfo = builder.build()
jobScheduler!!.scheduler(jobInfo)
이렇게 전달된 데이터를 가져올때는 잡 서비스에서 onStartJob() 에 jabparameter.extras.getString 처럼 하면 된다.