Skip to content

Commit 2d0cfb0

Browse files
committed
feat: update foreground services to specify SERVICE_TYPE_CONNECTED_DEVICE and optimize service start logic
1 parent d6d7736 commit 2d0cfb0

3 files changed

Lines changed: 94 additions & 13 deletions

File tree

app/src/main/java/com/sameerasw/airsync/quickshare/QuickShareService.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.app.NotificationManager
66
import android.app.PendingIntent
77
import android.app.Service
88
import android.content.Intent
9+
import android.content.pm.ServiceInfo
910
import android.os.Binder
1011
import android.os.Build
1112
import android.os.IBinder
@@ -62,7 +63,15 @@ class QuickShareService : Service() {
6263
super.onCreate()
6364
createNotificationChannel()
6465

65-
startForeground(NOTIFICATION_ID, createNotification("Quick Share is active"))
66+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
67+
startForeground(
68+
NOTIFICATION_ID,
69+
createNotification("Quick Share is active"),
70+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
71+
)
72+
} else {
73+
startForeground(NOTIFICATION_ID, createNotification("Quick Share is active"))
74+
}
6675

6776
server = QuickShareServer(this) { connection ->
6877
val id = java.util.UUID.randomUUID().toString()
@@ -229,8 +238,15 @@ class QuickShareService : Service() {
229238
private fun startDiscoveryWithTimeout() {
230239
discoveryJob?.cancel()
231240

232-
// Ensure service is in foreground with a notification while active
233-
startForeground(NOTIFICATION_ID, createNotification("Searching for files..."))
241+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
242+
startForeground(
243+
NOTIFICATION_ID,
244+
createNotification("Searching for files..."),
245+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
246+
)
247+
} else {
248+
startForeground(NOTIFICATION_ID, createNotification("Searching for files..."))
249+
}
234250

235251
server.start()
236252
val port = server.port

app/src/main/java/com/sameerasw/airsync/service/AirSyncService.kt

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.app.PendingIntent
77
import android.app.Service
88
import android.content.Context
99
import android.content.Intent
10+
import android.content.pm.ServiceInfo
1011
import android.net.ConnectivityManager
1112
import android.net.Network
1213
import android.net.NetworkCapabilities
@@ -58,6 +59,7 @@ class AirSyncService : Service() {
5859

5960
override fun onCreate() {
6061
super.onCreate()
62+
serviceInstance = this
6163
Log.d(TAG, "AirSyncService created")
6264
createNotificationChannel()
6365
MacDeviceStatusManager.startMonitoring(this)
@@ -103,7 +105,15 @@ class AirSyncService : Service() {
103105
Log.d(TAG, "Starting AirSync scanning mode")
104106
isScanning = true
105107
connectedDeviceName = null
106-
startForeground(NOTIFICATION_ID, buildNotification())
108+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
109+
startForeground(
110+
NOTIFICATION_ID,
111+
buildNotification(),
112+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
113+
)
114+
} else {
115+
startForeground(NOTIFICATION_ID, buildNotification())
116+
}
107117

108118
val dataStoreManager =
109119
DataStoreManager.getInstance(applicationContext)
@@ -161,15 +171,31 @@ class AirSyncService : Service() {
161171
if (isScanning) {
162172
Log.d(TAG, "App in foreground, switching to ACTIVE discovery")
163173
UDPDiscoveryManager.setDiscoveryMode(this, DiscoveryMode.ACTIVE)
164-
startForeground(NOTIFICATION_ID, buildNotification()) // Update notification if needed
174+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
175+
startForeground(
176+
NOTIFICATION_ID,
177+
buildNotification(),
178+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
179+
)
180+
} else {
181+
startForeground(NOTIFICATION_ID, buildNotification())
182+
}
165183
}
166184
}
167185

168186
private fun handleAppBackground() {
169187
if (isScanning) {
170188
Log.d(TAG, "App in background, switching to PASSIVE discovery")
171189
UDPDiscoveryManager.setDiscoveryMode(this, DiscoveryMode.PASSIVE)
172-
startForeground(NOTIFICATION_ID, buildNotification()) // Update notification if needed
190+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
191+
startForeground(
192+
NOTIFICATION_ID,
193+
buildNotification(),
194+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
195+
)
196+
} else {
197+
startForeground(NOTIFICATION_ID, buildNotification())
198+
}
173199
}
174200
}
175201

@@ -180,7 +206,15 @@ class AirSyncService : Service() {
180206
}
181207
Log.d(TAG, "Starting AirSync foreground service (connected)")
182208
isScanning = false
183-
startForeground(NOTIFICATION_ID, buildNotification())
209+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
210+
startForeground(
211+
NOTIFICATION_ID,
212+
buildNotification(),
213+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
214+
)
215+
} else {
216+
startForeground(NOTIFICATION_ID, buildNotification())
217+
}
184218

185219
val dataStoreManager =
186220
DataStoreManager.getInstance(applicationContext)
@@ -333,6 +367,7 @@ class AirSyncService : Service() {
333367

334368
override fun onDestroy() {
335369
Log.d(TAG, "AirSyncService destroyed")
370+
serviceInstance = null
336371
WebSocketUtil.unregisterConnectionStatusListener(connectionStatusListener)
337372

338373
networkCallback?.let {
@@ -365,6 +400,10 @@ class AirSyncService : Service() {
365400

366401
const val EXTRA_DEVICE_NAME = "device_name"
367402

403+
private var serviceInstance: AirSyncService? = null
404+
405+
fun isRunning(): Boolean = serviceInstance != null
406+
368407
fun startScanning(context: Context) {
369408
val intent = Intent(context, AirSyncService::class.java).apply {
370409
action = ACTION_START_SCANNING
@@ -396,10 +435,14 @@ class AirSyncService : Service() {
396435

397436
private fun startAction(context: Context, intent: Intent) {
398437
try {
399-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
400-
context.startForegroundService(intent)
401-
} else {
438+
if (isRunning()) {
402439
context.startService(intent)
440+
} else {
441+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
442+
context.startForegroundService(intent)
443+
} else {
444+
context.startService(intent)
445+
}
403446
}
404447
} catch (e: Exception) {
405448
Log.e(TAG, "Error starting foreground service", e)

app/src/main/java/com/sameerasw/airsync/service/MacMediaPlayerService.kt

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import android.app.NotificationManager
66
import android.app.PendingIntent
77
import android.app.Service
88
import android.content.Intent
9+
import android.content.pm.ServiceInfo
910
import android.graphics.Bitmap
11+
import android.os.Build
1012
import android.os.IBinder
1113
import android.support.v4.media.MediaMetadataCompat
1214
import android.support.v4.media.session.MediaSessionCompat
@@ -59,7 +61,11 @@ class MacMediaPlayerService : Service() {
5961
putExtra(EXTRA_TIMESTAMP, timestamp)
6062
putExtra(EXTRA_PLAYBACK_RATE, playbackRate)
6163
}
62-
context.startForegroundService(intent)
64+
if (serviceInstance != null) {
65+
context.startService(intent)
66+
} else {
67+
context.startForegroundService(intent)
68+
}
6369
serviceInstance?.updateAlbumArt(albumArt)
6470
}
6571

@@ -146,7 +152,15 @@ class MacMediaPlayerService : Service() {
146152
val initialIsPlaying = intent?.getBooleanExtra(EXTRA_IS_PLAYING, false) ?: false
147153
val notification = createMediaNotification(initialTitle, initialArtist, initialIsPlaying)
148154
try {
149-
startForeground(NOTIFICATION_ID, notification)
155+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
156+
startForeground(
157+
NOTIFICATION_ID,
158+
notification,
159+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
160+
)
161+
} else {
162+
startForeground(NOTIFICATION_ID, notification)
163+
}
150164
} catch (e: Exception) {
151165
Log.e(TAG, "Failed to start foreground in onStartCommand: ${e.message}")
152166
}
@@ -255,7 +269,15 @@ class MacMediaPlayerService : Service() {
255269
mediaSession?.isActive = true
256270

257271
val notification = createMediaNotification(title, artist, isPlaying)
258-
startForeground(NOTIFICATION_ID, notification)
272+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
273+
startForeground(
274+
NOTIFICATION_ID,
275+
notification,
276+
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
277+
)
278+
} else {
279+
startForeground(NOTIFICATION_ID, notification)
280+
}
259281

260282
Log.d(TAG, "Mac media session started as foreground service")
261283
} catch (e: Exception) {

0 commit comments

Comments
 (0)