Try to show foreground service notification asap to prevent crash if Core takes too long to start

This commit is contained in:
Sylvain Berfini 2022-05-10 15:33:20 +02:00
parent 8f8949cb3e
commit 05ee5794f2
4 changed files with 47 additions and 18 deletions

View file

@ -72,15 +72,21 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
Log.i("[Application] Core config & preferences created") Log.i("[Application] Core config & preferences created")
} }
fun ensureCoreExists(context: Context, pushReceived: Boolean = false) { fun ensureCoreExists(
context: Context,
pushReceived: Boolean = false,
service: CoreService? = null,
useAutoStartDescription: Boolean = false
): Boolean {
if (::coreContext.isInitialized && !coreContext.stopped) { if (::coreContext.isInitialized && !coreContext.stopped) {
Log.d("[Application] Skipping Core creation (push received? $pushReceived)") Log.d("[Application] Skipping Core creation (push received? $pushReceived)")
return return false
} }
Log.i("[Application] Core context is being created ${if (pushReceived) "from push" else ""}") Log.i("[Application] Core context is being created ${if (pushReceived) "from push" else ""}")
coreContext = CoreContext(context, corePreferences.config) coreContext = CoreContext(context, corePreferences.config, service, useAutoStartDescription)
coreContext.start() coreContext.start()
return true
} }
} }

View file

@ -64,7 +64,13 @@ import org.linphone.telecom.TelecomHelper
import org.linphone.utils.* import org.linphone.utils.*
import org.linphone.utils.Event import org.linphone.utils.Event
class CoreContext(val context: Context, coreConfig: Config) : LifecycleOwner, ViewModelStoreOwner { class CoreContext(
val context: Context,
coreConfig: Config,
service: CoreService? = null,
useAutoStartDescription: Boolean = false
) :
LifecycleOwner, ViewModelStoreOwner {
private val _lifecycleRegistry = LifecycleRegistry(this) private val _lifecycleRegistry = LifecycleRegistry(this)
override fun getLifecycle(): Lifecycle { override fun getLifecycle(): Lifecycle {
return _lifecycleRegistry return _lifecycleRegistry
@ -283,6 +289,8 @@ class CoreContext(val context: Context, coreConfig: Config) : LifecycleOwner, Vi
Log.i("[Context] Crashlytics enabled, register logging service listener") Log.i("[Context] Crashlytics enabled, register logging service listener")
} }
_lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
Log.i("=========================================") Log.i("=========================================")
Log.i("==== Linphone-android information dump ====") Log.i("==== Linphone-android information dump ====")
Log.i("VERSION=${BuildConfig.VERSION_NAME} / ${BuildConfig.VERSION_CODE}") Log.i("VERSION=${BuildConfig.VERSION_NAME} / ${BuildConfig.VERSION_CODE}")
@ -290,9 +298,15 @@ class CoreContext(val context: Context, coreConfig: Config) : LifecycleOwner, Vi
Log.i("BUILD TYPE=${BuildConfig.BUILD_TYPE}") Log.i("BUILD TYPE=${BuildConfig.BUILD_TYPE}")
Log.i("=========================================") Log.i("=========================================")
if (service != null) {
Log.i("[Context] Starting foreground service")
notificationsManager.startForeground(service, useAutoStartDescription)
}
core = Factory.instance().createCoreWithConfig(coreConfig, context) core = Factory.instance().createCoreWithConfig(coreConfig, context)
stopped = false stopped = false
_lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED _lifecycleRegistry.currentState = Lifecycle.State.CREATED
Log.i("[Context] Ready") Log.i("[Context] Ready")
} }
@ -316,7 +330,6 @@ class CoreContext(val context: Context, coreConfig: Config) : LifecycleOwner, Vi
configureCore() configureCore()
_lifecycleRegistry.currentState = Lifecycle.State.CREATED
core.start() core.start()
_lifecycleRegistry.currentState = Lifecycle.State.STARTED _lifecycleRegistry.currentState = Lifecycle.State.STARTED

View file

@ -29,23 +29,24 @@ import org.linphone.core.tools.service.CoreService
class CoreService : CoreService() { class CoreService : CoreService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
Log.i("[Service] Ensuring Core exists")
ensureCoreExists(applicationContext)
coreContext.notificationsManager.service = this
Log.i("[Service] Created") Log.i("[Service] Created")
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i("[Service] Ensuring Core exists")
if (corePreferences.keepServiceAlive) { if (corePreferences.keepServiceAlive) {
Log.i("[Service] Starting as foreground to keep app alive in background") Log.i("[Service] Starting as foreground to keep app alive in background")
if (!ensureCoreExists(applicationContext, pushReceived = false, service = this, useAutoStartDescription = false)) {
coreContext.notificationsManager.startForeground(this, false) coreContext.notificationsManager.startForeground(this, false)
}
} else if (intent?.extras?.get("StartForeground") == true) { } else if (intent?.extras?.get("StartForeground") == true) {
Log.i("[Service] Starting as foreground due to device boot or app update") Log.i("[Service] Starting as foreground due to device boot or app update")
if (!ensureCoreExists(applicationContext, pushReceived = false, service = this, useAutoStartDescription = true)) {
coreContext.notificationsManager.startForeground(this, true) coreContext.notificationsManager.startForeground(this, true)
}
coreContext.checkIfForegroundServiceNotificationCanBeRemovedAfterDelay(5000) coreContext.checkIfForegroundServiceNotificationCanBeRemovedAfterDelay(5000)
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
@ -80,7 +81,7 @@ class CoreService : CoreService() {
override fun onDestroy() { override fun onDestroy() {
Log.i("[Service] Stopping") Log.i("[Service] Stopping")
coreContext.notificationsManager.service = null coreContext.notificationsManager.serviceDestroyed()
super.onDestroy() super.onDestroy()
} }

View file

@ -105,7 +105,7 @@ class NotificationsManager(private val context: Context) {
private var currentForegroundServiceNotificationId: Int = 0 private var currentForegroundServiceNotificationId: Int = 0
private var serviceNotification: Notification? = null private var serviceNotification: Notification? = null
var service: CoreService? = null private var service: CoreService? = null
var currentlyDisplayedChatRoomAddress: String? = null var currentlyDisplayedChatRoomAddress: String? = null
@ -330,6 +330,8 @@ class NotificationsManager(private val context: Context) {
} }
fun startForeground(coreService: CoreService, useAutoStartDescription: Boolean = true) { fun startForeground(coreService: CoreService, useAutoStartDescription: Boolean = true) {
service = coreService
if (serviceNotification == null) { if (serviceNotification == null) {
createServiceNotification(useAutoStartDescription) createServiceNotification(useAutoStartDescription)
if (serviceNotification == null) { if (serviceNotification == null) {
@ -337,10 +339,10 @@ class NotificationsManager(private val context: Context) {
return return
} }
} }
currentForegroundServiceNotificationId = SERVICE_NOTIF_ID currentForegroundServiceNotificationId = SERVICE_NOTIF_ID
Log.i("[Notifications Manager] Starting service as foreground [$currentForegroundServiceNotificationId]") Log.i("[Notifications Manager] Starting service as foreground [$currentForegroundServiceNotificationId]")
Compatibility.startForegroundService(coreService, currentForegroundServiceNotificationId, serviceNotification) Compatibility.startForegroundService(coreService, currentForegroundServiceNotificationId, serviceNotification)
service = coreService
} }
private fun startForeground(notificationId: Int, callNotification: Notification) { private fun startForeground(notificationId: Int, callNotification: Notification) {
@ -353,10 +355,12 @@ class NotificationsManager(private val context: Context) {
fun stopForegroundNotification() { fun stopForegroundNotification() {
if (service != null) { if (service != null) {
if (currentForegroundServiceNotificationId != 0) {
Log.i("[Notifications Manager] Stopping service as foreground [$currentForegroundServiceNotificationId]") Log.i("[Notifications Manager] Stopping service as foreground [$currentForegroundServiceNotificationId]")
service?.stopForeground(true)
currentForegroundServiceNotificationId = 0 currentForegroundServiceNotificationId = 0
} }
service?.stopForeground(true)
}
} }
fun stopForegroundNotificationIfPossible() { fun stopForegroundNotificationIfPossible() {
@ -373,6 +377,11 @@ class NotificationsManager(private val context: Context) {
} }
} }
fun serviceDestroyed() {
stopForegroundNotification()
service = null
}
private fun createServiceNotification(useAutoStartDescription: Boolean = false) { private fun createServiceNotification(useAutoStartDescription: Boolean = false) {
val serviceChannel = context.getString(R.string.notification_channel_service_id) val serviceChannel = context.getString(R.string.notification_channel_service_id)
if (Compatibility.getChannelImportance(notificationManager, serviceChannel) == NotificationManagerCompat.IMPORTANCE_NONE) { if (Compatibility.getChannelImportance(notificationManager, serviceChannel) == NotificationManagerCompat.IMPORTANCE_NONE) {