Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3028,16 +3028,25 @@ class CallActivity : CallBaseActivity() {
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
v.onTouchEvent(event)
if (event.action == MotionEvent.ACTION_UP && isPushToTalkActive) {
isPushToTalkActive = false
binding!!.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px)
pulseAnimation!!.stop()
toggleMedia(false, false)
if (isPushToTalkRelease(event.action)) {
stopPushToTalk()
}
return true
}
}

// ACTION_CANCEL must end push to talk just like ACTION_UP, otherwise the microphone stays enabled although
// the gesture was aborted (e.g. by a system gesture or the notification shade) and the button shows "muted".
private fun stopPushToTalk() {
if (!isPushToTalkActive) {
return
}
isPushToTalkActive = false
binding!!.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px)
pulseAnimation!!.stop()
toggleMedia(false, false)
}

@Subscribe(threadMode = ThreadMode.BACKGROUND)
fun onMessageEvent(networkEvent: NetworkEvent) {
if (networkEvent.networkConnectionEvent == NetworkEvent.NetworkConnectionEvent.NETWORK_CONNECTED) {
Expand Down Expand Up @@ -3225,6 +3234,9 @@ class CallActivity : CallBaseActivity() {
private const val CALLING_TIMEOUT: Long = 45000
private const val PULSE_ANIMATION_DURATION: Int = 310

internal fun isPushToTalkRelease(action: Int): Boolean =
action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL

private const val DELAY_ON_ERROR_STOP_THRESHOLD: Int = 16

private const val SESSION_ID_PREFFIX_END: Int = 4
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.activities

import android.view.MotionEvent
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

/**
* Push-to-talk release detection ([CallActivity.isPushToTalkRelease]).
*
* A long-press that ends with ACTION_CANCEL (system gesture, notification shade) must mute the microphone again
* just like ACTION_UP, otherwise the mic stays hot while the button shows "muted".
*/
class CallActivityPushToTalkTest {

@Test
fun `ACTION_UP ends push to talk`() {
assertTrue(CallActivity.isPushToTalkRelease(MotionEvent.ACTION_UP))
}

@Test
fun `ACTION_CANCEL ends push to talk`() {
assertTrue(CallActivity.isPushToTalkRelease(MotionEvent.ACTION_CANCEL))
}

@Test
fun `other actions do not end push to talk`() {
assertFalse(CallActivity.isPushToTalkRelease(MotionEvent.ACTION_DOWN))
assertFalse(CallActivity.isPushToTalkRelease(MotionEvent.ACTION_MOVE))
assertFalse(CallActivity.isPushToTalkRelease(MotionEvent.ACTION_OUTSIDE))
}
}
Loading