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