Added call transfer capability.

This commit is contained in:
Juha Heinanen
2020-08-23 13:26:28 +03:00
parent 035f89c2ee
commit b1ff3ecc0e
8 changed files with 120 additions and 18 deletions

View File

@ -1285,7 +1285,6 @@ Java_com_tutpro_baresip_Api_ua_1debug(JNIEnv *env, jobject thiz, jstring javaUA)
ua_debug_log(ua);
}
JNIEXPORT jint JNICALL
Java_com_tutpro_baresip_Call_call_1connect(JNIEnv *env, jobject thiz, jstring javaCall,
jstring javaPeer) {
@ -1375,6 +1374,22 @@ Java_com_tutpro_baresip_Call_call_1unhold(JNIEnv *env, jobject thiz, jstring jav
return ret;
}
JNIEXPORT jint JNICALL
Java_com_tutpro_baresip_Call_call_1transfer(JNIEnv *env, jobject thiz, jstring jCall,
jstring jPeer) {
const char *native_call = (*env)->GetStringUTFChars(env, jCall, 0);
const char *native_peer = (*env)->GetStringUTFChars(env, jPeer, 0);
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
LOGD("transfering call %s to %s\n", native_call, native_peer);
re_thread_enter();
int err = call_transfer(call, native_peer);
re_thread_leave();
if (err) LOGW("call_transfer error: %d\n", err);
(*env)->ReleaseStringUTFChars(env, jCall, native_call);
(*env)->ReleaseStringUTFChars(env, jPeer, native_peer);
return err;
}
JNIEXPORT jstring JNICALL
Java_com_tutpro_baresip_Api_call_1peeruri(JNIEnv *env, jobject thiz, jstring javaCall)
{

View File

@ -695,7 +695,7 @@ class BaresipService: Service() {
.setContentIntent(pi)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setContentTitle(getString(R.string.transfer_request))
.setContentTitle(getString(R.string.transfer_request_to))
.setContentText(target)
if (Build.VERSION.SDK_INT < 26) {
nb.setVibrate(LongArray(0))
@ -757,7 +757,7 @@ class BaresipService: Service() {
"transfer failed" -> {
Log.d(LOG_TAG, "AoR $aor hanging up call $callp with ${ev[1]}")
Api.ua_hangup(uap, callp, 0, "")
return
if (!Utils.isVisible()) return
}
}
}

View File

@ -39,6 +39,10 @@ class Call(val callp: String, val ua: UserAgent, val peerURI: String, val dir: S
return call_unhold(callp)
}
fun transfer(uri: String): Int {
return call_transfer(callp, uri)
}
fun sendDigit(digit: Char): Int {
return call_send_digit(callp, digit)
}
@ -66,6 +70,7 @@ class Call(val callp: String, val ua: UserAgent, val peerURI: String, val dir: S
private external fun call_connect(callp: String, peer_uri: String): Int
private external fun call_hold(callp: String): Int
private external fun call_unhold(callp: String): Int
private external fun call_transfer(callp: String, peer_uri: String): Int
private external fun call_send_digit(callp: String, digit: Char): Int
private external fun call_notify_sipfrag(callp: String, code: Int, reason: String)
private external fun call_start_audio(callp: String)

View File

@ -36,6 +36,7 @@ class MainActivity : AppCompatActivity() {
internal lateinit var answerButton: ImageButton
internal lateinit var rejectButton: ImageButton
internal lateinit var holdButton: ImageButton
internal lateinit var transferButton: ImageButton
internal lateinit var voicemailButton: ImageButton
internal lateinit var contactsButton: ImageButton
internal lateinit var messagesButton: ImageButton
@ -82,6 +83,7 @@ class MainActivity : AppCompatActivity() {
answerButton = findViewById(R.id.answerButton) as ImageButton
rejectButton = findViewById(R.id.rejectButton) as ImageButton
holdButton = findViewById(R.id.holdButton) as ImageButton
transferButton = findViewById(R.id.transferButton) as ImageButton
dtmf = findViewById(R.id.dtmf) as EditText
infoButton = findViewById(R.id.info) as ImageButton
voicemailButton = findViewById(R.id.voicemailButton) as ImageButton
@ -329,6 +331,11 @@ class MainActivity : AppCompatActivity() {
}
}
transferButton.setOnClickListener {
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
callTransfer(Call.uaCalls(ua, "")[0])
}
infoButton.setOnClickListener {
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
val calls = Call.uaCalls(ua, "")
@ -748,12 +755,12 @@ class MainActivity : AppCompatActivity() {
return
}
val titleView = View.inflate(this, R.layout.alert_title, null) as TextView
titleView.text = getString(R.string.transfer)
titleView.text = getString(R.string.transfer_request)
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
Utils.aorDomain(aor))
with (AlertDialog.Builder(this)) {
setCustomTitle(titleView)
setMessage(String.format(getString(R.string.transfer_query),
setMessage(String.format(getString(R.string.transfer_request_query),
target))
setPositiveButton(getString(R.string.yes)) { dialog, _ ->
if (call in Call.calls())
@ -782,6 +789,11 @@ class MainActivity : AppCompatActivity() {
call(ua, ev[1], "transferring")
showCall(ua)
}
"transfer failed" -> {
Toast.makeText(applicationContext,
"${getString(R.string.transfer_failed)}: ${ev[1].trim()}",
Toast.LENGTH_LONG).show()
}
"call closed" -> {
if (aor == aorSpinner.tag) {
callUri.inputType = InputType.TYPE_CLASS_TEXT +
@ -1031,6 +1043,45 @@ class MainActivity : AppCompatActivity() {
}
}
private fun callTransfer(call: Call) {
val layout = LayoutInflater.from(this)
.inflate(R.layout.call_transfer_dialog, findViewById(android.R.id.content) as ViewGroup,
false)
val titleView = layout.findViewById(R.id.title) as TextView
titleView.text = getString(R.string.call_transfer)
val transferUri = layout.findViewById(R.id.transferUri) as AutoCompleteTextView
transferUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
Contact.contacts().map { Contact -> Contact.name }))
transferUri.threshold = 2
with (AlertDialog.Builder(this)) {
setView(layout)
setPositiveButton(R.string.transfer) { dialog, _ ->
dialog.dismiss()
val uriText = transferUri.text.toString().trim()
if (uriText.length > 0) {
var uri = ContactsActivity.findContactURI(uriText)
if (!uri.startsWith("sip:")) {
uri = "sip:$uri"
if (!uri.contains("@")) {
val aor = call.ua.account.aor
val host = aor.substring(aor.indexOf("@") + 1)
uri = "$uri@$host"
}
}
if (!Utils.checkSipUri(uri))
Utils.alertView(applicationContext, getString(R.string.notice),
String.format(getString(R.string.invalid_sip_uri), uri))
else
call.transfer(uri)
}
}
setNegativeButton(android.R.string.cancel) { dialog, _ ->
dialog.cancel()
}
show()
}
}
private fun askPassword(title: String, ua: UserAgent? = null) {
val layout = LayoutInflater.from(this)
.inflate(R.layout.password_dialog, findViewById(android.R.id.content) as ViewGroup,
@ -1303,6 +1354,7 @@ class MainActivity : AppCompatActivity() {
answerButton.visibility = View.INVISIBLE
rejectButton.visibility = View.INVISIBLE
holdButton.visibility = View.INVISIBLE
transferButton.visibility = View.INVISIBLE
dtmf.visibility = View.INVISIBLE
dialpadButton.isEnabled = true
infoButton.visibility = View.INVISIBLE
@ -1334,6 +1386,7 @@ class MainActivity : AppCompatActivity() {
answerButton.visibility = View.INVISIBLE
rejectButton.visibility = View.INVISIBLE
holdButton.visibility = View.INVISIBLE
transferButton.visibility = View.INVISIBLE
dtmf.visibility = View.INVISIBLE
dialpadButton.isEnabled = false
infoButton.visibility = View.INVISIBLE
@ -1347,6 +1400,7 @@ class MainActivity : AppCompatActivity() {
rejectButton.visibility = View.VISIBLE
rejectButton.isEnabled = true
holdButton.visibility = View.INVISIBLE
transferButton.visibility = View.INVISIBLE
dtmf.visibility = View.INVISIBLE
dialpadButton.isEnabled = false
infoButton.visibility = View.INVISIBLE
@ -1370,6 +1424,7 @@ class MainActivity : AppCompatActivity() {
holdButton.setImageResource(R.drawable.pause)
}
holdButton.visibility = View.VISIBLE
transferButton.visibility = View.VISIBLE
dtmf.visibility = View.VISIBLE
dtmf.isEnabled = true
dtmf.requestFocus()

View File

@ -0,0 +1,5 @@
<vector android:height="48dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M65.2,510.67c0,247.04 200.26,447.3 447.24,447.3C759.55,957.97 959.71,757.71 959.71,510.67c0,-246.98 -200.16,-447.24 -447.27,-447.24C265.46,63.43 65.2,263.68 65.2,510.67zM139.94,510.67c0,-205.69 166.82,-372.5 372.5,-372.5 205.75,0 372.57,166.81 372.57,372.5 0,205.82 -166.81,372.57 -372.57,372.57C306.75,883.23 139.94,716.48 139.94,510.67z"/>
<path android:fillColor="#FF000000" android:pathData="M721.86,508.24 L560.34,374.74c0,0 -19.11,-20.22 -19.11,1.64 0,22.12 0,75.26 0,75.26s-12.96,0 -32.72,0c-56.84,0 -160.21,0 -202.25,0 0,0 -11.35,-3.07 -11.35,14.33 0,17.41 0,93.65 0,105.95 0,12.5 9.49,12.17 9.49,12.17 40.9,0 147.77,0 202.61,0 17.87,0 34.39,0 34.39,0s0,42.67 0,69.44c0,26.83 19.01,3.6 19.01,3.6s146.95,-110.53 162.79,-126.37C734.68,519.17 721.86,508.24 721.86,508.24z"/>
</vector>

View File

@ -140,12 +140,26 @@
android:contentDescription="@string/hold" >
</ImageButton>
<EditText
android:id="@+id/dtmf"
android:layout_width="@dimen/button_width"
<ImageButton
android:id="@+id/transferButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/uriRow"
android:padding="0dp"
android:src="@drawable/call_transfer"
android:background="@null"
android:layout_marginStart="140dp"
android:clickable="false"
android:visibility="invisible"
android:contentDescription="@string/call_transfer" >
</ImageButton>
<EditText
android:id="@+id/dtmf"
android:layout_width="64dp"
android:layout_height="wrap_content"
android:layout_below="@id/uriRow"
android:layout_marginStart="210dp"
android:inputType="phone"
android:textSize="20sp"
android:hint="@string/dtmf"

View File

@ -153,7 +153,7 @@
<string name="answer">Vastaa</string>
<string name="reject">Hylkää</string>
<string name="incoming_call_from">Puhelu soittajalta</string>
<string name="transfer_request">Puhelun siirtopyyntö kohteeseen</string>
<string name="transfer_request_to">Puhelun siirtopyyntö kohteeseen</string>
<string name="message_from">Viesti lähettäjältä</string>
<!-- Boot Completed Receiver -->
<string name="tap_to_start">Kosketa käynnistääksesi sovelluksen</string>
@ -319,6 +319,10 @@
<string name="video_request">Videopyyntö</string>
<string name="allow_video">Salli video puhelussa \'%1$s\'?</string>
<string name="hold">Aseta puhelu pitoon</string>
<string name="call_transfer">Puhelun siirto</string>
<string name="transfer_destination">Siirron kohde</string>
<string name="transfer">Siirto</string>
<string name="transfer_failed">Siirto epäonnistui</string>
<string name="dtmf">DTMF</string>
<string name="call_info">Puhelutiedot</string>
<string name="call_info_not_available">Ei saatavilla</string>
@ -346,10 +350,10 @@
<string name="verify">Todennuspyyntö</string>
<string name="verify_sas">Todennatko SAS:n &lt;%1$s&gt; &lt;%2$s&gt;?
</string>
<string name="transfer">Siirtopyyntö</string>
<string name="transfer_query">Hyväksytkö tämän puhelun siirron kohteeseen \'%1$s\'?</string>
<string name="call_failed">Puhelu epäonnistui.</string>
<string name="call_closed">Puhelu on päättynyt.</string>
<string name="transfer_request">Siirtopyyntö</string>
<string name="transfer_request_query">Hyväksytkö tämän puhelun siirron kohteeseen \'%1$s\'?</string>
<string name="call_failed">Puhelu epäonnistui</string>
<string name="call_closed">Puhelu on päättynyt</string>
<string name="call_not_secure">Tämä puhelu EI ole turvallinen!</string>
<string name="peer_not_verified">Tämä puhelu on turvallinen, mutta
kohdetta ei ole todennettu!

View File

@ -132,7 +132,7 @@
<string name="answer">Answer</string>
<string name="reject">Reject</string>
<string name="incoming_call_from">Call from</string>
<string name="transfer_request">Call transfer request to</string>
<string name="transfer_request_to">Call transfer request to</string>
<string name="message_from">Message from</string>
<!-- Boot Completed Receiver -->
<string name="tap_to_start">Tap to start application</string>
@ -284,6 +284,10 @@
<string name="video_request">Video Request</string>
<string name="allow_video">Accept video call with \'%1$s\'?</string>
<string name="hold">Hold</string>
<string name="call_transfer">Call Transfer</string>
<string name="transfer_destination">Transfer destination</string>
<string name="transfer">Transfer</string>
<string name="transfer_failed">Transfer Failed</string>
<string name="dtmf">DTMF</string>
<string name="call_info">Call Info</string>
<string name="call_info_not_available">No info available</string>
@ -309,10 +313,10 @@
<string name="registering_failed">Registering of \`%1$s\` failed.</string>
<string name="verify">Verify Request</string>
<string name="verify_sas">Do you want to verify SAS &lt;%1$s&gt; &lt;%2$s&gt;?</string>
<string name="transfer">Transfer Request</string>
<string name="transfer_query">Do you accept to transfer this call to \'%1$s\'?</string>
<string name="call_failed">Call failed.</string>
<string name="call_closed">Call is closed.</string>
<string name="transfer_request">Transfer Request</string>
<string name="transfer_request_query">Do you accept to transfer this call to \'%1$s\'?</string>
<string name="call_failed">Call failed</string>
<string name="call_closed">Call is closed</string>
<string name="call_not_secure">This call is NOT secure!</string>
<string name="peer_not_verified">This call is SECURE, but peer is NOT verified!</string>
<string name="call_is_secure">This call is SECURE and peer is VERIFIED!