1+ package com.ciscowebex.androidsdk.kitchensink
2+
3+ import android.app.Notification
4+ import android.app.NotificationChannel
5+ import android.app.NotificationManager
6+ import android.app.Service
7+ import android.content.BroadcastReceiver
8+ import android.content.Context
9+ import android.content.Intent
10+ import android.os.Build
11+ import android.os.IBinder
12+ import android.util.Log
13+ import androidx.annotation.RequiresApi
14+ import androidx.core.app.NotificationCompat
15+ import com.ciscowebex.androidsdk.kitchensink.utils.CallObjectStorage
16+ import com.ciscowebex.androidsdk.phone.Call
17+ import com.ciscowebex.androidsdk.phone.CallObserver
18+
19+
20+ class CallManagementService : Service () {
21+ private val tag = " CallManagementService"
22+ private var receiver: BroadcastReceiver ? = null
23+
24+ override fun onBind (intent : Intent ? ): IBinder ? {
25+ return null
26+ }
27+
28+ override fun onStartCommand (intent : Intent ? , flags : Int , startId : Int ): Int {
29+ if (isForegroundServiceSupported()) {
30+ startForeground(1 , getNotification())
31+ }
32+ return START_STICKY
33+ }
34+
35+ override fun onTaskRemoved (rootIntent : Intent ? ) {
36+ Log .d(tag, " onTaskRemoved called!" )
37+ super .onTaskRemoved(rootIntent)
38+ val call = getOngoingCall()
39+ if (call != null ) {
40+ endCall(call)
41+ } else {
42+ Log .d(tag, " No call found in connected state. Killing service!" )
43+ stopSelf()
44+ }
45+ }
46+
47+ override fun onDestroy () {
48+ super .onDestroy()
49+ if (receiver != null ) {
50+ unregisterReceiver(receiver)
51+ }
52+ }
53+
54+ @RequiresApi(Build .VERSION_CODES .O )
55+ private fun getNotification (): Notification {
56+ // Create a notification for the foreground service
57+ val channelId = " ks_02"
58+ val notificationChannel =
59+ NotificationChannel (
60+ channelId, " Call Management Service Notifications" ,
61+ NotificationManager .IMPORTANCE_MIN
62+ )
63+ notificationChannel.enableLights(false )
64+ notificationChannel.lockscreenVisibility = Notification .VISIBILITY_SECRET
65+ val mNotificationManager = getSystemService(Context .NOTIFICATION_SERVICE ) as NotificationManager
66+ mNotificationManager.createNotificationChannel(notificationChannel)
67+
68+ val title = getString(R .string.call_management_service_notification_title)
69+ return NotificationCompat .Builder (
70+ this ,
71+ channelId
72+ ).setSmallIcon(R .drawable.app_notification_icon)
73+ .setWhen(0 )
74+ .setContentTitle(title)
75+ .setOngoing(true )
76+ .build()
77+ }
78+
79+ private fun getOngoingCall (): Call ? {
80+ var call: Call ? = null
81+
82+ for (i in 0 until CallObjectStorage .size()) {
83+ val callObj = CallObjectStorage .getCallObjectFromIndex(i)
84+ val status = callObj?.getStatus()
85+ if (status == Call .CallStatus .CONNECTED || status == Call .CallStatus .RINGING
86+ || status == Call .CallStatus .WAITING || status == Call .CallStatus .INITIATED ) {
87+ Log .d(tag, " Call with id = ${callObj.getCallId()} found in ${status.name} state. " )
88+ call = callObj
89+ break
90+ }
91+ }
92+ return call
93+ }
94+
95+ private fun endCall (call : Call ) {
96+ Log .d(tag, " Ending call with id = ${call.getCallId()} " )
97+ call.setObserver(object : CallObserver {
98+ override fun onDisconnected (event : CallObserver .CallDisconnectedEvent ? ) {
99+ Log .d(tag, " Call disconnected fired, stopping callManagementService!" )
100+ stopSelf()
101+ }
102+
103+ })
104+ if (call.getDirection() == Call .Direction .INCOMING && call.getStatus() == Call .CallStatus .RINGING ) {
105+ call.reject {
106+ if (it.isSuccessful) {
107+ Log .d(tag, " Call rejected successfully. Waiting for call disconnected event" )
108+ } else {
109+ Log .e(tag, " Call reject failed, reason : ${it.error?.errorMessage} " )
110+ stopSelf()
111+ }
112+ }
113+ } else {
114+ call.hangup { result ->
115+ if (result.isSuccessful) {
116+ Log .d(tag, " Call hung up success. Waiting for call disconnected event" )
117+ } else {
118+ Log .e(tag, " Call hangup failed, reason : ${result.error?.errorMessage} " )
119+ stopSelf()
120+ }
121+ }
122+ }
123+
124+ }
125+
126+ private fun isForegroundServiceSupported (): Boolean {
127+ return (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O )
128+ }
129+ }
0 commit comments