ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Android JobSchduler
    Android/Component 2019. 7. 25. 17:04

    JobSchduler는 Job(특정 업무)를 시스템에 등록시켜 실행시키는 방법이다.

    Network, Battery 조건 등을 등록하고 이 조건에 맞았을 때 Background 업무를 실행시키기 위한 목적으로 사용한다


    해당 기능은 API Level 21 부터 제공이 되었고, background 실행 제한이 강화되기 시작하면서 필요성 증가되었다.

     

    두 가지의 클래스를 사용하는데 아래와 같다.
    JobInfo : Job 이 실행될 조건 및 조건이 맞을 떄 실행시킨 JobService 정보
    JobScheduler : JobInfo를 시스템에 등록시키는 역할


    1. JobSchedulerService 클래스 생성하기

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    class MyJobSchedulerService : JobService() {
        override fun onCreate() {
            super.onCreate()
            "onCreate".log()
        }
    
        override fun onStartJob(params: JobParameters?): Boolean {
            "onStartJob".log()
            return true
        }
    
        override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
            val extra = intent.extras
            extra["extra_data"].log()
            return super.onStartCommand(intent, flags, startId)
        }
    
        override fun onStopJob(params: JobParameters?): Boolean {
            "onStopJob".log()
            return true
        }
    
        override fun onDestroy() {
            super.onDestroy()
            "onDestroy".log()
        }
    }
    

    어라? JobService는 Service를 상속 받았는데 Service도 onStartCommand를 구현할 수 있나요?

    네! Service도 onStartCommand는 정의할 수 있지만 호출 되지는 않는다.


    2. AndroidMenifest에 등록하기

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="kr.co.s1.myapplication">
    
        <application
                android:allowBackup="true"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <service android:name=".MyJobSchedulerService"
                     android:enabled="true"
                     android:exported="true"
                     android:permission="android.permission.BIND_JOB_SERVICE"/>
        </application>
    
    </manifest>

    3. JobSchduler 등록하기

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
            val componentName = ComponentName(this, MyJobSchedulerService::class.java)
    
            val extra = PersistableBundle()
            extra.putString("extra_data", "DongHun")
    
            val builder = JobInfo.Builder(1, componentName)
            builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
            builder.setRequiresCharging(true)
            builder.setExtras(extra)
    
            val jobInfo = builder.build()
            jobScheduler.schedule(jobInfo)
    
        }
    }

    getSystemService를 통해 JobSchduler를 가져와 주고 앞서 만든 MyJobSchedulerService를 생성해줍니다.

    필요에 따라 Extra데이터를 놓어주고 JobInfo를 생성해 저희만의 특별한 이벤트를 생성해줍니다.

     

    setRequiredNetworkType = 작동할 네트워크 타입을 설정합니다.

    setRequiresCharging = 작동할 충전 상태를 설정합니다.

     

    저는 네트워크가 끊어졌고 충전 중인 상태에서 서비스가 발동하도록 설정하고 엑스트라 값을 넣어준뒤

    해당 스케쥴러를 실행시켜 줍니다.

     

    테스트는 백그라운드에서 돌아야 함으로 앱을 실행 후 죽여준뒤 충전중인 상태에서 네트워크를 끊으면

    onCreate -> onStartJob -> onStartCommand

     

    다시 네트워크를 연결하면 onStopJob -> onDestroy를 실행하게 됩니다.


    4. 결과

    D: onCreate
    D: onStartJob
    D: DongHun
    D: onStopJob
    D: onDestroy
    

    여기서 하나 궁금한거는 JobService에 onStartJob과 onStopJob에 리턴값이 Boolean이라는 거다

     

    먼저 OnStartJob의 경우는 아래의 정리와 같다.

     

    onStartJob의 리턴 값을 false로 설정하는 경우에는 Job이 완벽하게 종료되었음을 명시적으로 시스템에게 알려준다.

     

    onStartJob의 리턴 값을 true로 설정하는 경우는 시스템에 job이 아직 끝나지 않았음을 명시적으로 선언 한다.

    이는 job 의 실행과 관련된 것을 제어하고 싶을때이다.


    보통의 경우 Thread를 수행시켜 장시간 수행하는 업무가 있는 경우 true로 설정하게 된다.
    onStartJob() 의 리턴이 true 이면 onCreate -> onStartJob() 까지 호출되고 더 이상 onDestroy() 등이 호출되지 않는다.

     

    true 가 리턴이 된 경우 특이 상황에 의해 Job이 취소가 되면 onStopJob() 함수가 호출이 되고 작업을 멈추게 된다.
    - 다른 곳에서 cancel 함수를 이용하여 취소 시키거나

    - 차징 조건으로 Job 이 실행되었는데 갑자기 베터리 차징이 안되는 경우 등


    onStartJob 함수에서 true를 리턴하고 쓰레드가 수행되다 jobFinish()를 호출한 경우 onStopJob 함수는 호출되지 않는다.
    onStartJob이 true를 리턴시켰지만 true 의해 thread 종료까지 Service가 대기 상태가 된다.

    onStopJob 함수가 호출이 안된거는 jobFinish() 함수가 job이 모두 끝났음을 명시적으로 선언하는 것이기 때문이다.

    만약 onStart 함수가 true를 리턴하고 외부에서 cancel을 하거나 Job 등록 조건이 바뀌게 되면 onStopJob 함수가 호출되게 된다.


    onStopJob 함수의 리턴 값의 경우는
    리턴값이 false이면 시스템에 이 job을 취소 시키는 것이고

    리턴값이 true이면 다시 스케줄을 등록시키는 역할을 하게 된다.

    'Android > Component' 카테고리의 다른 글

    Android Notification  (0) 2019.07.25
    Android Background Limits  (0) 2019.07.25
    Android Component - Service  (0) 2019.07.24
    Android Component - Broadcast Service  (0) 2019.07.24

    댓글

Designed by Tistory.