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)
+ }
+}