ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AOS] ForegroundService
    2022. 11. 15. 13:21
    λ°˜μ‘ν˜•

     

     

    🐱
    μ˜€μ†Œλ¦¬λ‹˜, 앱이 μ‹€ν–‰λ˜μ–΄ μžˆλŠ” λ™μ•ˆ μ„œλΉ„μŠ€λ„ 같이 μœ μ§€λ˜λ„λ‘ κ΅¬ν˜„ν•΄μ£Όμ„Έμš”.
    (ν›—.. κ»Œμ΄μ§€γ…‹) λ„΅ 😁
    🐢

     

     

     

     

    s..t..a..r..t...Service...()..@#$%

     

     

    🐱
    μ˜€μ†Œλ¦¬λ‹˜... 앱이 λ°±κ·ΈλΌμš΄λ“œλ‘œ λ“€μ–΄κ°€λ©΄ μ„œλΉ„μŠ€κ°€ 1λΆ„ 뒀에 μ£½λŠ”λ°μš”...?
    예...⁉️⁉️
    🐢

     

     

     

     


     

     

    μ„œλΉ„μŠ€ (Service)

    Declares a service (a Service subclass) as one of the application's components. Unlike activities, services lack a visual user interface. They're used to implement long-running background operations or a rich communications API that can be called by other applications.

    All services must be represented by <service> elements in the manifest file. Any that are not declared there will not be seen by the system and will never be run.

     

    A Service is an application component that can perform long-running operations in the background. It does not provide a user interface. Once started, a service might continue running for some time, even after the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service can handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

     

    κ³΅μ‹λ¬Έμ„œ1   κ³΅μ‹λ¬Έμ„œ2

     

     

    μ•ˆλ“œλ‘œμ΄λ“œμ˜ μ„œλΉ„μŠ€λŠ” activity와 달리 μ‚¬μš©μž μΈν„°νŽ˜μ΄μŠ€ 없이 λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ‹€ν–‰λ˜λŠ” κΈ°λŠ₯을 λ§ν•œλ‹€.

    μ„œλΉ„μŠ€λŠ” AndroidManifest.xml νŒŒμΌμ— μ„ μ–Έ ν›„ μ‚¬μš©ν•  수 μžˆλ‹€.

    μ„œλΉ„μŠ€μ—λŠ” μ„Έ 가지 μœ ν˜•μ΄ μžˆμœΌλ―€λ‘œ ν•„μš”ν•œ μœ ν˜•μ„ 선택 ν›„ κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.

     

     

    ν¬κ·ΈλΌμš΄λ“œ μ„œλΉ„μŠ€ (Foreground Service)

    ν¬κ·ΈλΌμš΄λ“œ μ„œλΉ„μŠ€λŠ” μ‚¬μš©μžμ—κ²Œ λ³΄μ΄λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

    μ•±κ³Ό μƒν˜Έμž‘μš©ν•˜μ§€ μ•Šμ„  λ•Œμ—λ„ 계속 μ‹€ν–‰λ˜λ―€λ‘œ μ‚¬μš©μžμ—κ²Œ μˆ˜ν–‰ μ€‘μž„μ„ μ•Œλ¦¬λŠ” μ•Œλ¦Όμ„ ν‘œμ‹œν•΄μ•Ό ν•œλ‹€.

     

    ex. μ˜€λ””μ˜€ μž¬μƒ μ‹œ μ•Œλ¦Όλ°”μ— λ³΄μ—¬μ§€λŠ” νŠΈλž™ λ°” / 만보기 걸음 수 μΈ‘μ • μ•Œλ¦Ό

     

    λ°±κ·ΈλΌμš΄λ“œ μ„œλΉ„μŠ€ (Background Service)

    λ°±κ·ΈλΌμš΄λ“œ μ„œλΉ„μŠ€λŠ” μ‚¬μš©μžμ—κ²Œ 직접 보이지 μ•ŠλŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€. μ‚¬μš©μžκ°€ μ•±κ³Ό μƒν˜Έμž‘μš©ν•˜μ§€ μ•ŠμœΌλ©΄ μ„œλΉ„μŠ€ 싀행이 μ œν•œλœλ‹€.

     

    ex. 파일 λ˜λŠ” κ²Œμ‹œκΈ€ μ—…λ‘œλ“œ

     

    λ°”μΈλ“œ μ„œλΉ„μŠ€ (Bind Service)

    λ°”μΈλ”©λœ μ„œλΉ„μŠ€λŠ” ν΄λΌμ΄μ–ΈνŠΈ-μ„œλ²„ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•˜μ—¬ ꡬ성 μš”μ†Œκ°€ μ„œλΉ„μŠ€μ™€ μƒν˜Έμž‘μš©ν•˜κ²Œ ν•˜λ©°, κ²°κ³Όλ₯Ό 받을 μˆ˜λ„ 있고 심지어 이와 같은 μž‘μ—…μ„ μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€μ— 걸쳐 ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신(IPC)으둜 μˆ˜ν–‰ν•  μˆ˜λ„ μžˆλ‹€.

    λ°”μΈλ”©λœ μ„œλΉ„μŠ€λŠ” 또 λ‹€λ₯Έ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ꡬ성 μš”μ†Œκ°€ 이에 λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” κ²½μš°μ—λ§Œ μ‹€ν–‰λœλ‹€.

    μ—¬λŸ¬ 개의 ꡬ성 μš”μ†Œκ°€ μ„œλΉ„μŠ€μ— ν•œκΊΌλ²ˆμ— 바인딩될 수 μžˆμ§€λ§Œ, 이 λͺ¨λ“  κ²ƒμ—μ„œ 바인딩이 ν•΄μ œλ˜λ©΄ ν•΄λ‹Ή μ„œλΉ„μŠ€λŠ” μ†Œλ©Έλœλ‹€.

     

     

    이 쀑 μ‚¬μš©μžκ°€ μ•±κ³Ό μƒν˜Έμž‘μš©ν•˜μ§€ μ•Šμ„ λ•Œμ—λ„ μ„œλΉ„μŠ€κ°€ μ‹€ν–‰λ˜μ–΄μ•Ό ν•˜λ―€λ‘œ Foreground Service κ΅¬ν˜„μ„ ν•˜λ € ν•œλ‹€.

     

     

     

    Foreground Service κ΅¬ν˜„ν•˜κΈ°

     

    πŸ’‘ Android 9 (API 28) 미만의 앱은 startService() λ§ŒμœΌλ‘œλ„ μΆ©λΆ„νžˆ Foreground Serviceλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.
    ν•˜μ§€λ§Œ Android 9 이상 λ ˆλ²¨μ„ νƒ€κΉƒμœΌλ‘œ ν•˜λŠ” 앱은 notification이 ν•„μˆ˜μ μ΄λ©° startForegroundService()λ₯Ό μ΄μš©ν•΄ Foreground Serviceλ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.

     

     

    1. AndroidManifest.xml νŒŒμΌμ— permission μ‚½μž…

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

     

    μ‹œμŠ€ν…œμ΄ μžλ™μœΌλ‘œ κΆŒν•œμ„ λΆ€μ—¬ν•˜κΈ° λ•Œλ¬Έμ— μΆ”κ°€ μ²˜λ¦¬λŠ” ν•„μš”ν•˜μ§€ μ•Šλ‹€.

     

     

    2. AndroidManifest.xml νŒŒμΌμ— Service μΆ”κ°€

    <service android:name="μ„œλΉ„μŠ€λͺ…"
    	android:stopWithTask="false" />

     

     

    3. Service 클래슀 생성

    class ServiceTask: Service() {
    
        override fun onBind(p0: Intent?): IBinder? {
           return null
        }
    
        override fun onCreate() {
            super.onCreate()
    
            startForegroundService()
        }
        
        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            return START_STICKY
        }
        
        private fun startForegroundService() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
                var channel = NotificationChannel("Notification channel id", "Notification channel name", NotificationManager.IMPORTANCE_DEFAULT)
                channel.setShowBadge(false)
                notificationManager.createNotificationChannel(channel)
    
                var notification: Notification? = NotificationCompat.Builder(this, channel.id).apply {
                    setContentTitle("Foreground Service")
                    setContentText("Foreground Serviceκ°€ ꡬ동 μ€‘μž…λ‹ˆλ‹€.")
                    setSmallIcon(R.drawable.ic_service)
                }.build()
    
                startForeground(NOTIFICATION_ID, notification)
            }
        }
    
        override fun onTaskRemoved(rootIntent: Intent?) {
            super.onTaskRemoved(rootIntent)
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                stopForeground(true)
            }
    
            stopSelf()
        }
        
    }

     

    startForegroundService() ν•¨μˆ˜μ˜ Notification 생성은 ν•„μˆ˜μ μ΄λ‹€.

    λ˜ν•œ ν•΄λ‹Ή ν•¨μˆ˜ ν•˜λ‹¨μ˜ startForeground() ν•¨μˆ˜λ₯Ό 싀행해주지 μ•ŠμœΌλ©΄ 앱이 λ°±κ·ΈλΌμš΄λ“œ μƒνƒœμΌ λ•Œ 1λΆ„ ν›„ μ„œλΉ„μŠ€κ°€ μ†Œλ©Έλ˜λ―€λ‘œ κΌ­ μ‹€ν–‰ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

     

    onStartCommand의 λ°˜ν™˜κ°’μ˜ μ’…λ₯˜λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

     

    - START_NOT_STICKY : μ„œλΉ„μŠ€ 비정상 μ’…λ£Œ μ‹œ μ„œλΉ„μŠ€λ₯Ό λͺ…μ‹œμ μœΌλ‘œ λ‹€μ‹œ μ‹œμž‘ν•  λ•Œ κΉŒμ§€ μ‹€ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€.

    - START_STICKY : μ„œλΉ„μŠ€κ°€ 비정상 μ’…λ£Œ μ‹œ μ„œλΉ„μŠ€λ₯Ό λ‹€μ‹œ μ‹€ν–‰ν•˜μ§€λ§Œ λ§ˆμ§€λ§‰ Intentλ₯Ό onStartCommand의 인자둜 λ‹€μ‹œ μ „λ‹¬ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λŠ” 일단 μ„œλΉ„μŠ€κ°€ 계속 μ‚΄μ•„μžˆμ–΄μ•Όν•˜μ§€λ§Œ 별닀λ₯Έ λ™μž‘μ΄ ν•„μš”ν•˜μ§€ μ•Šμ€ μ•± μ„œλΉ„μŠ€μ— μ ν•©ν•˜λ‹€.

    - START_REDELIVER_INTENT : λ§ˆμ§€λ§‰ Intentλ₯Ό onStartCommand의 인자둜 λ‹€μ‹œ 전달해쀀닀. 즉각적인 λ°˜μ‘μ΄ ν•„μš”ν•œ μ„œλΉ„μŠ€μ— μ ν•©ν•˜λ‹€.

     

    κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” μ„œλΉ„μŠ€μ— λ§žμΆ”μ–΄ μ„€μ •ν•΄μ£Όλ©΄ λœλ‹€.

     

     

    4. Activity μ•ˆμ— Service 채택

    private lateinit var serviceIntent: Intent
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        serviceIntent = Intent(this, ServiceTask::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(serviceIntent)
        } else {
            startService(serviceIntent)
        }
        ...
    }

     

     

     

    앱이 μ’…λ£Œλ˜κΈ° μ „κΉŒμ§€ μ’…λ£Œλ˜μ§€ μ•ŠλŠ” μ„œλΉ„μŠ€ κ΅¬ν˜„ μ™„.

     

     

     

     

    λ°˜μ‘ν˜•

    λŒ“κΈ€

Designed by Tistory.