240201 TIL #310 Android #23 Service - 2

김춘복·2024년 2월 1일
0

TIL : Today I Learned

목록 보기
310/571

Today I Learned

오늘은 서비스를 이어서 공부했다.


백그라운드 제약

API 26레벨 이후, 백그라운드 작업에 제약이 존재한다.

  • 리시버같은 경우는 매니페스트에 등록한 리시버를 암시적으로 실행할 때, 같은 앱이든 외부 리시버든 실행되지 않는다.

  • 서비스는 앱이 백그라운드 상태일 때, 인텐트를 전달하면 오류가 발생한다.(몇몇 예외상황이 있긴있다)

  • 포그라운드(foreground) 상태 (이외는 다 백그라운드 상태)

  1. 보이는 액티비티가 있을 때
  2. 포그라운드 서비스가 있을 때
  3. 앱의 서비스에 바인딩하거나, 앱의 콘텐츠프로바이더를 이용해 다른 포그라운드 앱이 연결되었을 때
  • startForegroundService()함수로 인텐트를 시작하면 앱이 백그라운드 상태이더라도 서비스가 실행할 수는 있다. 하지만 결국 오류가 발생하므로 서비스를 정상으로 유지할 수는 없다.

  • 따라서 위의 함수가 호출된다면 빨리 startForeground()를 호출해 포그라운드 상황으로 만들라는 의도이다.
    단, 이 함수를 정상적으로 호출하려면 매니페스트에 android.permission.FOREGROUND_SERVICE 퍼미션을 등록해야 한다.

val norification = builder.build()
startForeground(1, notification)

잡 스케줄러

앱이 백그라운드 상황일 때 작업처리에 제약을 덜 받기위해 잡 스케줄러를 이용한다.

실행조건

잡스케줄러는 개발자가 만드는 서비스이므로 어떤 상황에서 실행해야하는지 조건을 명시해줘야 백그라운드에서 작업이 가능하다.

  • 잡 스케줄러에 조건으로 명시할 수 있는 상황
    네트워크 타입 변경 시
    배터리 충전 상태 변경 시
    특정 앱의 콘텐츠 프로바이더 갱신(ex. 갤러리 앱)
    실행 주기
    최소 지연 시간
    시스템 재구동 시 현재 조건 유지 여부

구성요소

1. 잡서비스

백그라운드에서 처리할 작업을 구현한 서비스

  • 매니페스트에 <service> 태그로 등록. (퍼미션 추가로 등록)
        <service
            android:name=".MyJobService"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE"></service>
  • JobService()를 상속받아 onCreate()같은 생명주기 함수를 재정의한다. onStartJob(), onStopJob()은 필수.
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면 잡스케줄러를 재등록 한다. 이 함수는 작업이 정상적으로 처리되지 않았을때 호출된다.


2. 잡 인포

잡서비스의 실행 조건을 정의

  • JobInfo.Builder에 지정한 잡 서비스가 실행되는 조건을 명시한다.
       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): 배터리가 충전 상태인지를 설정


3. 잡 스케줄러

  • 잡서비스를 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()
  • 이렇게 전달한 데이터를 잡서비스에서 가져올땐 onStartJobs() 함수의 매개변수를 이용한다.
    override fun onStartJob(params: JobParameters?): Boolean {
        params.extras.getString("extra_data")
        return false
    }
profile
Backend Dev / Data Engineer

0개의 댓글