Skip to content
Merged
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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@

<receiver android:name=".receivers.DirectReplyReceiver" />
<receiver android:name=".receivers.MarkAsReadReceiver" />
<receiver android:name=".receivers.DeclineCallReceiver" android:exported="false" />
<receiver android:name=".receivers.DismissRecordingAvailableReceiver" />
<receiver android:name=".receivers.ShareRecordingToChatReceiver" />

Expand Down
20 changes: 11 additions & 9 deletions app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import android.view.OrientationEventListener
import android.view.View
import android.view.View.OnTouchListener
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.NotificationManagerCompat
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AlertDialog
import androidx.compose.material3.MaterialTheme
Expand Down Expand Up @@ -107,7 +108,6 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.CapabilitiesUtil
import com.nextcloud.talk.utils.CapabilitiesUtil.hasSpreedFeatureCapability
import com.nextcloud.talk.utils.CapabilitiesUtil.isCallRecordingAvailable
import com.nextcloud.talk.utils.NotificationUtils.cancelExistingNotificationsForRoom
import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri
import com.nextcloud.talk.utils.ReceiverFlag
import com.nextcloud.talk.utils.SpreedFeatures
Expand All @@ -118,6 +118,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CALL_WITHOUT_NOTIFICATION
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_PASSWORD
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_TIMESTAMP
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_BREAKOUT_ROOM
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_MODERATOR
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MODIFIED_BASE_URL
Expand Down Expand Up @@ -553,6 +554,11 @@ class CallActivity : CallBaseActivity() {

if (extras.containsKey(KEY_FROM_NOTIFICATION_START_CALL)) {
isIncomingCallFromNotification = extras.getBoolean(KEY_FROM_NOTIFICATION_START_CALL)
val notificationId = extras.getInt(KEY_NOTIFICATION_TIMESTAMP, 0)
if (notificationId != 0) {
// cancel the notification to stop the call ringing
NotificationManagerCompat.from(this).cancel(notificationId)
}
Comment thread
mahibi marked this conversation as resolved.
}
if (extras.containsKey(KEY_IS_BREAKOUT_ROOM)) {
isBreakoutRoom = extras.getBoolean(KEY_IS_BREAKOUT_ROOM)
Expand Down Expand Up @@ -1031,7 +1037,10 @@ class CallActivity : CallBaseActivity() {
binding!!.selfVideoViewWrapper.visibility = View.GONE
} else if (permissionUtil!!.isCameraPermissionGranted()) {
binding!!.selfVideoViewWrapper.visibility = View.VISIBLE
onCameraClick()
// don't enable the camera if call was answered via notification
if (!isIncomingCallFromNotification) {
onCameraClick()
}
Comment thread
mahibi marked this conversation as resolved.
if (cameraEnumerator!!.deviceNames.isEmpty()) {
binding!!.cameraButton.visibility = View.GONE
}
Expand Down Expand Up @@ -1582,13 +1591,6 @@ class CallActivity : CallBaseActivity() {
}
ApplicationWideCurrentRoomHolder.getInstance().isInCall = true
ApplicationWideCurrentRoomHolder.getInstance().isDialing = false
if (!TextUtils.isEmpty(roomToken)) {
cancelExistingNotificationsForRoom(
applicationContext,
conversationUser!!,
roomToken!!
)
}
if (!hasExternalSignalingServer) {
pullSignalingMessages()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.KeyguardManager;
import android.app.PictureInPictureParams;
import android.content.Context;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -76,10 +75,7 @@ void dismissKeyguard() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
} else {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Expand Down
66 changes: 64 additions & 2 deletions app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import autodagger.AutoInjector
import com.bluelinelabs.logansquare.LoganSquare
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
import com.nextcloud.talk.activities.CallActivity
import com.nextcloud.talk.activities.MainActivity
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
Expand All @@ -57,6 +58,7 @@ import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
import com.nextcloud.talk.models.json.push.DecryptedPushMessage
import com.nextcloud.talk.models.json.push.NotificationUser
import com.nextcloud.talk.receivers.DeclineCallReceiver
import com.nextcloud.talk.receivers.DirectReplyReceiver
import com.nextcloud.talk.receivers.DismissRecordingAvailableReceiver
import com.nextcloud.talk.receivers.MarkAsReadReceiver
Expand Down Expand Up @@ -90,7 +92,6 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_OPENED_VIA_NOTIFICATION
import com.nextcloud.talk.utils.preferences.AppPreferences
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.JavaNetCookieJar
Expand Down Expand Up @@ -261,11 +262,64 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
}
)

val pendingIntentFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}

val answerVoiceBundle = Bundle(bundle).apply { putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true) }
val answerVoicePendingIntent = PendingIntent.getActivity(
applicationContext,
requestCode + ANSWER_VOICE_REQUEST_OFFSET,
Intent(applicationContext, CallActivity::class.java).apply {
putExtras(answerVoiceBundle)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
},
pendingIntentFlags
)

val answerVideoBundle = Bundle(bundle).apply { putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false) }
val answerVideoPendingIntent = PendingIntent.getActivity(
applicationContext,
requestCode + ANSWER_VIDEO_REQUEST_OFFSET,
Intent(applicationContext, CallActivity::class.java).apply {
putExtras(answerVideoBundle)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
},
pendingIntentFlags
)

val declinePendingIntent = PendingIntent.getBroadcast(
applicationContext,
requestCode + DECLINE_CALL_REQUEST_OFFSET,
Intent(applicationContext, DeclineCallReceiver::class.java).apply {
putExtra(KEY_NOTIFICATION_TIMESTAMP, pushMessage.timestamp.toInt())
},
pendingIntentFlags
Comment thread
mahibi marked this conversation as resolved.
)

val soundUri = getCallRingtoneUri(applicationContext, appPreferences)
val notificationChannelId = NotificationUtils.NotificationChannels.NOTIFICATION_CHANNEL_CALLS_V4.name
val uri = signatureVerification.user!!.baseUrl!!.toUri()
val baseUrl = uri.host

val callerPersonBuilder = Person.Builder()
.setName(conversation.displayName)
.setImportant(true)
if (conversation.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
val avatarUrl = ApiUtils.getUrlForAvatar(
signatureVerification.user!!.baseUrl!!,
conversation.name,
false
)
loadAvatarSync(avatarUrl, applicationContext)?.let { callerPersonBuilder.setIcon(it) }
}
val callerPerson = callerPersonBuilder.build()

val isVideoCall = (conversation.callFlag and Participant.InCallFlags.WITH_VIDEO) > 0
val primaryAnswerIntent = if (isVideoCall) answerVideoPendingIntent else answerVoicePendingIntent

val notification =
NotificationCompat.Builder(applicationContext, notificationChannelId)
.setPriority(NotificationCompat.PRIORITY_HIGH)
Expand All @@ -282,6 +336,11 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
.setContentIntent(fullScreenPendingIntent)
.setFullScreenIntent(fullScreenPendingIntent, true)
.setSound(soundUri)
.setStyle(
NotificationCompat.CallStyle
.forIncomingCall(callerPerson, declinePendingIntent, primaryAnswerIntent)
.setIsVideo(isVideoCall)
)
.build()
notification.flags = notification.flags or Notification.FLAG_INSISTENT

Expand All @@ -292,7 +351,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor

chatNetworkDataSource?.getRoom(userBeingCalled, roomToken = pushMessage.id!!)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.observeOn(Schedulers.io())
?.subscribe(object : Observer<ConversationModel> {
override fun onSubscribe(d: Disposable) {
// unused atm
Expand Down Expand Up @@ -1037,5 +1096,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
private const val TIMER_COUNT = 12
private const val TIMER_DELAY: Long = 5
private const val LINEBREAK: String = "\n"
private const val ANSWER_VOICE_REQUEST_OFFSET = 1
private const val ANSWER_VIDEO_REQUEST_OFFSET = 2
private const val DECLINE_CALL_REQUEST_OFFSET = 3
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Nextcloud Talk - Android Client
*
*
* SPDX-FileCopyrightText: 2026 Jens Zalzala <jens@shakingearthdigital.com>
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
package com.nextcloud.talk.receivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationManagerCompat
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_TIMESTAMP

class DeclineCallReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
val notificationId = intent.getIntExtra(KEY_NOTIFICATION_TIMESTAMP, 0)
NotificationManagerCompat.from(context).cancel(notificationId)
}
}
30 changes: 18 additions & 12 deletions gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@
</component>
<component group="androidx.compose" name="compose-bom" version="2026.02.00">
<artifact name="compose-bom-2026.02.00.pom">
<sha256 value="f6f44c9c81f0c040a39fe92fa686b2046f5948087387cefcbce9f0524220512a" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="f6f44c9c81f0c040a39fe92fa686b2046f5948087387cefcbce9f0524220512a"/>
</artifact>
</component>
<component group="androidx.compose.animation" name="animation" version="1.10.0">
Expand Down Expand Up @@ -1502,7 +1502,7 @@
</component>
<component group="androidx.compose.animation" name="animation-core" version="1.2.1">
<artifact name="animation-core-1.2.1.module">
<sha256 value="9083ac53ad162f4167ecfb895469943504f4cd6a624e612936a5209144c5b6bf" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="9083ac53ad162f4167ecfb895469943504f4cd6a624e612936a5209144c5b6bf"/>
</artifact>
</component>
<component group="androidx.compose.animation" name="animation-core" version="1.7.7">
Expand Down Expand Up @@ -2644,7 +2644,7 @@
<sha256 value="1943daa4a3412861b9a2bdc1a7c8c2ff05d9b8191c1d3e56ebb223d2eb4a8526" origin="Generated by Gradle"/>
</artifact>
<artifact name="ui-1.0.1.module">
<sha256 value="57031a6ac9b60e5b56792ebf5cde6e16812ff566ed9190cbd188b00b46c13779" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="57031a6ac9b60e5b56792ebf5cde6e16812ff566ed9190cbd188b00b46c13779"/>
</artifact>
</component>
<component group="androidx.compose.ui" name="ui" version="1.10.0">
Expand Down Expand Up @@ -16722,7 +16722,9 @@
<sha256 value="6c8989f2945d50ab38b3e0300064f1f8d2d75bbcae1434fe535d9fb6898e9ad6" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="PhotoView-2.3.0.pom">
<sha256 value="5b99aa67a3d5422c6bd909a0bd9abebdb742157490399a6680aefe17384f0c68" origin="Generated by Gradle" reason="Artifact is not signed"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="5b99aa67a3d5422c6bd909a0bd9abebdb742157490399a6680aefe17384f0c68">
<also-trust value="7ec99dc514655aa11761da29a9af5d758e5c561d6ab14085f0d1ed8ea1c3102d"/>
</sha256>
</artifact>
</component>
<component group="com.github.ddB0515.FlexibleAdapter" name="flexible-adapter" version="5.1.1">
Expand Down Expand Up @@ -16831,15 +16833,19 @@
<sha256 value="e35716ca794a1678f5a5d5c57967fbf2e5e6d1b5abd9b08c5fbef590f95aa171" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="ChatKit-0.4.2.module">
<sha256 value="7a0c1c77c2cbacaf733e49244049afb9b21385da53fd3f18771b2ec86bd6f2e9" origin="Generated by Gradle" reason="Artifact is not signed"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="7a0c1c77c2cbacaf733e49244049afb9b21385da53fd3f18771b2ec86bd6f2e9">
<also-trust value="20dcd1b7c0163369e7065646ccd33f530494b6a8ee8e3ed9106f5e2df81f2093"/>
</sha256>
</artifact>
</component>
<component group="com.github.nextcloud-deps" name="ImagePicker" version="2.1.0.2">
<artifact name="ImagePicker-2.1.0.2.aar">
<sha256 value="d440ffb62d1d8e42706b30c330774f2d129f78fa56c75679c7aa154f2c8e8a7d" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="ImagePicker-2.1.0.2.module">
<sha256 value="5369620cc8054a2e600bf7e539c40e1ca920e59cf43fd35d8a557005f0290388" origin="Generated by Gradle" reason="Artifact is not signed"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="5369620cc8054a2e600bf7e539c40e1ca920e59cf43fd35d8a557005f0290388">
<also-trust value="74d17ee6bc50900ace04f16844189c575ea27678522cc89ab351aa8022f4afbe"/>
</sha256>
</artifact>
</component>
<component group="com.github.nextcloud-deps" name="android-talk-webrtc" version="110.5481.0">
Expand Down Expand Up @@ -17060,10 +17066,10 @@
</component>
<component group="com.github.nextcloud.android-common" name="core" version="0.33.0">
<artifact name="core-0.33.0.aar">
<sha256 value="5667a7a23055bcff6d88904e5d8e5a8300dd59476a835446b0cb169249b3bf75" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="5667a7a23055bcff6d88904e5d8e5a8300dd59476a835446b0cb169249b3bf75"/>
</artifact>
<artifact name="core-0.33.0.module">
<sha256 value="c2340d4f6b51d241067bb1c14f5a16884e5fce28d4d92fcba3bf5aa6c496ba48" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="c2340d4f6b51d241067bb1c14f5a16884e5fce28d4d92fcba3bf5aa6c496ba48"/>
</artifact>
</component>
<component group="com.github.nextcloud.android-common" name="material-color-utilities" version="0.18.0">
Expand Down Expand Up @@ -17192,10 +17198,10 @@
</component>
<component group="com.github.nextcloud.android-common" name="material-color-utilities" version="0.33.0">
<artifact name="material-color-utilities-0.33.0.jar">
<sha256 value="61568a8c8f0466aea4fec621653ca8d2c08c9c687ffd6e364f909a2d19185992" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="61568a8c8f0466aea4fec621653ca8d2c08c9c687ffd6e364f909a2d19185992"/>
</artifact>
<artifact name="material-color-utilities-0.33.0.module">
<sha256 value="8bf80f41da67e7da9bea847ff3f06a595f5fecec88aa8fd3ac13dc48619a8f71" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="8bf80f41da67e7da9bea847ff3f06a595f5fecec88aa8fd3ac13dc48619a8f71"/>
</artifact>
</component>
<component group="com.github.nextcloud.android-common" name="ui" version="0.18.0">
Expand Down Expand Up @@ -17320,10 +17326,10 @@
</component>
<component group="com.github.nextcloud.android-common" name="ui" version="0.33.0">
<artifact name="ui-0.33.0.aar">
<sha256 value="906d22fe924e01b992b456c9fa2022f83941e11a3e957b32f31352eb318d3ea9" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="906d22fe924e01b992b456c9fa2022f83941e11a3e957b32f31352eb318d3ea9"/>
</artifact>
<artifact name="ui-0.33.0.module">
<sha256 value="d24b70b167941dec25fb3d00cd89ea51753c289597b6c31ac2941517f52af80f" origin="Generated by Gradle"/>
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="d24b70b167941dec25fb3d00cd89ea51753c289597b6c31ac2941517f52af80f"/>
</artifact>
</component>
<component group="com.github.spotbugs" name="spotbugs" version="4.8.6">
Expand Down
Loading