Skip to content

Commit 04d5fe1

Browse files
shenlong-tanwenalextran1502
authored andcommitted
fix: promote to foreground service before starting engine (immich-app#22517)
fix: show notification from native Co-authored-by: shenlong-tanwen <[email protected]> Co-authored-by: Alex <[email protected]>
1 parent 133495a commit 04d5fe1

File tree

11 files changed

+104
-76
lines changed

11 files changed

+104
-76
lines changed

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
136136
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
137137
interface BackgroundWorkerFgHostApi {
138138
fun enable()
139+
fun saveNotificationMessage(title: String, body: String)
139140
fun configure(settings: BackgroundWorkerSettings)
140141
fun disable()
141142

@@ -164,6 +165,25 @@ interface BackgroundWorkerFgHostApi {
164165
channel.setMessageHandler(null)
165166
}
166167
}
168+
run {
169+
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage$separatedMessageChannelSuffix", codec)
170+
if (api != null) {
171+
channel.setMessageHandler { message, reply ->
172+
val args = message as List<Any?>
173+
val titleArg = args[0] as String
174+
val bodyArg = args[1] as String
175+
val wrapped: List<Any?> = try {
176+
api.saveNotificationMessage(titleArg, bodyArg)
177+
listOf(null)
178+
} catch (exception: Throwable) {
179+
BackgroundWorkerPigeonUtils.wrapError(exception)
180+
}
181+
reply.reply(wrapped)
182+
}
183+
} else {
184+
channel.setMessageHandler(null)
185+
}
186+
}
167187
run {
168188
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$separatedMessageChannelSuffix", codec)
169189
if (api != null) {
@@ -204,7 +224,6 @@ interface BackgroundWorkerFgHostApi {
204224
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
205225
interface BackgroundWorkerBgHostApi {
206226
fun onInitialized()
207-
fun showNotification(title: String, content: String)
208227
fun close()
209228

210229
companion object {
@@ -232,25 +251,6 @@ interface BackgroundWorkerBgHostApi {
232251
channel.setMessageHandler(null)
233252
}
234253
}
235-
run {
236-
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.showNotification$separatedMessageChannelSuffix", codec)
237-
if (api != null) {
238-
channel.setMessageHandler { message, reply ->
239-
val args = message as List<Any?>
240-
val titleArg = args[0] as String
241-
val contentArg = args[1] as String
242-
val wrapped: List<Any?> = try {
243-
api.showNotification(titleArg, contentArg)
244-
listOf(null)
245-
} catch (exception: Throwable) {
246-
BackgroundWorkerPigeonUtils.wrapError(exception)
247-
}
248-
reply.reply(wrapped)
249-
}
250-
} else {
251-
channel.setMessageHandler(null)
252-
}
253-
}
254254
run {
255255
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close$separatedMessageChannelSuffix", codec)
256256
if (api != null) {

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
7373
NotificationManager.IMPORTANCE_LOW
7474
)
7575
notificationManager.createNotificationChannel(notificationChannel)
76+
val notificationConfig = BackgroundWorkerPreferences(ctx).getNotificationConfig()
77+
showNotification(notificationConfig.first, notificationConfig.second)
7678

7779
loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
7880
engine = FlutterEngine(ctx)
@@ -109,7 +111,7 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
109111
}
110112

111113
// TODO: Move this to a separate NotificationManager class
112-
override fun showNotification(title: String, content: String) {
114+
private fun showNotification(title: String, content: String) {
113115
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
114116
.setSmallIcon(R.drawable.notification_icon)
115117
.setOnlyAlertOnce(true)

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
2020
enqueueMediaObserver(ctx)
2121
}
2222

23+
override fun saveNotificationMessage(title: String, body: String) {
24+
BackgroundWorkerPreferences(ctx).updateNotificationConfig(title, body)
25+
}
26+
2327
override fun configure(settings: BackgroundWorkerSettings) {
2428
BackgroundWorkerPreferences(ctx).updateSettings(settings)
2529
enqueueMediaObserver(ctx)

mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerPreferences.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
1010
private const val SHARED_PREF_MIN_DELAY_KEY = "BackgroundWorker::minDelaySeconds"
1111
private const val SHARED_PREF_REQUIRE_CHARGING_KEY = "BackgroundWorker::requireCharging"
1212
private const val SHARED_PREF_LOCK_KEY = "BackgroundWorker::isLocked"
13+
private const val SHARED_PREF_NOTIF_TITLE_KEY = "BackgroundWorker::notificationTitle"
14+
private const val SHARED_PREF_NOTIF_MSG_KEY = "BackgroundWorker::notificationMessage"
1315

1416
private const val DEFAULT_MIN_DELAY_SECONDS = 30L
1517
private const val DEFAULT_REQUIRE_CHARGING = false
18+
private const val DEFAULT_NOTIF_TITLE = "Uploading media"
19+
private const val DEFAULT_NOTIF_MSG = "Checking for new assets…"
1620
}
1721

1822
private val sp: SharedPreferences by lazy {
@@ -38,6 +42,20 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
3842
)
3943
}
4044

45+
fun updateNotificationConfig(title: String, message: String) {
46+
sp.edit {
47+
putString(SHARED_PREF_NOTIF_TITLE_KEY, title)
48+
putString(SHARED_PREF_NOTIF_MSG_KEY, message)
49+
}
50+
}
51+
52+
fun getNotificationConfig(): Pair<String, String> {
53+
val title =
54+
sp.getString(SHARED_PREF_NOTIF_TITLE_KEY, DEFAULT_NOTIF_TITLE) ?: DEFAULT_NOTIF_TITLE
55+
val message = sp.getString(SHARED_PREF_NOTIF_MSG_KEY, DEFAULT_NOTIF_MSG) ?: DEFAULT_NOTIF_MSG
56+
return Pair(title, message)
57+
}
58+
4159
fun setLocked(paused: Boolean) {
4260
sp.edit {
4361
putBoolean(SHARED_PREF_LOCK_KEY, paused)

mobile/ios/Runner/Background/BackgroundWorker.g.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Senda
182182
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
183183
protocol BackgroundWorkerFgHostApi {
184184
func enable() throws
185+
func saveNotificationMessage(title: String, body: String) throws
185186
func configure(settings: BackgroundWorkerSettings) throws
186187
func disable() throws
187188
}
@@ -205,6 +206,22 @@ class BackgroundWorkerFgHostApiSetup {
205206
} else {
206207
enableChannel.setMessageHandler(nil)
207208
}
209+
let saveNotificationMessageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
210+
if let api = api {
211+
saveNotificationMessageChannel.setMessageHandler { message, reply in
212+
let args = message as! [Any?]
213+
let titleArg = args[0] as! String
214+
let bodyArg = args[1] as! String
215+
do {
216+
try api.saveNotificationMessage(title: titleArg, body: bodyArg)
217+
reply(wrapResult(nil))
218+
} catch {
219+
reply(wrapError(error))
220+
}
221+
}
222+
} else {
223+
saveNotificationMessageChannel.setMessageHandler(nil)
224+
}
208225
let configureChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
209226
if let api = api {
210227
configureChannel.setMessageHandler { message, reply in
@@ -238,7 +255,6 @@ class BackgroundWorkerFgHostApiSetup {
238255
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
239256
protocol BackgroundWorkerBgHostApi {
240257
func onInitialized() throws
241-
func showNotification(title: String, content: String) throws
242258
func close() throws
243259
}
244260

@@ -261,22 +277,6 @@ class BackgroundWorkerBgHostApiSetup {
261277
} else {
262278
onInitializedChannel.setMessageHandler(nil)
263279
}
264-
let showNotificationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.showNotification\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
265-
if let api = api {
266-
showNotificationChannel.setMessageHandler { message, reply in
267-
let args = message as! [Any?]
268-
let titleArg = args[0] as! String
269-
let contentArg = args[1] as! String
270-
do {
271-
try api.showNotification(title: titleArg, content: contentArg)
272-
reply(wrapResult(nil))
273-
} catch {
274-
reply(wrapError(error))
275-
}
276-
}
277-
} else {
278-
showNotificationChannel.setMessageHandler(nil)
279-
}
280280
let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
281281
if let api = api {
282282
closeChannel.setMessageHandler { _, reply in

mobile/ios/Runner/Background/BackgroundWorker.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,6 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
119119
})
120120
}
121121

122-
func showNotification(title: String, content: String) throws {
123-
// No-op on iOS for the time being
124-
}
125-
126122
/**
127123
* Cancels the currently running background task, either due to timeout or external request.
128124
* Sends a cancel signal to the Flutter side and sets up a fallback timer to ensure

mobile/ios/Runner/Background/BackgroundWorkerApiImpl.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
1212
// Android only
1313
}
1414

15+
func saveNotificationMessage(title: String, body: String) throws {
16+
// Android only
17+
}
18+
1519
func disable() throws {
1620
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID);
1721
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID);

mobile/lib/domain/services/background_worker.service.dart

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import 'package:immich_mobile/domain/services/log.service.dart';
1111
import 'package:immich_mobile/entities/store.entity.dart';
1212
import 'package:immich_mobile/extensions/network_capability_extensions.dart';
1313
import 'package:immich_mobile/extensions/platform_extensions.dart';
14-
import 'package:immich_mobile/extensions/translate_extensions.dart';
15-
import 'package:immich_mobile/generated/intl_keys.g.dart';
1614
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
1715
import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.dart';
1816
import 'package:immich_mobile/platform/background_worker_api.g.dart';
@@ -44,6 +42,9 @@ class BackgroundWorkerFgService {
4442
// TODO: Move this call to native side once old timeline is removed
4543
Future<void> enable() => _foregroundHostApi.enable();
4644

45+
Future<void> saveNotificationMessage(String title, String body) =>
46+
_foregroundHostApi.saveNotificationMessage(title, body);
47+
4748
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) => _foregroundHostApi.configure(
4849
BackgroundWorkerSettings(
4950
minimumDelaySeconds:
@@ -112,13 +113,6 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
112113

113114
configureFileDownloaderNotifications();
114115

115-
if (Platform.isAndroid) {
116-
await _backgroundHostApi.showNotification(
117-
IntlKeys.uploading_media.t(),
118-
IntlKeys.backup_background_service_default_notification.t(),
119-
);
120-
}
121-
122116
// Notify the host that the background worker service has been initialized and is ready to use
123117
_backgroundHostApi.onInitialized();
124118
} catch (error, stack) {

mobile/lib/main.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import 'package:immich_mobile/constants/locales.dart';
1515
import 'package:immich_mobile/domain/services/background_worker.service.dart';
1616
import 'package:immich_mobile/entities/store.entity.dart';
1717
import 'package:immich_mobile/extensions/build_context_extensions.dart';
18+
import 'package:immich_mobile/extensions/translate_extensions.dart';
1819
import 'package:immich_mobile/generated/codegen_loader.g.dart';
20+
import 'package:immich_mobile/generated/intl_keys.g.dart';
1921
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
2022
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
2123
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
@@ -210,6 +212,14 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
210212
if (Store.isBetaTimelineEnabled) {
211213
ref.read(backgroundServiceProvider).disableService();
212214
ref.read(backgroundWorkerFgServiceProvider).enable();
215+
if (Platform.isAndroid) {
216+
ref
217+
.read(backgroundWorkerFgServiceProvider)
218+
.saveNotificationMessage(
219+
IntlKeys.uploading_media.t(),
220+
IntlKeys.backup_background_service_default_notification.t(),
221+
);
222+
}
213223
} else {
214224
ref.read(backgroundWorkerFgServiceProvider).disable();
215225
ref.read(backgroundServiceProvider).resumeServiceIfEnabled();

mobile/lib/platform/background_worker_api.g.dart

Lines changed: 23 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)