diff --git a/TCHAP_CHANGES.md b/TCHAP_CHANGES.md
index 362b65fadd..71fbb161c5 100644
--- a/TCHAP_CHANGES.md
+++ b/TCHAP_CHANGES.md
@@ -1,7 +1,9 @@
-Changes in Tchap 2.13.11 (2024-11-15)
+Changes in Tchap 2.13.11 (2024-11-16)
=====================================
-No significant changes.
+Bugfixes 🐛
+----------
+- Correction du crash quand on reçoit ou émet un appel sur Tchap. ([#1126](https://github.com/tchapgouv/tchap-android/issues/1126))
Changes in Tchap 2.13.10 (2024-11-15)
=====================================
@@ -10,10 +12,6 @@ Improvements 🙌
--------------
- Modification du commentaire lorsqu'on active l'accès à un salon par lien. ([#1112](https://github.com/tchapgouv/tchap-android/issues/1112))
-Bugfixes 🐛
-----------
- - Correction du crash quand on reçoit ou émet un appel sur Tchap. ([#1126](https://github.com/tchapgouv/tchap-android/issues/1126))
-
Changes in Tchap 2.13.9 (2024-11-12)
====================================
diff --git a/vector-config/src/tchap/res/values/config-features.xml b/vector-config/src/tchap/res/values/config-features.xml
index 6050a08f7c..3796724003 100755
--- a/vector-config/src/tchap/res/values/config-features.xml
+++ b/vector-config/src/tchap/res/values/config-features.xml
@@ -3,7 +3,7 @@
true
true
false
- true
+ false
- agent.dinum.tchap.gouv.fr
diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index 1f4eb1ef93..a15f56a045 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -44,7 +44,6 @@
-
@@ -58,6 +57,9 @@
+
+
+
diff --git a/vector/src/main/java/im/vector/app/core/services/CallAndroidService.kt b/vector/src/main/java/im/vector/app/core/services/CallAndroidService.kt
index b14c5604eb..1f5b0f7b5c 100644
--- a/vector/src/main/java/im/vector/app/core/services/CallAndroidService.kt
+++ b/vector/src/main/java/im/vector/app/core/services/CallAndroidService.kt
@@ -182,8 +182,11 @@ class CallAndroidService : VectorAndroidService() {
title = callInformation.opponentMatrixItem?.getBestName() ?: callInformation.opponentUserId,
fromBg = fromBg
)
- // TCHAP fix crash when a call incoming on Androd 14 and higher
- notificationManager.notify(callId.hashCode(), notification)
+ if (knownCalls.isEmpty()) {
+ startForegroundCompat(callId.hashCode(), notification)
+ } else {
+ notificationManager.notify(callId.hashCode(), notification)
+ }
knownCalls[callId] = callInformation
}
@@ -200,8 +203,7 @@ class CallAndroidService : VectorAndroidService() {
}
val notification = notificationUtils.buildCallEndedNotification(false)
val notificationId = callId.hashCode()
- // TCHAP fix crash when a call incoming on Androd 14 and higher
- notificationManager.notify(notificationId, notification)
+ startForegroundCompat(notificationId, notification)
if (knownCalls.isEmpty()) {
Timber.tag(loggerTag.value).v("No more call, stop the service")
stopForegroundCompat()
@@ -262,8 +264,11 @@ class CallAndroidService : VectorAndroidService() {
call = call,
title = callInformation.opponentMatrixItem?.getBestName() ?: callInformation.opponentUserId
)
- // TCHAP fix crash when a call incoming on Androd 14 and higher
- startForegroundCompat(callId.hashCode(), notification)
+ if (knownCalls.isEmpty()) {
+ startForegroundCompat(callId.hashCode(), notification)
+ } else {
+ notificationManager.notify(callId.hashCode(), notification)
+ }
knownCalls[callId] = callInformation
}
diff --git a/vector/src/withdmvoip/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt b/vector/src/main/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt
similarity index 92%
rename from vector/src/withdmvoip/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt
rename to vector/src/main/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt
index 1cf2aee737..bb570442ae 100644
--- a/vector/src/withdmvoip/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt
+++ b/vector/src/main/java/im/vector/app/features/call/audio/MicrophoneAccessService.kt
@@ -23,12 +23,14 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.startForegroundCompat
import im.vector.app.core.services.VectorAndroidService
import im.vector.app.features.notifications.NotificationUtils
+import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
@AndroidEntryPoint
class MicrophoneAccessService : VectorAndroidService() {
@Inject lateinit var notificationUtils: NotificationUtils
+ @Inject lateinit var clock: Clock
private val binder = LocalBinder()
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@@ -38,7 +40,7 @@ class MicrophoneAccessService : VectorAndroidService() {
}
private fun showMicrophoneAccessNotification() {
- val notificationId = System.currentTimeMillis().toInt()
+ val notificationId = clock.epochMillis().toInt()
val notification = notificationUtils.buildMicrophoneAccessNotification()
startForegroundCompat(notificationId, notification)
}
diff --git a/vector/src/withdmvoip/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/withdmvoip/java/im/vector/app/features/call/VectorCallActivity.kt
index 483fdf8d71..7919320871 100644
--- a/vector/src/withdmvoip/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/withdmvoip/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -251,26 +251,24 @@ class VectorCallActivity :
}
private fun startMicrophoneService() {
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
- == PackageManager.PERMISSION_GRANTED) {
-
- // Only start the service if the app is in the foreground
- if (isAppInForeground()) {
- Timber.tag(loggerTag.value).v("Starting microphone foreground service")
- val intent = Intent(this, MicrophoneAccessService::class.java)
- ContextCompat.startForegroundService(this, intent)
- } else {
- Timber.tag(loggerTag.value).v("App is not in foreground; cannot start microphone service")
- }
- } else {
- Timber.tag(loggerTag.value).v("Microphone permission not granted; cannot start service")
+ val isConnected = withState(callViewModel) {
+ val callState = it.callState.invoke()
+ callState is CallState.Connected
}
+ if (!isAppInForeground()) return
+ if (!isConnected) return
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) return
+
+ Timber.tag(loggerTag.value).d("Starting microphone foreground service")
+ val intent = Intent(this, MicrophoneAccessService::class.java)
+ ContextCompat.startForegroundService(this, intent)
}
private fun isAppInForeground(): Boolean {
val appProcess = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
return appProcess
}
+
private fun stopMicrophoneService() {
Timber.tag(loggerTag.value).d("Stopping MicrophoneAccessService (if needed).")
val intent = Intent(this, MicrophoneAccessService::class.java)
@@ -292,6 +290,7 @@ class VectorCallActivity :
turnScreenOffAndKeyguardOn()
removeOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer)
screenCaptureServiceConnection.unbind()
+ stopMicrophoneService()
super.onDestroy()
}
diff --git a/vector/src/withvoip/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/withvoip/java/im/vector/app/features/call/VectorCallActivity.kt
index 4480126038..7919320871 100644
--- a/vector/src/withvoip/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/withvoip/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -16,12 +16,14 @@
package im.vector.app.features.call
+import android.Manifest
import android.app.Activity
import android.app.KeyguardManager
import android.app.PictureInPictureParams
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
+import android.content.pm.PackageManager
import android.graphics.Color
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
@@ -40,6 +42,8 @@ import androidx.core.content.getSystemService
import androidx.core.util.Consumer
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.ProcessLifecycleOwner
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel
@@ -57,6 +61,7 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.ActivityCallBinding
+import im.vector.app.features.call.audio.MicrophoneAccessService
import im.vector.app.features.call.dialpad.CallDialPadBottomSheet
import im.vector.app.features.call.dialpad.DialPadFragment
import im.vector.app.features.call.transfer.CallTransferActivity
@@ -245,11 +250,47 @@ class VectorCallActivity :
}
}
+ private fun startMicrophoneService() {
+ val isConnected = withState(callViewModel) {
+ val callState = it.callState.invoke()
+ callState is CallState.Connected
+ }
+ if (!isAppInForeground()) return
+ if (!isConnected) return
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) return
+
+ Timber.tag(loggerTag.value).d("Starting microphone foreground service")
+ val intent = Intent(this, MicrophoneAccessService::class.java)
+ ContextCompat.startForegroundService(this, intent)
+ }
+
+ private fun isAppInForeground(): Boolean {
+ val appProcess = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
+ return appProcess
+ }
+
+ private fun stopMicrophoneService() {
+ Timber.tag(loggerTag.value).d("Stopping MicrophoneAccessService (if needed).")
+ val intent = Intent(this, MicrophoneAccessService::class.java)
+ stopService(intent)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ startMicrophoneService()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ stopMicrophoneService()
+ }
+
override fun onDestroy() {
detachRenderersIfNeeded()
turnScreenOffAndKeyguardOn()
removeOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer)
screenCaptureServiceConnection.unbind()
+ stopMicrophoneService()
super.onDestroy()
}