1- package coredevices.ring.service
1+ package coredevices.coreapp
22
3- import android.Manifest
43import android.app.NotificationManager
5- import android.app.PendingIntent
64import android.app.Service
75import android.content.Intent
8- import android.content.pm.PackageManager
96import android.content.pm.ServiceInfo
107import android.os.Build
118import android.os.IBinder
12- import androidx.core.app.ActivityCompat
139import androidx.core.app.NotificationChannelCompat
1410import androidx.core.app.NotificationCompat
1511import androidx.core.app.NotificationManagerCompat
1612import androidx.core.app.ServiceCompat
1713import co.touchlab.kermit.Logger
1814import coredevices.haversine.KMPHaversineSatelliteManager
15+ import coredevices.ring.database.Preferences
16+ import coredevices.ring.service.IndexNotificationManager
17+ import coredevices.ring.service.PEBBLE_DEBUG_NOTIFICATION_CHANNEL_ID
18+ import coredevices.ring.service.PEBBLE_DEBUG_NOTIFICATION_CHANNEL_NAME
19+ import coredevices.ring.service.RecordingBackgroundScope
20+ import coredevices.ring.service.RingSync
1921import coredevices.ring.service.recordings.RecordingProcessingQueue
22+ import coredevices.util.R
23+ import kotlinx.coroutines.GlobalScope
2024import kotlinx.coroutines.Job
2125import kotlinx.coroutines.cancel
2226import kotlinx.coroutines.cancelAndJoin
27+ import kotlinx.coroutines.flow.distinctUntilChanged
28+ import kotlinx.coroutines.flow.launchIn
29+ import kotlinx.coroutines.flow.map
30+ import kotlinx.coroutines.flow.onEach
2331import kotlinx.coroutines.launch
2432import kotlinx.coroutines.runBlocking
2533import org.koin.core.component.KoinComponent
2634import org.koin.core.component.inject
2735
28- class RingService : Service (), KoinComponent {
36+ class PebbleService : Service (), KoinComponent {
2937 companion object {
30- const val NOTIFICATION_CHANNEL_ID = " ring"
31- const val DEBUG_NOTIFICATION_CHANNEL_ID = " ring_debug"
32- const val NOTIFICATION_CHANNEL_NAME = " Ring Service"
33- const val DEBUG_NOTIFICATION_CHANNEL_NAME = " Ring Debug"
38+ const val NOTIFICATION_CHANNEL_ID = " pebble"
39+ const val NOTIFICATION_CHANNEL_NAME = " Pebble Service"
3440 const val ACTION_STOP = " STOP"
3541
36- private val logger = Logger .withTag(" RingService " )
42+ private val logger = Logger .withTag(" PebbleService " )
3743 }
3844
3945 private val satelliteManager: KMPHaversineSatelliteManager by inject()
@@ -42,10 +48,12 @@ class RingService: Service(), KoinComponent {
4248 private var recordingDebugNotificationJob: Job ? = null
4349 private var ringSyncJob: Job ? = null
4450 private val ringSync: RingSync by inject()
45- private val ringBackgroundManager : RingBackgroundManager by inject()
51+ private val pebbleBackgroundManager : PebbleBackgroundManager by inject()
4652 private val indexNotificationManager: IndexNotificationManager by inject()
4753 private val recordingProcessingQueue: RecordingProcessingQueue by inject()
48- private var firstRun: Boolean = true
54+ private val commonPrefs: Preferences by inject()
55+ private var ringObserverJob: Job ? = null
56+ private var firstRingRun: Boolean = true
4957
5058 private fun handleIntent (intent : Intent ) {
5159 when (intent.action) {
@@ -60,9 +68,9 @@ class RingService: Service(), KoinComponent {
6068 recordingDebugNotificationJob?.cancel()
6169 recordingDebugNotificationJob = scope.launch {
6270 val notificationChannel = NotificationChannelCompat .Builder (
63- DEBUG_NOTIFICATION_CHANNEL_ID ,
71+ PEBBLE_DEBUG_NOTIFICATION_CHANNEL_ID ,
6472 NotificationManager .IMPORTANCE_DEFAULT )
65- .setName(DEBUG_NOTIFICATION_CHANNEL_NAME )
73+ .setName(PEBBLE_DEBUG_NOTIFICATION_CHANNEL_NAME )
6674 .build()
6775 notificationManagerCompat.createNotificationChannel(notificationChannel)
6876
@@ -71,9 +79,9 @@ class RingService: Service(), KoinComponent {
7179 }
7280
7381 private fun startRingSyncJob () {
74- if (firstRun ) {
82+ if (firstRingRun ) {
7583 logger.i { " Starting ring sync job for the first time, resuming pending recording processing tasks" }
76- firstRun = false
84+ firstRingRun = false
7785 recordingProcessingQueue.resumePendingTasks()
7886 }
7987 if (ringSyncJob?.isActive == true ) {
@@ -85,6 +93,33 @@ class RingService: Service(), KoinComponent {
8593 }
8694 }
8795
96+ private fun stopRingJobs () {
97+ runBlocking {
98+ recordingDebugNotificationJob?.cancelAndJoin()
99+ recordingDebugNotificationJob = null
100+ ringSync.stop()
101+ ringSyncJob?.cancelAndJoin()
102+ ringSyncJob = null
103+ }
104+ }
105+
106+ private fun observeRingPaired () {
107+ if (ringObserverJob?.isActive == true ) return
108+ ringObserverJob = commonPrefs.ringPaired
109+ .map { it != null }
110+ .distinctUntilChanged()
111+ .onEach { ringPaired ->
112+ logger.d { " ringPaired changed: $ringPaired " }
113+ if (ringPaired) {
114+ startRingSyncJob()
115+ startRecordingDebugNotificationJob()
116+ } else {
117+ stopRingJobs()
118+ }
119+ }
120+ .launchIn(GlobalScope )
121+ }
122+
88123 override fun onStartCommand (intent : Intent ? , flags : Int , startId : Int ): Int {
89124 logger.v { " onStartCommand()" }
90125 if (intent != null ) {
@@ -99,10 +134,10 @@ class RingService: Service(), KoinComponent {
99134 notificationManagerCompat.createNotificationChannel(notificationChannel)
100135
101136 val notification = NotificationCompat .Builder (this , NOTIFICATION_CHANNEL_ID )
102- .setContentTitle(" Ring Service " )
103- .setContentText(" Ring Service is running " )
137+ .setContentTitle(" Pebble " )
138+ .setContentText(" Keeping Pebble connection alive " )
104139 .setOngoing(true )
105- .setSmallIcon(android. R .drawable.ic_dialog_info )
140+ .setSmallIcon(R .mipmap.ic_launcher )
106141 .build()
107142 ServiceCompat .startForeground(
108143 this ,
@@ -114,20 +149,16 @@ class RingService: Service(), KoinComponent {
114149 0
115150 }
116151 )
117- startRingSyncJob()
118- startRecordingDebugNotificationJob()
119- ringBackgroundManager.onServiceStarted()
152+ observeRingPaired()
153+ pebbleBackgroundManager.onServiceStarted()
120154 return START_STICKY
121155 }
122156
123-
124-
125157 override fun onDestroy () {
126- ringBackgroundManager.onServiceStopped()
127- runBlocking {
128- recordingDebugNotificationJob?.cancelAndJoin()
129- ringSync.stop()
130- }
158+ pebbleBackgroundManager.onServiceStopped()
159+ ringObserverJob?.cancel()
160+ ringObserverJob = null
161+ stopRingJobs()
131162 scope.cancel(" Service destroyed" )
132163 notificationManagerCompat.cancel(1 )
133164 super .onDestroy()
@@ -136,4 +167,4 @@ class RingService: Service(), KoinComponent {
136167 override fun onBind (intent : Intent ? ): IBinder ? {
137168 return null
138169 }
139- }
170+ }
0 commit comments