## 원본
- [Android O에서의 백그라운드 처리를 위한 JobIntentService](https://medium.com/til-kotlin-ko/android-o에서의-백그라운드-처리를-위한-jobintentservice-250af2f7783c)
#### 참고
- https://stackoverflow.com/questions/51668607/jobintentservice-runs-periodically
- [JobScheduler를 사용하여 프로와 같은 작업 예약](https://medium.com/google-developers/scheduling-jobs-like-a-pro-with-jobscheduler-286ef8510129)
- https://github.com/firebase/firebase-jobdispatcher-android#fn2
- [Android 작업 스케줄러](https://docs.microsoft.com/ko-kr/xamarin/android/platform/android-job-scheduler)
- https://developer.android.com/topic/performance/scheduling
- [Android 배터리 및 메모리 최적화-Google I/O 2016 (비디오)](https://www.youtube.com/watch?v=aSjBBPYjelE)
- [Android JobScheduler-René Ruppert-Xamarin University](https://www.youtube.com/watch?v=aSjBBPYjelE)
- [1분반복](http://www.masterqna.com/android/77616/일정-시간마다-1분-서비스를-실행하기-위한-방법)
#### Comparison to other libraries
Library |
Minimum API |
Requires Google Play |
Service API1 |
Custom retry strategies |
Framework JobScheduler |
21 |
No |
JobScheduler |
Yes |
Firebase JobDispatcher |
14 |
Yes |
JobScheduler |
Yes |
evernote/android-job |
14 |
No2 |
Custom |
Yes |
Android WorkManager3 |
14 |
No2 |
Custom |
Yes |
---
### JobScheduler?
- Android Lollipop - Project Volta ::> 백그라운드 동작을 최적화위해 소개됨.
- ACTION_POWER_CONNECTED 브로드캐스트 수신조건을 대체할 수 있습니다.
### 구성요소
- 필요한 조건 및 인자 : [Android.App.Job.JobInfo](https://developer.android.com/reference/android/content/Context#registerReceiver%28android.content.BroadcastReceiver,%20android.content.IntentFilter%29)
- 해당조건의 동작 : [Android.App.Job.JobService](https://developer.android.com/reference/android/content/Context#registerReceiver%28android.content.BroadcastReceiver,%20android.content.IntentFilter%29)
- 예약, 실행 및 취소 : [Android.App.Job.JobScheduler](https://developer.android.com/reference/android/app/job/JobScheduler)
### Job의 구현
1. JobInfo를 통해 Job의 **실행 조건을 설정**해 JobScheduler에 **등록**.
2. JobService를 상속받아 Job실행시 필요한 동작을 구현.
3. Job실행을 위한 권한(android.permission.BIND_JOB_SERVICE)를 등록합니다.
#### 실행조건의 설정과 등록 - JobInfo
- JobInfo : 네트워크의 연결 상태, 충전여부, 디바이스의 유휴시점
- JobService : 실행 조건, 설정가능한 동작 조건.
1. 연결된 네트워크 타입
1. 충전 여부
1. 디바이스 유휴(Idle)여부
1. 콘텐트 프로바이더의 갱신
1. 클립 데이터
1. 실행주기
1. 최소 지연 시간
1. 데드라인 설정
1. 재시도 정책
1. 리부팅 시의 현재 조건 유지 여부
```java
class JobSchedulerSample {
private static final int JOB_ID_UPDATE = 0x1000;
static void setUpdateJob(Context context) {
// 대용량 데이터를 업데이트하기 위한 적정 조건 설정
JobInfo job =
new JobInfo.Builder(
// Job에 설정할 Id 값
JOB_ID_UPDATE,
// 조건 만족 시 UpdateDataByWiFiService가 실행
new ComponentName(this, SyncJobService.class)
)
// 충분한 저장 공간이 있고,
.setRequiresStorageNotLow(true)
// WiFi 등의 비과금 네트워크를 사용 중이며
.setRequiredNetworksCapabilities(JobInfo.NETWORK_TYPE_UNMETERED)
// 충전 중 일 때
.setRequiresCharging(true)
.build();
// JobScheduler 서비스
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
JobScheduler jobScheduler = (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
// Job을 등록한다.
jobScheduler.schedule(job);
}
}
}
```
#### 동작의 처리 - JobService
- 시작 동작
- 종료 동작
- 임의시점 동작 > Jbo의 종료를 요청할 수 있음
#### 동작의 처리 - JobService - Method
- ##### onStartJob : 종료시 지속할 동작 Job 시작 Callback
- "지속" 동작 : return true : AsyncTask나 Thread를 처리기 있을 경우, 경우에따라 jobFinished()로 명시적으로 작업을 종료 가능
```java
@Override
public boolean onStartJob(final JobParameters params) {
mDownloadArtworkTask = new DownloadArtworkTask(this) {
@Override
protected void onPostExecute(Boolean success) {
jobFinished(params, !success); // <<<<<<<<< point
}
};
mDownloadArtworkTask.execute();
return true; // <<<<<<<<<<<<< point
}
```
- "완료" 동작 : return false
- ##### onStopJob()
- 시스템에 의해 호출됨 : 완료전에 작업이 취소 된 경우
- 갑작스러운 중지로 현재 실행하던 Job을 다시 스케줄러에 등록하여, 다음 기회에 실행할 필요가 있다면 setRequiresCharging : return true
- 다시 작업이 스케쥴링되지 않는다. : return false
```java
@Override
public boolean onStopJob(final JobParameters params) {
if (mDownloadArtworkTask != null) {
mDownloadArtworkTask.cancel(true);
}
return true;
}
```
- ##### jobFinished : 완료시 호출해야 ( Override 메소드 아님 )
- JobManager로 하여금 해당 Job을 종료하도록함.
- ##### source
```java
package com.example.android.jobscheduler.service;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
public class SyncJobService extends JobService {
ArtworkDownloader mDownloader;
@Override
public void onCreate() {
super.onCreate();
mDownloader = ArtworkDownloader.getSequencialDownloader();
}
@Override
public boolean onStartJob(final JobParameters params) {
// 신규 Job 수행 조건이 만족되었을 때 호출됩니다.
// onStartJob()의 종료 후에도 지속할 동작이 있다면 true, 여기에서 완료되면 false를 반환합니다.
// true를 반환할 경우 finishJob()의 호출을 통해 작업 종료를 선언하거나,
// 시스템이 필요 onStopJob()를 호출하여 작업을 중지할 수 있습니다.
return mDownloader.hasPendingArtworkDownload();
}
@Override
public boolean onStopJob(JobParameters params) {
// 시스템에서 Job 종료 시 호출되며, 현재 처리 중인 동작들을 중지해야 합니다.
// 갑작스러운 중지로 현재 실행하던 Job을 재실행해야 할 경우 true, 새로 스케쥴링을 할 필요가 없다면 false를 반환합니다.
return !mDownloader.isFinished();
}
}
```
#### JobService에 대한 실행 권한 부여 ( AndroidManifest.xml )
```xml
```
#### 일반적인 고려 사항
- JobService는 기본적으로 메인스레드에서 동작합니다.
- Job의 구분은 id를 통해 이루어집니다.
- Job은 실행 조건을 만족하지 못하는 순간 종료됩니다.
- Job의 실행은 어쨌던 Wakelock을 전제로 합니다.
#### 가장 치명적인 문제는 하위 호환성
- API 레벨 21부터 지원
```java
JobScheduler jobScheduler =(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(new JobInfo.Builder(JOB_ID_UPDATE,
new ComponentName(this, SyncJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build());
```
댓글