Skip to content

Commit c516a54

Browse files
committed
service code added
1 parent ad10b0a commit c516a54

8 files changed

Lines changed: 210 additions & 0 deletions

service/AndroidManifest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!-- some AndroidManifest body -->
2+
3+
<!-- don't declare intent filters, use explicit intent to start -->
4+
<!-- enabled - can be instantiated by the system, exported - is available for other apps -->
5+
<service
6+
android:name=".CustomService"
7+
android:enabled="true"
8+
android:exported="false"/>

service/BackgroundActivity.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class BackgroundActivity : AppCompatActivity() {
2+
3+
override fun onCreate(savedInstanceState: Bundle?) {
4+
super.onCreate(savedInstanceState)
5+
6+
val intent = Intent(this, BackgroundService::class.java)
7+
intent.putExtra("PARAM", "value")
8+
startService(intent)
9+
}
10+
11+
override fun onStop() {
12+
super.onStop()
13+
stopService(Intent(this, BackgroundService::class.java))
14+
}
15+
}

service/BackgroundService.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class BackgroundService : Service() {
2+
3+
override fun onBind(intent: Intent?): IBinder? {
4+
return null
5+
}
6+
7+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
8+
if(intent != null && intent.hasExtra("PARAM")) {
9+
val data = intent.getStringExtra("PARAM")
10+
//do something based on param
11+
action()
12+
}
13+
return START_STICKY
14+
}
15+
16+
override fun onDestroy() {
17+
//will destroy on Android Oreo and above if app close
18+
super.onDestroy()
19+
}
20+
21+
private fun action() {
22+
//some work
23+
24+
//inform about finish by Toast
25+
Toast.makeText(this, "Some message", Toast.LENGTH_LONG).show()
26+
27+
//after that service is no longer need, so destroy manual
28+
stopSelf()
29+
}
30+
}

service/BoundActivity.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class BoundActivity : AppCompatActivity() {
2+
3+
private var service : CustomService? = null
4+
private var isBound = false
5+
6+
private val connection = object: ServiceConnection {
7+
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
8+
val binder = service as CustomService.CustomBinder
9+
this@MainActivity.service = binder.getService()
10+
isBound = true
11+
}
12+
override fun onServiceDisconnected(name: ComponentName?) {
13+
isBound = false
14+
}
15+
}
16+
17+
override fun onCreate(savedInstanceState: Bundle?) {
18+
super.onCreate(savedInstanceState)
19+
20+
val intent = Intent(this, CustomService::class.java)
21+
intent.putExtra("PARAM", "value")
22+
bindService(intent, connection, Context.BIND_AUTO_CREATE)
23+
24+
//use service binder action to communicate
25+
button.setOnClickListener { service?.action() }
26+
}
27+
28+
override fun onStop() {
29+
super.onStop()
30+
unbindService(connection)
31+
isBound = false
32+
}
33+
}

service/BoundService.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class BoundService : Service() {
2+
3+
inner class CustomBinder : Binder() {
4+
fun getService() : CustomService = this@CustomService
5+
//allow to call public methods
6+
}
7+
8+
private val binder = CustomBinder()
9+
10+
override fun onBind(intent: Intent?): IBinder? {
11+
return binder
12+
}
13+
14+
override fun onUnbind(intent: Intent?): Boolean {
15+
//called when all clients disconnect, return true to allow call onRebind
16+
return super.onUnbind(intent)
17+
}
18+
19+
override fun onRebind(intent: Intent?) {
20+
//called when new client connect after all had disconnected
21+
super.onRebind(intent)
22+
}
23+
24+
//can be used by Binder
25+
fun action() {
26+
//some work
27+
}
28+
}

service/CustomService.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
class CustomService : Service() {
2+
3+
//use worker thread if long running operation to not block main UI thread
4+
//or provide some multithreading if needed
5+
private val handlerThread = HandlerThread("HandlerThread")
6+
private lateinit var handler : Handler
7+
8+
override fun onBind(intent: Intent?): IBinder? {
9+
//invokes when bindService called, retrieve intent and decide what to do
10+
//if service is created by bindService and onStartCommand wasn't called then runs only as components are bound
11+
12+
return null //provide communication interface or return null when no bind needed
13+
}
14+
15+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
16+
//invokes when startService or startForegroundService called, retrieve intent and decide what to do
17+
//continues to run until stops itself or by another component
18+
19+
return START_STICKY //restart service strategy after destroyed by the system
20+
}
21+
22+
override fun onCreate() {
23+
//invokes one time setup before onStartCommand or onBind
24+
//not called when service already running
25+
super.onCreate()
26+
handlerThread.start()
27+
handler = Handler(handlerThread.looper)
28+
}
29+
30+
override fun onDestroy() {
31+
//invokes when stopSelf or stopService is called
32+
//service is no longer used or is being destroyed by system or client
33+
super.onDestroy()
34+
handler.removeCallbacksAndMessages(null)
35+
handlerThread.quitSafely()
36+
handlerThread.interrupt()
37+
}
38+
39+
//more lifecycle callbacks
40+
}
41+
42+
//run startService or bindService and pass Intent to run Service

service/ForegroundActivity.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class ForegroundActivity : AppCompatActivity() {
2+
3+
override fun onCreate(savedInstanceState: Bundle?) {
4+
super.onCreate(savedInstanceState)
5+
6+
val intent = Intent(this, ForegroundService::class.java)
7+
intent.putExtra("PARAM", "value")
8+
9+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
10+
//background restriction for Android Oreo and above
11+
startForegroundService(intent)
12+
}
13+
else {
14+
//just start as normal
15+
startService(intent)
16+
}
17+
18+
//remove from foreground by calling stopForeground
19+
}
20+
}

service/ForegroundService.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class ForegroundService : Service() {
2+
3+
override fun onBind(intent: Intent?): IBinder? {
4+
return null
5+
}
6+
7+
override fun onCreate() {
8+
super.onCreate()
9+
10+
//must run service in foreground immediately by show notification
11+
showNotification()
12+
//notification can't be dismissed unless the service is stopped or removed from foreground
13+
}
14+
15+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
16+
//do some action
17+
return START_STICKY
18+
}
19+
20+
private fun showNotification() {
21+
//create NotificationChannel if not exists for Android Oreo and above
22+
val channelId = "channel_id"
23+
24+
//customize notification
25+
val notification = NotificationCompat.Builder(this, channelId)
26+
.setOngoing(true)
27+
.setSmallIcon(R.mipmap.ic_launcher)
28+
.setContentTitle("title")
29+
.build()
30+
31+
//start service in foreground
32+
startForeground(100, notification)
33+
}
34+
}

0 commit comments

Comments
 (0)