From 8218e115ae0e4ae754cfbb7b3aa5de4e974803c8 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Fri, 19 Jun 2026 16:30:35 +0300 Subject: [PATCH] When incoming call or message arrives and baresip is not running, start baresip and show notification --- .../com/tutpro/baresip/BaresipService.kt | 51 ++++++++++++++++++- .../com/tutpro/baresip/InCallService.kt | 11 +++- .../kotlin/com/tutpro/baresip/MmsReceiver.kt | 39 +++++--------- .../kotlin/com/tutpro/baresip/SmsReceiver.kt | 21 +++----- 4 files changed, 82 insertions(+), 40 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index d3edc8e1..0eec08b8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -121,6 +121,9 @@ class BaresipService: Service() { private lateinit var stopState: String private lateinit var quitTimer: CountDownTimer + private data class PendingMessage(val sender: String, val body: String, val time: Long) + private val pendingMessages = mutableListOf() + private var vbTimer: Timer? = null private var origVolume = mutableMapOf() private var linkAddresses = mutableMapOf() @@ -473,6 +476,29 @@ class BaresipService: Service() { "Start" -> { + val sender = intent?.getStringExtra("sender") + val body = intent?.getStringExtra("body") + val time = intent?.getLongExtra("time", 0L) ?: 0L + + if (sender != null && body != null && time != 0L) { + Handler(Looper.getMainLooper()).post { + if (isNativeReady) { + val mobileUa = uas.value.find { it.account.isMobile } + if (mobileUa != null) + handleIncomingMessage(mobileUa.uap, sender, body, time) + else + synchronized(pendingMessages) { + pendingMessages.add(PendingMessage(sender, body, time)) + } + } + else + synchronized(pendingMessages) { + pendingMessages.add(PendingMessage(sender, body, time)) + } + } + } + + if (isStartReceived || isServiceRunning) return START_STICKY isStartReceived = true if (VERSION.SDK_INT < 31) { @@ -1646,7 +1672,30 @@ class BaresipService: Service() { fun started() { Log.d(TAG, "Received 'started' from baresip") isNativeReady = true - addMobileUserAgent() + + Handler(Looper.getMainLooper()).post { + addMobileUserAgent() + + val mobileUa = uas.value.find { it.account.isMobile } + if (mobileUa != null) + synchronized(pendingMessages) { + for (m in pendingMessages) + handleIncomingMessage(mobileUa.uap, m.sender, m.body, m.time) + pendingMessages.clear() + } + + // Process any calls that arrived while baresip is starting + InCallService.instance?.let { inCallService -> + for (call in inCallService.getCalls()) { + val aor = call.details.intentExtras?.getString("aor") + if (Call.ofCallp(call.hashCode().toLong()) == null) { + Log.d(TAG, "Processing pending external call ${call.hashCode()}") + handleExternalCall(call, aor) + } + } + } + } + if (VERSION.SDK_INT >= 31 && !telephonyCallbackRegistered) { try { telephonyManager.registerTelephonyCallback(mainExecutor, telephonyCallback) diff --git a/app/src/main/kotlin/com/tutpro/baresip/InCallService.kt b/app/src/main/kotlin/com/tutpro/baresip/InCallService.kt index 40970583..c3b1953d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/InCallService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/InCallService.kt @@ -23,9 +23,18 @@ class InCallService : InCallService() { if (handle == baresipHandle) { Log.d(TAG, "InCallService: Identified as SIP call") // SIP call is already managed by ConnectionService/BaresipService - } else { + } + else { Log.d(TAG, "InCallService: Identified as PSTN call from $handle") val aor = call.details.intentExtras?.getString("aor") + + if (BaresipService.instance == null) { + Log.i(TAG, "InCallService: BaresipService not running, starting it") + val intent = Intent(this, BaresipService::class.java) + intent.action = "Start" + androidx.core.content.ContextCompat.startForegroundService(this, intent) + } + BaresipService.instance?.handleExternalCall(call, aor) } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MmsReceiver.kt b/app/src/main/kotlin/com/tutpro/baresip/MmsReceiver.kt index 05c8b887..87d0e56c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MmsReceiver.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MmsReceiver.kt @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.provider.Telephony +import androidx.core.content.ContextCompat import androidx.core.net.toUri /** @@ -25,37 +26,26 @@ class MmsReceiver : BroadcastReceiver() { // Query the most recent MMS message val uri = "content://mms".toUri() val cursor = context.contentResolver.query(uri, null, null, null, "date DESC LIMIT 1") - + cursor?.use { c -> if (c.moveToFirst()) { val id = c.getString(c.getColumnIndexOrThrow("_id")) val date = c.getLong(c.getColumnIndexOrThrow("date")) * 1000 // mms date is in seconds - + // Get sender address val address = getMmsAddr(context, id) ?: "unknown" - + // Get text parts val body = getMmsText(context, id) - + if (body.isNotEmpty()) { - Log.d(TAG, "Extracted MMS text from $address: $body") - - val mobileUa = BaresipService.uas.value.find { it.account.isMobile } - if (mobileUa != null) { - // Notify Service for history update, notification, and alert sound - if (BaresipService.isServiceRunning) { - BaresipService.instance?.handleIncomingMessage(mobileUa.uap, "tel:$address", body, date) - } else { - // Service not running, at least save to history - val aor = mobileUa.account.aor - // Check if this message was already added (simple deduplication by timestamp) - val lastMsg = Message.messages().lastOrNull { m -> m.aor == aor } - if (lastMsg == null || lastMsg.timeStamp != date || lastMsg.peerUri != "tel:$address") { - Message(aor, "tel:$address", body, date, MESSAGE_DOWN, 0, "", true).add() - mobileUa.account.unreadMessages = true - } - } - } + Log.d(TAG, "Extracted MMS text from $address, starting service") + val serviceIntent = Intent(context, BaresipService::class.java) + serviceIntent.action = "Start" + serviceIntent.putExtra("sender", "tel:$address") + serviceIntent.putExtra("body", body) + serviceIntent.putExtra("time", date) + ContextCompat.startForegroundService(context, serviceIntent) } } } @@ -90,11 +80,10 @@ class MmsReceiver : BroadcastReceiver() { val type = it.getString(it.getColumnIndexOrThrow("ct")) if (type == "text/plain") { val data = it.getString(it.getColumnIndexOrThrow("_data")) - val body = if (data != null) { + val body = if (data != null) getPartText(context, it.getString(it.getColumnIndexOrThrow("_id"))) - } else { + else it.getString(it.getColumnIndexOrThrow("text")) - } if (body != null) sb.append(body) } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/SmsReceiver.kt b/app/src/main/kotlin/com/tutpro/baresip/SmsReceiver.kt index 2a98b0f2..78d02f5a 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/SmsReceiver.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/SmsReceiver.kt @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.provider.Telephony +import androidx.core.content.ContextCompat class SmsReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -15,20 +16,14 @@ class SmsReceiver : BroadcastReceiver() { val body = messages.joinToString("") { it.displayMessageBody ?: "" } val timestamp = messages[0].timestampMillis - Log.d(TAG, "Received SMS from $sender: $body") + Log.d(TAG, "Received SMS from $sender, starting service") - val mobileUa = BaresipService.uas.value.find { it.account.isMobile } - if (mobileUa != null) { - // Notify Service for history update, notification, and alert sound - if (BaresipService.isServiceRunning) { - BaresipService.instance?.handleIncomingMessage(mobileUa.uap, "tel:$sender", body, timestamp) - } else { - // Service not running, at least save to history - val aor = mobileUa.account.aor - Message(aor, "tel:$sender", body, timestamp, MESSAGE_DOWN, 0, "", true).add() - mobileUa.account.unreadMessages = true - } - } + val serviceIntent = Intent(context, BaresipService::class.java) + serviceIntent.action = "Start" + serviceIntent.putExtra("sender", "tel:$sender") + serviceIntent.putExtra("body", body) + serviceIntent.putExtra("time", timestamp) + ContextCompat.startForegroundService(context, serviceIntent) } }