feat: add custom notification title and message for VoIP calls (also stopCallService method)

This commit is contained in:
Andrew 2026-04-09 12:22:18 +07:00
parent f722fc0e5f
commit ab5df9fd28
7 changed files with 106 additions and 26 deletions

View file

@ -139,8 +139,11 @@ class LiblinphoneFlutterPlugin : FlutterPlugin, ActivityAware, MethodCallHandler
try {
val callTo = call.argument<String>("callTo")!!
val isVideoEnabled = call.argument<Boolean>("isVideoEnabled")!!
val notificationTitle = call.argument<String>("notificationTitle")!!
val notificationMessage = call.argument<String>("notificationMessage")!!
linphoneBridge.makeCall(callTo, isVideoEnabled)
startCallService()
startCallService(notificationTitle, notificationMessage)
result.success(true)
} catch (e: Exception) {
Log.e(TAG, "makeCall: ${e.message}")
@ -149,14 +152,17 @@ class LiblinphoneFlutterPlugin : FlutterPlugin, ActivityAware, MethodCallHandler
}
"answerCall" -> {
val notificationTitle = call.argument<String>("notificationTitle")!!
val notificationMessage = call.argument<String>("notificationMessage")!!
val res = linphoneBridge.answerCall()
if (res) startCallService()
if (res) startCallService(notificationTitle, notificationMessage)
result.success(res)
}
"hangupCall" -> {
val res = linphoneBridge.hangupCall()
if (res) startCallService()
if (res) stopCallService()
result.success(res)
}
@ -201,6 +207,11 @@ class LiblinphoneFlutterPlugin : FlutterPlugin, ActivityAware, MethodCallHandler
}
}
"stopCallService" -> {
stopCallService()
result.success(true)
}
else -> {
result.notImplemented()
}
@ -243,9 +254,11 @@ class LiblinphoneFlutterPlugin : FlutterPlugin, ActivityAware, MethodCallHandler
return null
}
private fun startCallService() {
private fun startCallService(title: String, message: String) {
try {
val intent = Intent(activity.applicationContext, LinphoneVoipService::class.java)
intent.putExtra("lvs_key_name", title)
intent.putExtra("lvs_key_message", message)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
activity.startForegroundService(intent)
} else {

View file

@ -25,7 +25,11 @@ class LinphoneVoipService : Service() {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
val bundle: Bundle? = intent?.extras
val notificationTitle = bundle?.getString("lvs_key_name") ?: "Voice Call"
val notificationMessage = bundle?.getString("lvs_key_message") ?: "Call in progress"
val notification = createNotification(notificationTitle, notificationMessage)
// Android 14+ requires explicit service type in startForeground
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
@ -51,7 +55,7 @@ class LinphoneVoipService : Service() {
val channel = NotificationChannel(
channelId,
"Active VoIP Call",
NotificationManager.IMPORTANCE_LOW
NotificationManager.IMPORTANCE_HIGH
).apply {
setShowBadge(false)
setSound(null, null)
@ -61,11 +65,11 @@ class LinphoneVoipService : Service() {
}
}
private fun createNotification(): Notification {
private fun createNotification(title: String, message: String): Notification {
return NotificationCompat.Builder(this, channelId)
.setContentTitle("Voice Call")
.setContentText("Call in progress")
.setSmallIcon(android.R.drawable.ic_menu_call)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.drawable.liblinphone_flutter_dialer_sip_24px)
.setOngoing(true)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M798,840Q673,840 551,785.5Q429,731 329,631Q229,531 174.5,409Q120,287 120,162Q120,144 132,132Q144,120 162,120L324,120Q338,120 349,129.5Q360,139 362,152L388,292Q390,308 387,319Q384,330 376,338L279,436Q299,473 326.5,507.5Q354,542 387,574Q418,605 452,631.5Q486,658 524,680L618,586Q627,577 641.5,572.5Q656,568 670,570L808,598Q822,602 831,612.5Q840,623 840,636L840,798Q840,816 828,828Q816,840 798,840ZM241,360L307,294Q307,294 307,294Q307,294 307,294L290,200Q290,200 290,200Q290,200 290,200L201,200Q201,200 201,200Q201,200 201,200Q206,241 215,281Q224,321 241,360ZM599,718Q638,735 678.5,745Q719,755 760,758Q760,758 760,758Q760,758 760,758L760,670Q760,670 760,670Q760,670 760,670L666,651Q666,651 666,651Q666,651 666,651L599,718ZM241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360ZM599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718ZM480,320L480,280L560,280L560,240L480,240L480,120L600,120L600,160L520,160L520,200L600,200L600,320L480,320ZM640,320L640,120L680,120L680,320L640,320ZM720,320L720,120L840,120L840,240L760,240L760,320L720,320ZM760,200L800,200L800,160L760,160L760,200Z"/>
</vector>