Added call transfer capability.
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
5
app/src/main/res/drawable/call_transfer.xml
Normal file
5
app/src/main/res/drawable/call_transfer.xml
Normal 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>
|
||||
@ -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"
|
||||
|
||||
@ -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 <%1$s> <%2$s>?
|
||||
</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!
|
||||
|
||||
@ -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 <%1$s> <%2$s>?</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!
|
||||
|
||||
Reference in New Issue
Block a user