Android App/Kotlin
4대 컴포넌트-서비스 실행(포어그라운드 서비스)
AppJinny
2022. 12. 2. 23:36
*4대 컴포넌트-서비스 실행(포어그라운드 서비스)
*Foreground Service(포어그라운드 서비스)
-사용자에게 알림을 통해 현재 작업이 진행 중이라는 것을 알려줌
-사용자가 알림을 통해 서비스가 동작하고 있다는 것을 인지하여 가용 자원 부족과 같은 이유로는 종료되지 않음
-서비스를 먼저 생성 후 시스템에 포어그라운드로 사용된다는 것을 알려줘야 함
-실행구조를 기준으로 포어그라운드와 백그라운드 서비스로 분류
-기본적으로 서비스는 모두 백그라운드 서비스(화면에 나타나지 않는 서비스를 뜻함 : 스타티드서비스, 바운드서비스)
-포어그라운드 서비스 3단계
--포어그라운드 서비스 권한 명세
--서비스의 선행
--서비스 안에서 startForeground() 메서드 호출하여 서비스가 포어그라운드로 실행되고 있음을 안드로이드에게 알림
*포어그라운드 서비스 실행
-build.gradle
-- android{} 에 뷰바인딩 추가
//뷰바인딩
buildFeatures{
viewBinding true
}
-MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.content.ContextCompat
import com.heeyjinny.foregroundservice.databinding.ActivityMainBinding
//1
//포어그라운드 서비스를 사용하기 위해
//AndroidManifest.xml 포어그라운드 권한 추가
//2
//app - java 패키지명 우클릭 - New - Service - Service
//Foreground.kt 생성
class MainActivity : AppCompatActivity() {
//뷰바인딩
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
//3
//시작버튼 클릭 시 서비스 시작코드 작성
binding.buttonStart.setOnClickListener {
//3-1
//인텐트 생성
val intent = Intent(this, Foreground::class.java)
//3-2
//포어그라운드 서비스 실행 메서드 작성
//startService()가 아닌
//ContextCompat.startForegroundService()사용
ContextCompat.startForegroundService(this, intent)
}
//4
//종료버튼 클릭 시 서비스 종료코드 작성
binding.buttonStop.setOnClickListener {
//4-1
//인텐트 생성하고 종료 메서드 작성하여 인텐트 전달
val intent = Intent(this, Foreground::class.java)
stopService(intent)
}
//5
//에뮬레이터 실행 후 확인
//상단에 아이콘이 떠있고 알림창 생성됨
//포어그라운드는 사용자에게 현재 서비스가 실행 중임을 항상 알려줘야 함
//실행한 액티비티를 강제 종료해도 서비스가 실행되기 때문에 알림이 사라지지 않음
}//onCreate
}//MainActivity
-AndroidManifest.xml
--<manifest/>태그에 포어그라운드 서비스 권한 추가
<!-- 포어그라운드 서비스 권한 추가 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
-Foreground.kt
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
class Foreground : Service() {
//2
//포어그라운드 서비스를 사용하기 위해서는 상태바에 알림을 띄워야함
//이 알림이 사용할 채널을 설정할 때 사용하는 상수 정의
val CHANNEL_ID = "ForegroundChannel"
override fun onBind(intent: Intent): IBinder {
//1
//오류를 막기위해 비어있는 바인더 리턴
return Binder()
}//onBind
//3
//포어그라운드 서비스에 사용할 알림 실행 전
//알림채널을 생성하는 메서드 생성
//모든 알림은 채널 단위로 동작하도록 설계되어 있음
fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val serviceChannel = NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(serviceChannel)
}
}
//4
//onStartCommand()메서드 오버라이드
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
//4-1
//앞에서 만들어둔 메서드를 호출해 알림채널 생성
createNotificationChannel()
//4-2
//알림 생성: 알림제목, 알림 아이콘 설정
val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setSmallIcon(R.mipmap.ic_launcher_round)
.build()
//4-3
//알림 실행 메서드 사용
startForeground(1, notification)
return super.onStartCommand(intent, flags, startId)
}
//5
//서비스 실행할 버튼 배치
//activity_main.xml 에서 버튼 생성
}//Foreground
-activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- 서비스 시작, 종료 버튼 생성 -->
<Button
android:id="@+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="서비스 시작"
app:layout_constraintEnd_toStartOf="@+id/buttonStop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="서비스 종료"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/buttonStart"
app:layout_constraintTop_toTopOf="parent" />
<!-- 액티비티에서 서비스를 호출하기 위해 -->
<!-- MainActivity.kt 작성 -->
</androidx.constraintlayout.widget.ConstraintLayout>
-결과
이 포스팅에 작성한 내용은 고돈호, ⌜이것이 안드로이드다⌟, 한빛미디어(주), 2022 에서 발췌하였습니다.