Skip to content

incoming and out going caller name. #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
831f56d
feat: Preserve device token for VoIP push notifications
bazl-E Jul 17, 2024
257303b
chore: Remove unnecessary missed call notification code
bazl-E Jul 17, 2024
d326ac4
feat: Update localized caller name handling
bazl-E Jul 17, 2024
b803552
chore: Update TwilioVoice dependency versions
bazl-E Sep 12, 2024
420649f
voice name indication added
bazl-E Sep 26, 2024
520e276
Fix issue with missing call handle in TVConnectionService
bazl-E Sep 26, 2024
3e83395
Refactor extractClient and extractCallHandle functions
bazl-E Sep 26, 2024
e071937
Refactor extractClient and extractCallHandle functions
bazl-E Sep 27, 2024
7e8a020
Refactor extractClient and extractCallHandle functions
bazl-E Sep 30, 2024
ccb48b4
Refactor callDidStartRinging function to handle outgoing calls properly
bazl-E Oct 1, 2024
37a24e5
terminated sate call handle ios
bazl-E Oct 1, 2024
ba92a7a
Refactor onReconnected and GetActiveCallOnResumeFromTerminatedState f…
bazl-E Oct 1, 2024
3603a9b
Refactor logEvents function to only log connected calls
bazl-E Oct 1, 2024
c0f300a
Add callerName parameter to place method and update call handling
bazl-E Nov 8, 2024
333cc23
Add callerName parameter to placeCall method and update related handling
bazl-E Nov 8, 2024
3fd1050
Update client name extraction to use custom parameters and remove unu…
bazl-E Nov 11, 2024
5c81c1e
Refactor main.dart for improved readability and add callerName parame…
bazl-E Nov 14, 2024
d04fc94
Extract user number from current call in TwilioVoicePlugin for improv…
bazl-E Nov 20, 2024
c1e1a97
Refactor TwilioVoicePlugin to improve user number extraction clarity
bazl-E Nov 21, 2024
dda22ad
call_error_case_handled
bazl-E Jan 9, 2025
a2a96b6
Add namespace to Android build.gradle for Twilio Voice integration
bazl-E Mar 19, 2025
64384af
Merge remote-tracking branch 'upstream/master' into easify-specific
bazl-E Jun 20, 2025
ec3e629
feat(lldb): add LLDB helper and initialization script for debugging i…
bazl-E Jun 20, 2025
9954cb4
fix: correct plugin registration for Firebase functions and analytics
bazl-E Jun 20, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
error.message
)
logEvent(message)
logEvent("", "Call Ended")
TVConnectionService.clearActiveConnections()

}

override fun onConnected(call: Call) {
Expand Down Expand Up @@ -471,6 +474,24 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
}
}

TVMethodChannels.GetActiveCallOnResumeFromTerminatedState -> {
//is on call
val hasActiveCalls = isOnCall()
if(hasActiveCalls){
val activeCalls = TVConnectionService.Companion.activeConnections
val currentCall = activeCalls.values.firstOrNull()
val isAnsweredCall = currentCall?.twilioCall?.state == Call.State.CONNECTED
if(isAnsweredCall){
val from = extractUserNumber(currentCall?.twilioCall?.from ?: "")
val to = currentCall?.twilioCall?.to ?: ""
val callDirection = currentCall?.callDirection ?: CallDirection.INCOMING
logEvents("", arrayOf("Connected", from, to, callDirection.label ))
}
}
result.success(true)

}

TVMethodChannels.IS_BLUETOOTH_ON -> {
Log.d(TAG, "isBluetoothOn invoked")
result.success(isBluetoothOn)
Expand Down Expand Up @@ -617,11 +638,22 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
)
return@onMethodCall
}

val callerName = call.argument<String>(Constants.CALLER_NAME) ?: run {
result.error(
FlutterErrorCodes.MALFORMED_ARGUMENTS,
"No '${Constants.CALLER_NAME}' provided or invalid type",
null
)
return@onMethodCall
}


Log.d(TAG, "calling $from -> $to")

accessToken?.let { token ->
context?.let { ctx ->
val success = placeCall(ctx, token, from, to, params)
val success = placeCall(ctx, token, from, to, params,callerName )
result.success(success)
} ?: run {
Log.e(TAG, "Context is null, cannot place call")
Expand Down Expand Up @@ -672,7 +704,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH

accessToken?.let { token ->
context?.let { ctx ->
val success = placeCall(ctx, token, from, to, params, connect = true)
val success = placeCall(ctx, token, from, to, params,null, connect = true)
result.success(success)
} ?: run {
Log.e(TAG, "Context is null, cannot place call")
Expand Down Expand Up @@ -1094,6 +1126,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
from: String?,
to: String?,
params: Map<String, String>,
callerName: String?,
connect: Boolean = false
): Boolean {
assert(accessToken.isNotEmpty()) { "Twilio Access Token cannot be empty" }
Expand Down Expand Up @@ -1140,6 +1173,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
}
putExtra(TVConnectionService.EXTRA_TO, to)
putExtra(TVConnectionService.EXTRA_FROM, from)
putExtra(TVConnectionService.EXTRA_CALLER_NAME, callerName)
putExtra(TVConnectionService.EXTRA_OUTGOING_PARAMS, Bundle().apply {
for ((key, value) in params) {
putString(key, value)
Expand Down Expand Up @@ -1585,6 +1619,18 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
}
}


fun extractUserNumber(input: String): String {
// Define the regular expression pattern to match the user_number part
val pattern = Regex("""user_number:([^\s:]+)""")

// Search for the first match in the input string
val match = pattern.find(input)

// Extract the matched part (user_number:+11230123)
return match?.groups?.get(1)?.value ?: input
}

private fun requestPermissionForPhoneState(onPermissionResult: (Boolean) -> Unit) {
return requestPermissionOrShowRationale(
"Read Phone State",
Expand Down Expand Up @@ -1661,6 +1707,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
fun handleBroadcastIntent(intent: Intent) {
when (intent.action) {
TVBroadcastReceiver.ACTION_AUDIO_STATE -> {
println("Event called Basil : TVBroadcastReceiver.ACTION_AUDIO_STATE")
val callAudioState: CallAudioState =
intent.getParcelableExtraSafe(TVBroadcastReceiver.EXTRA_AUDIO_STATE) ?: run {
Log.e(
Expand Down Expand Up @@ -1715,7 +1762,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
)
return
}
val from = callInvite.from ?: ""
val from = extractUserNumber(callInvite.from ?: "")
val to = callInvite.to
val params = JSONObject().apply {
callInvite.customParameters.forEach { (key, value) ->
Expand All @@ -1728,6 +1775,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
}

TVBroadcastReceiver.ACTION_CALL_ENDED -> {
println("Event called Basil : TVBroadcastReceiver.ACTION_CALL_ENDED")
val callHandle =
intent.getStringExtra(TVBroadcastReceiver.EXTRA_CALL_HANDLE) ?: run {
Log.e(
Expand Down Expand Up @@ -1782,7 +1830,7 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
)
return
}
val from = ci.from ?: ""
val from = extractUserNumber(ci.from ?: "")
val to = ci.to
val params = JSONObject().apply {
ci.customParameters.forEach { (key, value) ->
Expand Down Expand Up @@ -1892,6 +1940,9 @@ class TwilioVoicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamH
return
}
logEvent("Call Error: ${code}, $message");
logEvent("", "Call Ended")
TVConnectionService.clearActiveConnections()

}

TVNativeCallEvents.EVENT_RECONNECTING -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ class TVCallInviteParametersImpl(storage: Storage, callInvite: CallInvite) : TVP
?: customParameters[PARAM_CALLER_ID]?.let { resolveHumanReadableName(it) }
?: run {
val mFrom = mCallInvite.from ?: ""
if (mFrom.isEmpty()) {
return mStorage.defaultCaller
}

if (!mFrom.startsWith("client:")) {
// we have a number, return as is
return mFrom
}

val mToName = mFrom.replace("client:", "")
return resolveHumanReadableName(mToName)
// if (mFrom.isEmpty()) {
// return mStorage.defaultCaller
// }
//
// if (!mFrom.startsWith("client:")) {
// // we have a number, return as is
// return mFrom
// }
//
// val mToName = mFrom.replace("client:", "")
// return resolveHumanReadableName(mToName)
return extractClient(mFrom)
}
}

Expand All @@ -55,7 +56,7 @@ class TVCallInviteParametersImpl(storage: Storage, callInvite: CallInvite) : TVP

override val fromRaw: String
get() {
return mCallInvite.from ?: ""
return extractClient( mCallInvite.from ?: "")
}

override val toRaw: String
Expand Down Expand Up @@ -91,17 +92,18 @@ class TVCallParametersImpl(storage: Storage, call: Call, callTo: String, callFro
return customParameters[PARAM_CALLER_NAME]
?: customParameters[PARAM_CALLER_ID]?.let { resolveHumanReadableName(it) }
?: run {
if (mFrom.isEmpty()) {
return mStorage.defaultCaller
}

if (!mFrom.startsWith("client:")) {
// we have a number, return as is
return mFrom
}

val mFromName = mFrom.replace("client:", "")
return resolveHumanReadableName(mFromName)
// if (mFrom.isEmpty()) {
// return mStorage.defaultCaller
// }
//
// if (!mFrom.startsWith("client:")) {
// // we have a number, return as is
// return mFrom
// }
//
// val mFromName = mFrom.replace("client:", "")
// return resolveHumanReadableName(mFromName)
return extractClient(mFrom)
}
}

Expand All @@ -126,7 +128,7 @@ class TVCallParametersImpl(storage: Storage, call: Call, callTo: String, callFro

override val fromRaw: String
get() {
return mFrom
return extractClient(mFrom)
}

override val toRaw: String
Expand Down Expand Up @@ -197,4 +199,27 @@ open class TVParametersImpl(storage: Storage, override val callSid: String = "",
override fun toString(): String {
return "TVParametersImpl(callSid='$callSid', from='$from', fromRaw='$fromRaw' to='$to', toRaw='$toRaw', customParameters=$customParameters)"
}

fun extractUserNumber(input: String): String {
// Define the regular expression pattern to match the user_number part
val pattern = Regex("""user_number:([^\s:]+)""")

// Search for the first match in the input string
val match = pattern.find(input)

// Extract the matched part (user_number:+11230123)
return match?.groups?.get(1)?.value ?: input
}

fun extractClient(input: String): String {
// // Define the regular expression pattern to match the client part
// val pattern = Regex("""client:([^\s:]+)""")

// // Search for the first match in the input string
// val match = pattern.find(input)

// // Extract the matched part (client:+11230(123))
// return match?.groups?.get(1)?.value ?: input
return input
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ object Constants {

const val kDefaultCaller: String = "defaultCaller"
const val kDEVICETOKEN: String = "DEVICETOKEN"
const val CALLER_NAME: String = "CallerName"
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class VoiceFirebaseMessagingService : FirebaseMessagingService(), MessageListene
// send broadcast to TVBroadcastReceiver, we notify Flutter about incoming call
Intent(applicationContext, TVBroadcastReceiver::class.java).apply {
action = TVBroadcastReceiver.ACTION_INCOMING_CALL
putExtra(TVBroadcastReceiver.EXTRA_CALL_INVITE, callInvite)
putExtra(TVBroadcastReceiver.EXTRA_CALL_INVITE , callInvite)
putExtra(TVBroadcastReceiver.EXTRA_CALL_HANDLE, callInvite.callSid)
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(this)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,23 @@ class TVCallInviteConnection(
setCallParameters(callParams)
}

override fun onAnswer() {
Log.d(TAG, "onAnswer: onAnswer")
super.onAnswer()
twilioCall = callInvite.accept(context, this)
onAction?.onChange(TVNativeCallActions.ACTION_ANSWERED, Bundle().apply {
putParcelable(TVBroadcastReceiver.EXTRA_CALL_INVITE, callInvite)
putInt(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, callDirection.id)
})
}
override fun onAnswer() {
Log.d(TAG, "onAnswer: onAnswer")
super.onAnswer()

// Accept the call and assign it to twilioCall
twilioCall = callInvite.accept(context, this)

// Extract the user number from callInvite.from using your custom extractUserNumber method
val extractedFrom = extractUserNumber(callInvite.from ?: "")

// Broadcast the call answered action with the extracted number
onAction?.onChange(TVNativeCallActions.ACTION_ANSWERED, Bundle().apply {
putParcelable(TVBroadcastReceiver.EXTRA_CALL_INVITE, callInvite)
putString(TVBroadcastReceiver.EXTRA_CALL_FROM, extractedFrom) // Use extracted number here
putInt(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, callDirection.id)
})
}

fun acceptInvite() {
Log.d(TAG, "acceptInvite: acceptInvite")
Expand Down Expand Up @@ -183,20 +191,32 @@ open class TVCallConnection(
onCallStateListener?.withValue(call.state)
onEvent?.onChange(TVNativeCallEvents.EVENT_RINGING, Bundle().apply {
putString(TVBroadcastReceiver.EXTRA_CALL_HANDLE, callParams?.callSid)
putString(TVBroadcastReceiver.EXTRA_CALL_FROM, callParams?.fromRaw)
putString(TVBroadcastReceiver.EXTRA_CALL_FROM,extractUserNumber( callParams?.fromRaw ?: ""))
putString(TVBroadcastReceiver.EXTRA_CALL_TO, callParams?.toRaw)
putInt(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, callDirection.id)
})
}


fun extractUserNumber(input: String): String {
// Define the regular expression pattern to match the user_number part
val pattern = Regex("""user_number:([^\s:]+)""")

// Search for the first match in the input string
val match = pattern.find(input)

// Extract the matched part (user_number:+11230123)
return match?.groups?.get(1)?.value ?: input
}

override fun onConnected(call: Call) {
Log.d(TAG, "onConnected: onConnected")
twilioCall = call
setActive()
onCallStateListener?.withValue(call.state)
onEvent?.onChange(TVNativeCallEvents.EVENT_CONNECTED, Bundle().apply {
putString(TVBroadcastReceiver.EXTRA_CALL_HANDLE, callParams?.callSid)
putString(TVBroadcastReceiver.EXTRA_CALL_FROM, callParams?.fromRaw)
putString(TVBroadcastReceiver.EXTRA_CALL_FROM,extractUserNumber(callParams?.fromRaw ?: "" ))
putString(TVBroadcastReceiver.EXTRA_CALL_TO, callParams?.toRaw)
putInt(TVBroadcastReceiver.EXTRA_CALL_DIRECTION, callDirection.id)
})
Expand Down Expand Up @@ -512,4 +532,6 @@ open class TVCallConnection(
Log.e(TAG, "sendDigits: Unable to send digits, active call is null")
}
}
}
}


Loading
Loading