서비스는 백그라운드에서 동작하는 작업을 수행한다. 따라서 서비스를 실행한 앱을 종료하더라도
서비스에서 시작한 작업은 백그라운드에서 계속 실행된다.
백그라운드 서비스 : 사용자에게 보이지 않는 백그라운드에서 작업을 수행한다. (시스템 리소스 부족시 강제종료)
포그라운드 서비스 : 알림창에 서비스가 실행중인 것을 표시해준다. (시스템에 의해 강제종료 되지 않음)
바인드 서비스 : 서비스와 서비스를 호출하는 앱 구성요소가 서버-클라이언트와 같은 형태로 상호작용
이번 예제에서는 백그라운드 서비스를 다루어 보도록 하겠습니다.
<?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/start_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="서비스 시작"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.282"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.33" />
<Button
android:id="@+id/stop_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="서비스 중지"
app:layout_constraintBottom_toBottomOf="@+id/start_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/start_btn"
app:layout_constraintTop_toTopOf="@+id/start_btn" />
</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {
private val startBtn by lazy {findViewById<Button>(R.id.start_btn)}
private val stopBtn by lazy {findViewById<Button>(R.id.stop_btn)}
private val serviceIntent by lazy { Intent(this, MyService::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//서비스 시작 버튼 클릭시 호출
startBtn.setOnClickListener {
//Intent 값 넘겨주기
serviceIntent.putExtra("Number", 1000)
//startService 호출시 MyService 클래스의 onStartCommand 가 자동으로 호출된다.
startService(serviceIntent)
}
//서비스중지 버튼 클릭시 호출
stopBtn.setOnClickListener {
//stopService 호출시 MyService 클래스의 onDestroy 가 자동으로 호출된다.
stopService(serviceIntent)
}
}
//Activity 종료시 stopService 가 호출되므로 MyService 클래스의 onDestroy 가 자동으로 호출된다.
override fun onDestroy() {
stopService(serviceIntent)
super.onDestroy()
}
}
class MyService : Service() {
var isRunning = false
override fun onBind(intent: Intent): IBinder? {
return null
}
// startService 호출시 자동으로 호출되는 메소드
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
//MainActivity startBtn 클릭시 넘어온 Intent 값 추출
Log.d("onStartCommand", intent?.getIntExtra("Number",0).toString())
//Thread 실행을 위해 isRunning 값을 true로 변경
isRunning = true
//람다식 형태로 Thread 호출
Thread{
var i = 0
while (isRunning){
Log.d("onStartCommand", "$i")
i++
//Thread 1초 지연시키기
Thread.sleep(1000)
}
}.start() //Thread 시작메소드
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
Log.d("onStartCommand", "서비스 종료")
//백그라운드 작업(thread)을 종료 시키기 위해 isRunning 값을 false로 변경
isRunning = false
super.onDestroy()
}
}
<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/Theme.Review">
<!--Service 추가시 Manifest 등록을 해야함-->
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>