Skip to content

Commit 7a39764

Browse files
Generalize AlwaysOnService with multiple versions
1 parent ad51e8c commit 7a39764

File tree

3 files changed

+74
-54
lines changed

3 files changed

+74
-54
lines changed

wear/src/main/AndroidManifest.xml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,21 @@
224224
</activity>
225225

226226
<service
227-
android:name=".snippets.alwayson.AlwaysOnService"
227+
android:name=".snippets.alwayson.AlwaysOnService1"
228+
android:foregroundServiceType="specialUse"
229+
android:exported="false">
230+
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
231+
android:value="For Ongoing Activity"/>
232+
</service>
233+
<service
234+
android:name=".snippets.alwayson.AlwaysOnService2"
235+
android:foregroundServiceType="specialUse"
236+
android:exported="false">
237+
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
238+
android:value="For Ongoing Activity"/>
239+
</service>
240+
<service
241+
android:name=".snippets.alwayson.AlwaysOnService3"
228242
android:foregroundServiceType="specialUse"
229243
android:exported="false">
230244
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"

wear/src/main/java/com/example/wear/snippets/alwayson/AlwaysOnActivity.kt

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.example.wear.snippets.alwayson
1818

1919
import android.Manifest
20+
import android.content.Intent
2021
import android.content.pm.PackageManager
2122
import android.os.Build
2223
import android.os.Bundle
@@ -141,46 +142,55 @@ fun ElapsedTime(ambientState: AmbientState) {
141142
@Composable
142143
fun WearApp() {
143144
val context = LocalContext.current
144-
var isOngoingActivity by rememberSaveable { mutableStateOf(AlwaysOnService.isRunning) }
145+
var runningService by rememberSaveable { mutableStateOf<Class<*>?>(null) }
146+
145147
MaterialTheme(
146148
colorScheme = dynamicColorScheme(LocalContext.current) ?: MaterialTheme.colorScheme
147149
) {
148-
// [START android_wear_ongoing_activity_ambientaware]
149150
AmbientAware { ambientState ->
150-
// [START_EXCLUDE]
151151
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
152152
Column(horizontalAlignment = Alignment.CenterHorizontally) {
153153
Text(text = "Elapsed Time", style = MaterialTheme.typography.titleLarge)
154154
Spacer(modifier = Modifier.height(8.dp))
155-
// [END_EXCLUDE]
156155
ElapsedTime(ambientState = ambientState)
157-
// [START_EXCLUDE]
158156
Spacer(modifier = Modifier.height(8.dp))
159-
SwitchButton(
160-
checked = isOngoingActivity,
161-
onCheckedChange = { newState ->
162-
Log.d(TAG, "Switch button changed: $newState")
163-
isOngoingActivity = newState
164-
165-
if (newState) {
166-
Log.d(TAG, "Starting AlwaysOnService")
167-
AlwaysOnService.startService(context)
168-
} else {
169-
Log.d(TAG, "Stopping AlwaysOnService")
170-
AlwaysOnService.stopService(context)
171-
}
172-
},
173-
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 4.dp),
174-
) {
175-
Text(
176-
text = "Ongoing Activity",
177-
style = MaterialTheme.typography.bodyExtraSmall,
178-
)
157+
158+
val services = listOf(
159+
AlwaysOnService1::class.java,
160+
AlwaysOnService2::class.java,
161+
AlwaysOnService3::class.java
162+
)
163+
164+
services.forEachIndexed { index, serviceClass ->
165+
val isRunning = runningService == serviceClass
166+
SwitchButton(
167+
checked = isRunning,
168+
onCheckedChange = { newState ->
169+
if (newState) {
170+
if (runningService != null) {
171+
Log.d(TAG, "Stopping ${runningService?.simpleName}")
172+
context.stopService(Intent(context, runningService))
173+
}
174+
Log.d(TAG, "Starting ${serviceClass.simpleName}")
175+
val intent = Intent(context, serviceClass)
176+
context.startForegroundService(intent)
177+
runningService = serviceClass
178+
} else {
179+
Log.d(TAG, "Stopping ${serviceClass.simpleName}")
180+
context.stopService(Intent(context, serviceClass))
181+
runningService = null
182+
}
183+
},
184+
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 4.dp),
185+
) {
186+
Text(
187+
text = "Ongoing Activity ${index + 1}",
188+
style = MaterialTheme.typography.bodyExtraSmall,
189+
)
190+
}
179191
}
180192
}
181193
}
182-
// [END_EXCLUDE]
183194
}
184-
// [END android_wear_ongoing_activity_ambientaware]
185195
}
186196
}

wear/src/main/java/com/example/wear/snippets/alwayson/AlwaysOnService.kt

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package com.example.wear.snippets.alwayson
1919
import android.app.NotificationChannel
2020
import android.app.NotificationManager
2121
import android.app.PendingIntent
22-
import android.content.Context
2322
import android.content.Intent
2423
import android.os.SystemClock
2524
import android.util.Log
@@ -30,29 +29,19 @@ import androidx.wear.ongoing.OngoingActivity
3029
import androidx.wear.ongoing.Status
3130
import com.example.wear.R
3231

33-
class AlwaysOnService : LifecycleService() {
32+
abstract class AlwaysOnServiceBase : LifecycleService() {
3433

3534
private val notificationManager by lazy { getSystemService<NotificationManager>() }
3635

3736
companion object {
3837
private const val TAG = "AlwaysOnService"
39-
private const val NOTIFICATION_ID = 1001
40-
private const val CHANNEL_ID = "always_on_service_channel"
38+
const val NOTIFICATION_ID = 1001
39+
const val CHANNEL_ID = "always_on_service_channel"
4140
private const val CHANNEL_NAME = "Always On Service"
41+
4242
@Volatile
4343
var isRunning = false
4444
private set
45-
46-
fun startService(context: Context) {
47-
Log.d(TAG, "Starting AlwaysOnService")
48-
val intent = Intent(context, AlwaysOnService::class.java)
49-
context.startForegroundService(intent)
50-
}
51-
52-
fun stopService(context: Context) {
53-
Log.d(TAG, "Stopping AlwaysOnService")
54-
context.stopService(Intent(context, AlwaysOnService::class.java))
55-
}
5645
}
5746

5847
override fun onCreate() {
@@ -66,16 +55,15 @@ class AlwaysOnService : LifecycleService() {
6655
super.onStartCommand(intent, flags, startId)
6756
Log.d(TAG, "onStartCommand: Service started with startId: $startId")
6857

69-
// Switch between different types of ongoing notification
70-
createNotification1()
71-
// createNotification2()
72-
// createNotification3()
58+
createNotification()
7359

7460
Log.d(TAG, "onStartCommand: Service is now running as foreground service")
7561

7662
return START_STICKY
7763
}
7864

65+
66+
7967
override fun onDestroy() {
8068
Log.d(TAG, "onDestroy: Service destroyed")
8169
isRunning = false
@@ -94,8 +82,12 @@ class AlwaysOnService : LifecycleService() {
9482
Log.d(TAG, "createNotificationChannel: Notification channel created")
9583
}
9684

97-
// Creates an ongoing activity that demonstrates how to link the touch intent to the always-on activity.
98-
private fun createNotification1() {
85+
abstract fun createNotification()
86+
}
87+
88+
class AlwaysOnService1 : AlwaysOnServiceBase() {
89+
override fun createNotification() {
90+
// Creates an ongoing activity that demonstrates how to link the touch intent to the always-on activity.
9991
// [START android_wear_ongoing_activity_create_notification]
10092
val activityIntent =
10193
Intent(this, AlwaysOnActivity::class.java).apply {
@@ -145,9 +137,11 @@ class AlwaysOnService : LifecycleService() {
145137

146138
startForeground(NOTIFICATION_ID, notification)
147139
}
140+
}
148141

149-
// Creates an ongoing activity with a static status text
150-
private fun createNotification2() {
142+
class AlwaysOnService2 : AlwaysOnServiceBase() {
143+
override fun createNotification() {
144+
// Creates an ongoing activity with a static status text
151145

152146
// [START android_wear_ongoing_activity_notification_builder]
153147
// Create a PendingIntent to pass to the notification builder
@@ -192,9 +186,11 @@ class AlwaysOnService : LifecycleService() {
192186
startForeground(NOTIFICATION_ID, notificationBuilder.build())
193187
// [END android_wear_ongoing_activity_post_notification]
194188
}
189+
}
195190

196-
// Creates an ongoing activity that demonstrates dynamic status text (a timer)
197-
private fun createNotification3() {
191+
class AlwaysOnService3 : AlwaysOnServiceBase() {
192+
override fun createNotification() {
193+
// Creates an ongoing activity that demonstrates dynamic status text (a timer)
198194
val activityIntent =
199195
Intent(this, AlwaysOnActivity::class.java).apply {
200196
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
@@ -252,4 +248,4 @@ class AlwaysOnService : LifecycleService() {
252248
ongoingActivity.apply(applicationContext)
253249
startForeground(NOTIFICATION_ID, notificationBuilder.build())
254250
}
255-
}
251+
}

0 commit comments

Comments
 (0)