From 9dda647c52edb618a17fdc4a9ca000a4505ea5e0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 19 Jul 2022 16:46:04 +0200 Subject: [PATCH] Add Foreground service when data are updated. --- vector/src/main/AndroidManifest.xml | 5 ++ .../im/vector/app/features/MainActivity.kt | 7 +++ .../notifications/NotificationUtils.kt | 13 ++++ .../features/start/StartAppAndroidService.kt | 63 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/start/StartAppAndroidService.kt diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 1c104f3bbf..b7bdac6879 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -380,6 +380,11 @@ android:exported="false" android:foregroundServiceType="location" /> + + (), UnlockedActivity views.status.setText(R.string.updating_your_data) } views.status.isVisible = state.duration > 0 + if (state.duration == 1L && startAppViewModel.shouldStartApp()) { + // Start foreground service, because the operation may take a while + val intent = Intent(this, StartAppAndroidService::class.java) + ContextCompat.startForegroundService(this, intent) + } } private fun handleViewEvents(event: StartAppViewEvent) { diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index 514952b66c..2948565d58 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -568,6 +568,19 @@ class NotificationUtils @Inject constructor( .build() } + /** + * Creates a notification that indicates the application is initializing. + */ + fun buildStartAppNotification(): Notification { + return NotificationCompat.Builder(context, LISTENING_FOR_EVENTS_NOTIFICATION_CHANNEL_ID) + .setContentTitle(stringProvider.getString(R.string.updating_your_data)) + .setSmallIcon(R.drawable.sync) + .setColor(ThemeUtils.getColor(context, android.R.attr.colorPrimary)) + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setPriority(NotificationCompat.PRIORITY_LOW) + .build() + } + fun buildDownloadFileNotification(uri: Uri, fileName: String, mimeType: String): Notification { return NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) .setGroup(stringProvider.getString(R.string.app_name)) diff --git a/vector/src/main/java/im/vector/app/features/start/StartAppAndroidService.kt b/vector/src/main/java/im/vector/app/features/start/StartAppAndroidService.kt new file mode 100644 index 0000000000..e8e0eac863 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/start/StartAppAndroidService.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.start + +import android.content.Intent +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.di.NamedGlobalScope +import im.vector.app.core.services.VectorAndroidService +import im.vector.app.features.notifications.NotificationUtils +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import javax.inject.Inject +import kotlin.random.Random +import kotlin.time.Duration.Companion.seconds + +/** + * A simple foreground service that let the app (and the SDK) time to initialize. + * Will self stop itself once the active session is set. + */ +@AndroidEntryPoint +class StartAppAndroidService : VectorAndroidService() { + + @NamedGlobalScope @Inject lateinit var globalScope: CoroutineScope + @Inject lateinit var notificationUtils: NotificationUtils + @Inject lateinit var activeSessionHolder: ActiveSessionHolder + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + showStickyNotification() + startPollingActiveSession() + return START_STICKY + } + + private fun startPollingActiveSession() { + globalScope.launch { + do { + delay(1.seconds.inWholeMilliseconds) + } while (activeSessionHolder.hasActiveSession().not()) + myStopSelf() + } + } + + private fun showStickyNotification() { + val notificationId = Random.nextInt() + val notification = notificationUtils.buildStartAppNotification() + startForeground(notificationId, notification) + } +}