반응형

Service

설명

  • 백그라운드 처리를 위해 제공되는 요소
  • 일반 서비스는 메모리 부족해질 경우 OS에 의해 제거된다. 이를 방지하기 위해 Foreground Service가 있다.

코드

manifests/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android_example">

    <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.Androidexample">
        <service
            android:name=".TestService"
            android:enabled="true"
            android:exported="true" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <!-- Entry Point -->
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
TestService
class TestService : Service() {
    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        var builder: NotificationCompat.Builder? = null

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel("test1", "Service", NotificationManager.IMPORTANCE_HIGH)

            channel.enableLights(true)
            channel.lightColor = Color.RED
            channel.enableVibration(true)
            manager.createNotificationChannel(channel)

            builder = NotificationCompat.Builder(this, "test1")
        } else {
            builder = NotificationCompat.Builder(this)
        }

        builder?.setSmallIcon(android.R.drawable.ic_menu_search)
        builder?.setContentTitle("서비스 가동")
        builder?.setContentText("서비스가 가동중입니다.")

        val notification = builder?.build()
        startForeground(10, notification)

        val thread = MyThread()
        thread.start()

        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("TestService", "onDestroy")
    }

    inner class MyThread : Thread() {
        override fun run() {
            var index = 0

            while (index < 3) {
                SystemClock.sleep(2000)
                Log.d("TestService", index.toString())
                index++
            }
        }
    }
}
MainActivity
class MainActivity : AppCompatActivity() {
    private var serviceIntent: Intent? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val startButton = findViewById<Button>(R.id.startButton)
        val stopButton = findViewById<Button>(R.id.stopButton)

        startButton.setOnClickListener {
            serviceIntent = Intent(this, TestService::class.java)

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(serviceIntent)
            } else {
                startService(serviceIntent)
            }
        }

        stopButton.setOnClickListener {
            stopService(serviceIntent)
        }
    }
}

참고

IPC

설명

  • Activity에서 실행 중인 서비스의 데이터를 사용하고자 할 때 사용하는 개념

코드

TestService
class TestService : Service() {
    private var value = 0
    private var thread: Thread? = null
    private val binder: IBinder = LocalBinder()

    override fun onBind(intent: Intent): IBinder {
        return binder
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        thread = MyThread()
        thread?.start()

        return super.onStartCommand(intent, flags, startId)
    }

    inner class LocalBinder : Binder() {
        fun getService(): TestService {
            return this@TestService
        }
    }

    inner class MyThread : Thread() {
        override fun run() {
            while (true) {
                SystemClock.sleep(2000)
                Log.d("TestService", value.toString())
                value++
            }
        }
    }

    fun getValue(): Int {
        return value
    }
}
MainActivity
class MainActivity : AppCompatActivity() {
    private var testService: TestService? = null

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as TestService.LocalBinder
            testService = binder.getService()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            testService = null
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)
        val intent = Intent(this, TestService::class.java)

        if (!isServiceRunning("com.example.android_example.TestService")) {
            startService(intent)
        }

        bindService(intent, connection, Context.BIND_AUTO_CREATE) // BIND_AUTO_CREATE : 서비스가 가동중이 아니면 가동 후 bind 처리

        button.setOnClickListener {
            val value = testService?.getValue()

            Toast.makeText(this, value.toString(), Toast.LENGTH_SHORT).show()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        unbindService(connection)
    }

    private fun isServiceRunning(name: String): Boolean {
        val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

        for (service: ActivityManager.RunningServiceInfo in manager.getRunningServices(Int.MAX_VALUE)) {
            if (service.service.className.equals(name)) {
                return true
            }
        }

        return false
    }
}

참고

반응형

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

[Android] Resources  (0) 2021.02.09
[Android] SQLite  (0) 2021.02.09
[Android] BroadcastReceiver  (0) 2021.02.09
[Android] Thread & Handler  (0) 2021.02.09
[Android] DialogFragment  (0) 2021.02.09

+ Recent posts