From dbb07df7e9792b56a437d8c46e4df557b0f52809 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 19 Oct 2026 14:00:43 +0200 Subject: [PATCH] Support incoming radio ringtone and notification actions on Android --- .../chat/data/IncomingCallActionReceiver.kt | 4 +++ .../com/utun/chat/data/IncomingCallManager.kt | 30 ++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallActionReceiver.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallActionReceiver.kt index eba62461..941b5ee4 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallActionReceiver.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallActionReceiver.kt @@ -19,6 +19,10 @@ class IncomingCallActionReceiver : BroadcastReceiver() { return } LogManager.addLog("INFO", "InCall", "DECLINE action callId=0x%016x".format(callId)) + if (intent.getBooleanExtra(IncomingCallManager.EXTRA_RADIO_CALL, false)) { + RadioCallController.end(callId) + return + } CallController.end(callId, 2) } } diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallManager.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallManager.kt index 108e3fdb..24124566 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallManager.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/IncomingCallManager.kt @@ -22,11 +22,16 @@ object IncomingCallManager { const val EXTRA_CALL_ID = "call_id" const val EXTRA_CHANNEL_ID = "channel_id" const val EXTRA_PEER_NODE_ID = "peer_node_id" + const val EXTRA_RADIO_CALL = "radio_call" + const val EXTRA_ANSWER_RADIO = "answer_radio" private val ringtone = RingtonePlayer() @Volatile private var initialized = false @Volatile private var activeCallId = 0L + private var activeRadio = false + private var activeChannel = "" + private var activePeer = 0L private var wakeLock: PowerManager.WakeLock? = null fun init() { @@ -54,9 +59,10 @@ object IncomingCallManager { LogManager.addLog("INFO", "InCall", "ringing stopped callId=0x%016x".format(id)) } - fun show(callId: Long, channelId: String, peerNodeId: Long) { + fun show(callId: Long, channelId: String, peerNodeId: Long, radio: Boolean = false) { stopRinging() activeCallId = callId + activeRadio = radio; activeChannel = channelId; activePeer = peerNodeId LogManager.addLog("INFO", "InCall", "incoming call id=$callId peer=$peerNodeId ch=$channelId") acquireWakeLock() ringtone.play() @@ -65,10 +71,7 @@ object IncomingCallManager { fun refreshLanguage() { createChannel(AppLanguage.context()) - val st = CallController.state.value ?: return - if (activeCallId != 0L && st.callId == activeCallId) { - showNotification(activeCallId, st.channelId, st.peerNodeId, alert = false) - } + if (activeCallId != 0L) showNotification(activeCallId, activeChannel, activePeer, alert = false) } /* ── пробуждение устройства ── */ @@ -121,6 +124,7 @@ object IncomingCallManager { putExtra(EXTRA_CALL_ID, callId) putExtra(EXTRA_CHANNEL_ID, channelId) putExtra(EXTRA_PEER_NODE_ID, peerNodeId) + putExtra(EXTRA_RADIO_CALL, activeRadio) } val contentPi = PendingIntent.getActivity(ctx, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) @@ -129,20 +133,30 @@ object IncomingCallManager { Intent(ctx, IncomingCallActionReceiver::class.java).apply { action = IncomingCallActionReceiver.ACTION_DECLINE putExtra(EXTRA_CALL_ID, callId) + putExtra(EXTRA_RADIO_CALL, activeRadio) }, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) val builder = NotificationCompat.Builder(ctx, CHANNEL_CALL) .setSmallIcon(android.R.drawable.ic_dialog_info) - .setContentTitle(AppLanguage.text(R.string.incoming_call)) - .setContentText("0x%016x".format(peerNodeId)) + .setContentTitle(AppLanguage.text(if (activeRadio) R.string.radio_call_incoming else R.string.incoming_call)) + .setContentText(if (activeRadio) RadioCallController.state.value?.let { "${it.peerName} · ${it.channelName}" } + ?: channelId else "0x%016x".format(peerNodeId)) .setCategory(NotificationCompat.CATEGORY_CALL) .setPriority(NotificationCompat.PRIORITY_MAX) .setOngoing(true) .setAutoCancel(false) .setOnlyAlertOnce(true) .setContentIntent(contentPi) - .addAction(0, AppLanguage.text(R.string.hang_up), declinePi) + .addAction(0, AppLanguage.text(if (activeRadio) R.string.decline else R.string.hang_up), declinePi) + + if (activeRadio) { + val answerPi = PendingIntent.getActivity(ctx, 2, Intent(launchIntent).apply { + action = "com.utun.chat.ANSWER_RADIO" + putExtra(EXTRA_ANSWER_RADIO, true) + }, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) + builder.addAction(0, AppLanguage.text(R.string.accept), answerPi) + } val nm = ctx.getSystemService(NotificationManager::class.java) if (alert && (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE || nm.canUseFullScreenIntent())) {