Don't show call timer notification on locked screen after call is closed
This commit is contained in:
@ -1089,6 +1089,7 @@ class BaresipService: Service() {
|
|||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
connection.destroy()
|
connection.destroy()
|
||||||
ConnectionService.connections.remove(callp)
|
ConnectionService.connections.remove(callp)
|
||||||
|
updateStatusNotification()
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
nm.cancel(CALL_NOTIFICATION_ID)
|
nm.cancel(CALL_NOTIFICATION_ID)
|
||||||
@ -1565,117 +1566,142 @@ class BaresipService: Service() {
|
|||||||
|
|
||||||
fun updateStatusNotification() {
|
fun updateStatusNotification() {
|
||||||
|
|
||||||
val activeCall = Call.calls().find {
|
Handler(Looper.getMainLooper()).post {
|
||||||
it.status.value == "connected" || it.status.value == "outgoing" || it.status.value == "answered"
|
val activeCall = synchronized(calls) {
|
||||||
}
|
calls.find {
|
||||||
|
it.status.value == "connected" || it.status.value == "outgoing" || it.status.value == "answered"
|
||||||
val builder = NotificationCompat.Builder(this, LOW_CHANNEL_ID)
|
|
||||||
val intent = Intent(applicationContext, MainActivity::class.java)
|
|
||||||
.setAction(Intent.ACTION_MAIN)
|
|
||||||
.addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
|
|
||||||
val pi = PendingIntent.getActivity(applicationContext, STATUS_REQ_CODE, intent, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
val deleteIntent = Intent(this, BaresipService::class.java).setAction("Notification Dismissed")
|
|
||||||
val dpi = PendingIntent.getService(this, STATUS_REQ_CODE, deleteIntent, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
|
|
||||||
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification_b)
|
|
||||||
.setContentIntent(pi)
|
|
||||||
.setDeleteIntent(dpi)
|
|
||||||
.setOngoing(true)
|
|
||||||
|
|
||||||
if (activeCall != null) {
|
|
||||||
val peerUri = activeCall.peerUri
|
|
||||||
val caller = Utils.friendlyUri(this, peerUri, activeCall.ua.account)
|
|
||||||
val person = Person.Builder().setName(caller).build()
|
|
||||||
|
|
||||||
val hangupIntent = Intent(this, BaresipService::class.java)
|
|
||||||
hangupIntent.action = "Call Hangup"
|
|
||||||
hangupIntent.putExtra("callp", activeCall.callp)
|
|
||||||
val hpi = PendingIntent.getService(this, REJECT_REQ_CODE, hangupIntent,
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
|
|
||||||
builder.setStyle(NotificationCompat.CallStyle.forOngoingCall(person, hpi))
|
|
||||||
.setCategory(Notification.CATEGORY_CALL)
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
||||||
.setWhen(activeCall.startTime?.timeInMillis ?: System.currentTimeMillis())
|
|
||||||
.setUsesChronometer(true)
|
|
||||||
.setContentText(
|
|
||||||
if (activeCall.onhold)
|
|
||||||
getString(R.string.call_is_on_hold)
|
|
||||||
else
|
|
||||||
when (activeCall.status.value) {
|
|
||||||
"outgoing", "incoming" -> getString(R.string.call_is_ringing)
|
|
||||||
"connected", "answered" -> getString(R.string.call_is_connected)
|
|
||||||
else -> getString(R.string.call)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
builder.setStyle(null)
|
|
||||||
builder.setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
|
||||||
.setCategory(Notification.CATEGORY_SERVICE)
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
|
||||||
.setWhen(0)
|
|
||||||
.setShowWhen(false)
|
|
||||||
.setUsesChronometer(false)
|
|
||||||
.setContentTitle("")
|
|
||||||
.setContentText("")
|
|
||||||
|
|
||||||
val notificationLayout = RemoteViews(packageName, R.layout.status_notification)
|
|
||||||
for (i in 0..3) {
|
|
||||||
val resId = when (i) {
|
|
||||||
0 -> R.id.status0
|
|
||||||
1 -> R.id.status1
|
|
||||||
2 -> R.id.status2
|
|
||||||
else -> R.id.status3
|
|
||||||
}
|
|
||||||
if (i < uas.value.size) {
|
|
||||||
notificationLayout.setImageViewResource(resId, uas.value[i].status)
|
|
||||||
notificationLayout.setViewVisibility(resId, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
notificationLayout.setViewVisibility(resId, View.INVISIBLE)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uas.value.size > 4)
|
|
||||||
notificationLayout.setViewVisibility(R.id.etc, View.VISIBLE)
|
|
||||||
else
|
|
||||||
notificationLayout.setViewVisibility(R.id.etc, View.INVISIBLE)
|
|
||||||
|
|
||||||
builder.setCustomContentView(notificationLayout)
|
val builder = NotificationCompat.Builder(this, LOW_CHANNEL_ID)
|
||||||
}
|
val intent = Intent(applicationContext, MainActivity::class.java)
|
||||||
|
.setAction(Intent.ACTION_MAIN)
|
||||||
|
.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
|
||||||
if (VERSION.SDK_INT >= 31)
|
val pi = PendingIntent.getActivity(
|
||||||
builder.foregroundServiceBehavior = Notification.FOREGROUND_SERVICE_IMMEDIATE
|
applicationContext,
|
||||||
|
STATUS_REQ_CODE,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
val deleteIntent =
|
||||||
|
Intent(this, BaresipService::class.java).setAction("Notification Dismissed")
|
||||||
|
val dpi = PendingIntent.getService(
|
||||||
|
this,
|
||||||
|
STATUS_REQ_CODE,
|
||||||
|
deleteIntent,
|
||||||
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
|
||||||
builder.setOngoing(true)
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
val notification = builder.build()
|
.setSmallIcon(R.drawable.ic_notification_b)
|
||||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR or Notification.FLAG_ONGOING_EVENT
|
.setContentIntent(pi)
|
||||||
|
.setDeleteIntent(dpi)
|
||||||
|
.setOngoing(true)
|
||||||
|
|
||||||
try {
|
|
||||||
if (activeCall != null) {
|
if (activeCall != null) {
|
||||||
if (VERSION.SDK_INT >= 29)
|
val peerUri = activeCall.peerUri
|
||||||
startForeground(STATUS_NOTIFICATION_ID, notification, foregroundServiceType(activeCall))
|
val caller = Utils.friendlyUri(this, peerUri, activeCall.ua.account)
|
||||||
else
|
val person = Person.Builder().setName(caller).build()
|
||||||
startForeground(STATUS_NOTIFICATION_ID, notification)
|
|
||||||
isNotificationInCall = true
|
val hangupIntent = Intent(this, BaresipService::class.java)
|
||||||
|
hangupIntent.action = "Call Hangup"
|
||||||
|
hangupIntent.putExtra("callp", activeCall.callp)
|
||||||
|
val hpi = PendingIntent.getService(
|
||||||
|
this, REJECT_REQ_CODE, hangupIntent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.setStyle(NotificationCompat.CallStyle.forOngoingCall(person, hpi))
|
||||||
|
.setCategory(Notification.CATEGORY_CALL)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setWhen(activeCall.startTime?.timeInMillis ?: System.currentTimeMillis())
|
||||||
|
.setUsesChronometer(true)
|
||||||
|
.setContentText(
|
||||||
|
if (activeCall.onhold)
|
||||||
|
getString(R.string.call_is_on_hold)
|
||||||
|
else
|
||||||
|
when (activeCall.status.value) {
|
||||||
|
"outgoing", "incoming" -> getString(R.string.call_is_ringing)
|
||||||
|
"connected", "answered" -> getString(R.string.call_is_connected)
|
||||||
|
else -> getString(R.string.call)
|
||||||
|
}
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// If we are currently in a call notification mode, downgrade to standby FGS
|
builder.setStyle(null)
|
||||||
// but DO NOT call stopForeground as that would drop FGS status.
|
builder.setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
||||||
if (isNotificationInCall) {
|
.setCategory(Notification.CATEGORY_SERVICE)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||||
|
.setWhen(0)
|
||||||
|
.setShowWhen(false)
|
||||||
|
.setUsesChronometer(false)
|
||||||
|
.setContentTitle("")
|
||||||
|
.setContentText("")
|
||||||
|
|
||||||
|
val notificationLayout = RemoteViews(packageName, R.layout.status_notification)
|
||||||
|
for (i in 0..3) {
|
||||||
|
val resId = when (i) {
|
||||||
|
0 -> R.id.status0
|
||||||
|
1 -> R.id.status1
|
||||||
|
2 -> R.id.status2
|
||||||
|
else -> R.id.status3
|
||||||
|
}
|
||||||
|
if (i < uas.value.size) {
|
||||||
|
notificationLayout.setImageViewResource(resId, uas.value[i].status)
|
||||||
|
notificationLayout.setViewVisibility(resId, View.VISIBLE)
|
||||||
|
} else {
|
||||||
|
notificationLayout.setViewVisibility(resId, View.INVISIBLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uas.value.size > 4)
|
||||||
|
notificationLayout.setViewVisibility(R.id.etc, View.VISIBLE)
|
||||||
|
else
|
||||||
|
notificationLayout.setViewVisibility(R.id.etc, View.INVISIBLE)
|
||||||
|
|
||||||
|
builder.setCustomContentView(notificationLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= 31)
|
||||||
|
builder.foregroundServiceBehavior = Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||||
|
|
||||||
|
builder.setOngoing(true)
|
||||||
|
val notification = builder.build()
|
||||||
|
notification.flags =
|
||||||
|
notification.flags or Notification.FLAG_NO_CLEAR or Notification.FLAG_ONGOING_EVENT
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (activeCall != null) {
|
||||||
if (VERSION.SDK_INT >= 29)
|
if (VERSION.SDK_INT >= 29)
|
||||||
startForeground(STATUS_NOTIFICATION_ID, notification, foregroundServiceType())
|
startForeground(
|
||||||
|
STATUS_NOTIFICATION_ID,
|
||||||
|
notification,
|
||||||
|
foregroundServiceType(activeCall)
|
||||||
|
)
|
||||||
else
|
else
|
||||||
startForeground(STATUS_NOTIFICATION_ID, notification)
|
startForeground(STATUS_NOTIFICATION_ID, notification)
|
||||||
isNotificationInCall = false
|
isNotificationInCall = true
|
||||||
} else {
|
} else {
|
||||||
// Already in standby, just update the notification content
|
// If we are currently in a call notification mode, downgrade to standby FGS.
|
||||||
nm.notify(STATUS_NOTIFICATION_ID, notification)
|
// We call stopForeground(REMOVE) to explicitly clear the system's telephony UI context
|
||||||
|
// that might be persisting the timer/peer info on the lock screen.
|
||||||
|
if (isNotificationInCall) {
|
||||||
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
|
isNotificationInCall = false
|
||||||
|
}
|
||||||
|
if (VERSION.SDK_INT >= 29)
|
||||||
|
startForeground(
|
||||||
|
STATUS_NOTIFICATION_ID,
|
||||||
|
notification,
|
||||||
|
foregroundServiceType()
|
||||||
|
)
|
||||||
|
else
|
||||||
|
startForeground(STATUS_NOTIFICATION_ID, notification)
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to update foreground notification: ${e.message}")
|
||||||
|
// Fallback to standard notification if promotion/update fails
|
||||||
|
nm.notify(STATUS_NOTIFICATION_ID, notification)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to update foreground notification: ${e.message}")
|
|
||||||
// Fallback to standard notification if promotion/update fails
|
|
||||||
nm.notify(STATUS_NOTIFICATION_ID, notification)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1841,6 +1867,7 @@ class BaresipService: Service() {
|
|||||||
proximitySensing(false)
|
proximitySensing(false)
|
||||||
stopMediaPlayer()
|
stopMediaPlayer()
|
||||||
}
|
}
|
||||||
|
updateStatusNotification()
|
||||||
messageUpdate.postValue(System.currentTimeMillis())
|
messageUpdate.postValue(System.currentTimeMillis())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,11 +48,15 @@ open class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir
|
|||||||
val focusDtmf: MutableState<Boolean> = mutableStateOf(false)
|
val focusDtmf: MutableState<Boolean> = mutableStateOf(false)
|
||||||
|
|
||||||
fun add() {
|
fun add() {
|
||||||
BaresipService.calls.add(this)
|
synchronized(BaresipService.calls) {
|
||||||
|
BaresipService.calls.add(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove() {
|
fun remove() {
|
||||||
BaresipService.calls.remove(this)
|
synchronized(BaresipService.calls) {
|
||||||
|
BaresipService.calls.remove(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun connect(uri: String): Boolean {
|
open fun connect(uri: String): Boolean {
|
||||||
|
|||||||
@ -195,6 +195,7 @@ class ConnectionService : ConnectionService() {
|
|||||||
if (call != null)
|
if (call != null)
|
||||||
Api.ua_hangup(uap, callp, 0, "")
|
Api.ua_hangup(uap, callp, 0, "")
|
||||||
setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
|
setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
|
||||||
|
connections.remove(callp)
|
||||||
destroy()
|
destroy()
|
||||||
// Allow other disconnects after a short period to prevent the "Telecom Cascade" effect
|
// Allow other disconnects after a short period to prevent the "Telecom Cascade" effect
|
||||||
android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
|
android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
|
||||||
|
|||||||
Reference in New Issue
Block a user