Merge branch 'tel_uri'
This commit is contained in:
@@ -3,6 +3,8 @@ package com.tutpro.baresip
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
import java.net.URLEncoder
|
||||||
|
import java.net.URLDecoder
|
||||||
|
|
||||||
class Account(val accp: String) {
|
class Account(val accp: String) {
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ class Account(val accp: String) {
|
|||||||
var missedCalls = false
|
var missedCalls = false
|
||||||
var unreadMessages = false
|
var unreadMessages = false
|
||||||
var callHistory = true
|
var callHistory = true
|
||||||
|
var telProvider = Utils.aorDomain(aor)
|
||||||
var resumeUri = ""
|
var resumeUri = ""
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -56,6 +59,10 @@ class Account(val accp: String) {
|
|||||||
|
|
||||||
val extra = Api.account_extra(accp)
|
val extra = Api.account_extra(accp)
|
||||||
callHistory = Utils.paramValue(extra,"call_history") == ""
|
callHistory = Utils.paramValue(extra,"call_history") == ""
|
||||||
|
telProvider = if (Utils.paramExists(extra, "tel_provider"))
|
||||||
|
URLDecoder.decode(Utils.paramValue(extra,"tel_provider"), "UTF-8")
|
||||||
|
else
|
||||||
|
Utils.aorDomain(aor)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +126,8 @@ class Account(val accp: String) {
|
|||||||
if (!callHistory)
|
if (!callHistory)
|
||||||
extra += ";call_history=no"
|
extra += ";call_history=no"
|
||||||
|
|
||||||
|
extra += ";tel_provider=${URLEncoder.encode(telProvider, "UTF-8")}"
|
||||||
|
|
||||||
if (extra != "")
|
if (extra != "")
|
||||||
res += ";extra=\"" + extra.substringAfter(";") + "\""
|
res += ";extra=\"" + extra.substringAfter(";") + "\""
|
||||||
|
|
||||||
@@ -189,6 +198,14 @@ class Account(val accp: String) {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun telProviderAccounts(): Array<String> {
|
||||||
|
val res = ArrayList<String>()
|
||||||
|
for (account in accounts())
|
||||||
|
if (account.telProvider != "")
|
||||||
|
res.add(account.aor.substring(4))
|
||||||
|
return res.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
fun ofAor(aor: String): Account? {
|
fun ofAor(aor: String): Account? {
|
||||||
for (ua in UserAgent.uas())
|
for (ua in UserAgent.uas())
|
||||||
if (ua.account.aor == aor) return ua.account
|
if (ua.account.aor == aor) return ua.account
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package com.tutpro.baresip
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.opengl.Visibility
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.tutpro.baresip.databinding.ActivityAccountBinding
|
import com.tutpro.baresip.databinding.ActivityAccountBinding
|
||||||
@@ -33,6 +36,7 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
private lateinit var outbound1: EditText
|
private lateinit var outbound1: EditText
|
||||||
private lateinit var outbound2: EditText
|
private lateinit var outbound2: EditText
|
||||||
private lateinit var mediaNat: String
|
private lateinit var mediaNat: String
|
||||||
|
private lateinit var stun: LinearLayout
|
||||||
private lateinit var stunServer: EditText
|
private lateinit var stunServer: EditText
|
||||||
private lateinit var stunUser: EditText
|
private lateinit var stunUser: EditText
|
||||||
private lateinit var stunPass: EditText
|
private lateinit var stunPass: EditText
|
||||||
@@ -45,6 +49,7 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
private var answerMode = Api.ANSWERMODE_MANUAL
|
private var answerMode = Api.ANSWERMODE_MANUAL
|
||||||
private lateinit var answerModeSpinner: Spinner
|
private lateinit var answerModeSpinner: Spinner
|
||||||
private lateinit var vmUri: EditText
|
private lateinit var vmUri: EditText
|
||||||
|
private lateinit var telProvider: EditText
|
||||||
private lateinit var defaultCheck: CheckBox
|
private lateinit var defaultCheck: CheckBox
|
||||||
|
|
||||||
private val mediaEncKeys = arrayListOf("zrtp", "dtls_srtp", "srtp-mandf", "srtp-mand", "srtp", "")
|
private val mediaEncKeys = arrayListOf("zrtp", "dtls_srtp", "srtp-mandf", "srtp-mand", "srtp", "")
|
||||||
@@ -73,6 +78,7 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
outbound2 = binding.Outbound2
|
outbound2 = binding.Outbound2
|
||||||
regCheck = binding.Register
|
regCheck = binding.Register
|
||||||
mediaNatSpinner = binding.mediaNatSpinner
|
mediaNatSpinner = binding.mediaNatSpinner
|
||||||
|
stun = binding.Stun
|
||||||
stunServer = binding.StunServer
|
stunServer = binding.StunServer
|
||||||
stunUser = binding.StunUser
|
stunUser = binding.StunUser
|
||||||
stunPass = binding.StunPass
|
stunPass = binding.StunPass
|
||||||
@@ -80,6 +86,7 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
dtmfModeSpinner = binding.dtmfModeSpinner
|
dtmfModeSpinner = binding.dtmfModeSpinner
|
||||||
answerModeSpinner = binding.answerModeSpinner
|
answerModeSpinner = binding.answerModeSpinner
|
||||||
vmUri = binding.voicemailUri
|
vmUri = binding.voicemailUri
|
||||||
|
telProvider = binding.telephonyProvider
|
||||||
defaultCheck = binding.Default
|
defaultCheck = binding.Default
|
||||||
|
|
||||||
aor = intent.getStringExtra("aor")!!
|
aor = intent.getStringExtra("aor")!!
|
||||||
@@ -230,27 +237,21 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
stunServer.setText(resources.getString(R.string.stun_server_default))
|
stunServer.setText(resources.getString(R.string.stun_server_default))
|
||||||
else if ((mediaNat == "ice") && (stunServer.text.toString() == ""))
|
else if ((mediaNat == "ice") && (stunServer.text.toString() == ""))
|
||||||
stunServer.setText(resources.getString(R.string.stun_server_default))
|
stunServer.setText(resources.getString(R.string.stun_server_default))
|
||||||
else if (mediaNat == "") {
|
if (mediaNat == "") {
|
||||||
|
stun.visibility = GONE
|
||||||
stunServer.setText("")
|
stunServer.setText("")
|
||||||
stunUser.setText("")
|
stunUser.setText("")
|
||||||
stunPass.setText("")
|
stunPass.setText("")
|
||||||
}
|
} else
|
||||||
stunServer.isEnabled = mediaNat != ""
|
stun.visibility = VISIBLE
|
||||||
stunUser.isEnabled = mediaNat != ""
|
|
||||||
stunPass.isEnabled = mediaNat != ""
|
|
||||||
}
|
}
|
||||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stunServer.setText(acc.stunServer)
|
stunServer.setText(acc.stunServer)
|
||||||
stunServer.isEnabled = mediaNat != ""
|
|
||||||
|
|
||||||
stunUser.setText(acc.stunUser)
|
stunUser.setText(acc.stunUser)
|
||||||
stunUser.isEnabled = mediaNat != ""
|
|
||||||
|
|
||||||
stunPass.setText(acc.stunPass)
|
stunPass.setText(acc.stunPass)
|
||||||
stunPass.isEnabled = mediaNat != ""
|
|
||||||
|
|
||||||
mediaEnc = acc.mediaEnc
|
mediaEnc = acc.mediaEnc
|
||||||
keyIx = mediaEncKeys.indexOf(mediaEnc)
|
keyIx = mediaEncKeys.indexOf(mediaEnc)
|
||||||
@@ -313,6 +314,8 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
telProvider.setText(acc.telProvider)
|
||||||
|
|
||||||
vmUri.setText(acc.vmUri)
|
vmUri.setText(acc.vmUri)
|
||||||
|
|
||||||
defaultCheck.isChecked = uaIndex == 0
|
defaultCheck.isChecked = uaIndex == 0
|
||||||
@@ -563,9 +566,9 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
if (tVmUri != "") {
|
if (tVmUri != "") {
|
||||||
if (!tVmUri.startsWith("sip:")) tVmUri = "sip:$tVmUri"
|
if (!tVmUri.startsWith("sip:")) tVmUri = "sip:$tVmUri"
|
||||||
if (!tVmUri.contains("@")) tVmUri = "$tVmUri@${acc.host()}"
|
if (!tVmUri.contains("@")) tVmUri = "$tVmUri@${acc.host()}"
|
||||||
if (!Utils.checkSipUri(tVmUri)) {
|
if (!Utils.checkUri(tVmUri)) {
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
String.format(getString(R.string.invalid_voicemail_uri), tVmUri))
|
String.format(getString(R.string.invalid_sip_or_tel_uri), tVmUri))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
Api.account_set_mwi(acc.accp, "yes")
|
Api.account_set_mwi(acc.accp, "yes")
|
||||||
@@ -576,6 +579,17 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
save = true
|
save = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hostPart = telProvider.text.toString().trim()
|
||||||
|
if (hostPart != acc.telProvider) {
|
||||||
|
if (hostPart != "" && !Utils.checkHostPortParams(hostPart)) {
|
||||||
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
|
String.format(getString(R.string.invalid_sip_uri_hostpart), hostPart))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
acc.telProvider = hostPart
|
||||||
|
save = true
|
||||||
|
}
|
||||||
|
|
||||||
if (defaultCheck.isChecked && (uaIndex > 0)) {
|
if (defaultCheck.isChecked && (uaIndex > 0)) {
|
||||||
val uasTmp = BaresipService.uas[0]
|
val uasTmp = BaresipService.uas[0]
|
||||||
val statusTmp = BaresipService.status[0]
|
val statusTmp = BaresipService.status[0]
|
||||||
@@ -708,6 +722,12 @@ class AccountActivity : AppCompatActivity() {
|
|||||||
getString(R.string.voicemain_uri_help)
|
getString(R.string.voicemain_uri_help)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
binding.TelephonyProviderTitle.setOnClickListener {
|
||||||
|
Utils.alertView(
|
||||||
|
this, getString(R.string.telephony_provider),
|
||||||
|
getString(R.string.telephony_provider_help)
|
||||||
|
)
|
||||||
|
}
|
||||||
binding.DefaultTitle.setOnClickListener {
|
binding.DefaultTitle.setOnClickListener {
|
||||||
Utils.alertView(
|
Utils.alertView(
|
||||||
this, getString(R.string.default_account),
|
this, getString(R.string.default_account),
|
||||||
|
|||||||
@@ -123,17 +123,14 @@ class ChatsActivity: AppCompatActivity() {
|
|||||||
plusButton.setOnClickListener {
|
plusButton.setOnClickListener {
|
||||||
val uriText = peerUri.text.toString().trim()
|
val uriText = peerUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
var uri = ContactsActivity.findContactURI(uriText)
|
val contactUri = ContactsActivity.findContactUri(uriText)
|
||||||
if (!uri.startsWith("sip:")) {
|
val uri = if (contactUri == null)
|
||||||
uri = "sip:$uri"
|
Utils.uriComplete(uriText, Utils.aorDomain(aor))
|
||||||
if (!uri.contains("@")) {
|
else
|
||||||
val host = aor.substring(aor.indexOf("@") + 1)
|
uriText
|
||||||
uri = "$uri@$host"
|
if (!Utils.checkUri(uri)) {
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Utils.checkSipUri(uri)) {
|
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
getString(R.string.invalid_chat_peer_uri))
|
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||||
} else {
|
} else {
|
||||||
peerUri.text.clear()
|
peerUri.text.clear()
|
||||||
peerUri.isCursorVisible = false
|
peerUri.isCursorVisible = false
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.tutpro.baresip.databinding.ActivityContactBinding
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class ContactActivity : AppCompatActivity() {
|
class ContactActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityContactBinding
|
private lateinit var binding: ActivityContactBinding
|
||||||
@@ -83,12 +84,10 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
nameView.hint = getString(R.string.contact_name)
|
nameView.hint = getString(R.string.contact_name)
|
||||||
nameView.setSelection(nameView.text.length)
|
nameView.setSelection(nameView.text.length)
|
||||||
val uri = intent.getStringExtra("uri")!!
|
val uri = intent.getStringExtra("uri")!!
|
||||||
if (uri == "") {
|
if (uri == "")
|
||||||
uriView.setText("")
|
uriView.setText("")
|
||||||
uriView.hint = getString(R.string.sip_uri)
|
else
|
||||||
} else {
|
|
||||||
uriView.setText(uri)
|
uriView.setText(uri)
|
||||||
}
|
|
||||||
uOrI = uri
|
uOrI = uri
|
||||||
androidCheck.isChecked = false
|
androidCheck.isChecked = false
|
||||||
} else {
|
} else {
|
||||||
@@ -183,6 +182,9 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
requestPermissions(permissions, CONTACT_PERMISSION_REQUEST_CODE)
|
requestPermissions(permissions, CONTACT_PERMISSION_REQUEST_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log.d(TAG, "Android sip contacts ${logAndroidContacts(this, "sip")}")
|
||||||
|
// Log.d(TAG, "Android tel contacts ${logAndroidContacts(this, "tel")}")
|
||||||
|
|
||||||
Utils.addActivity("contact,$newContact,$uOrI")
|
Utils.addActivity("contact,$newContact,$uOrI")
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -255,7 +257,7 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
R.id.checkIcon -> {
|
R.id.checkIcon -> {
|
||||||
|
|
||||||
var newName = nameView.text.toString().trim()
|
var newName = nameView.text.toString().trim()
|
||||||
var newUri = uriView.text.toString().trim()
|
var newUri = uriView.text.toString().filterNot{setOf('-', ' ').contains(it)}
|
||||||
|
|
||||||
if (newName == "") newName = newUri
|
if (newName == "") newName = newUri
|
||||||
|
|
||||||
@@ -275,15 +277,14 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newUri.startsWith("sip:")) {
|
if (!newUri.startsWith("sip:") && !newUri.startsWith("tel:"))
|
||||||
newUri = if (newUri.contains("@") || (BaresipService.uas.size != 1))
|
newUri = if (Utils.isTelNumber(newUri))
|
||||||
"sip:$newUri"
|
"tel:$newUri"
|
||||||
else
|
else
|
||||||
"sip:$newUri@${Utils.aorDomain(BaresipService.uas[0].account.aor)}"
|
"sip:$newUri"
|
||||||
}
|
if (!Utils.checkUri(newUri)) {
|
||||||
if (!Utils.checkSipUri(newUri)) {
|
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
String.format(getString(R.string.invalid_contact_uri), newUri))
|
String.format(getString(R.string.invalid_sip_or_tel_uri), newUri))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,10 +434,14 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
.withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
.withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
.withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, contact.name)
|
.withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, contact.name)
|
||||||
.build())
|
.build())
|
||||||
|
val mimeType = if (contact.uri.startsWith("sip:"))
|
||||||
|
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
|
||||||
|
else
|
||||||
|
CommonDataKinds.Phone.CONTENT_ITEM_TYPE
|
||||||
ops.add(ContentProviderOperation
|
ops.add(ContentProviderOperation
|
||||||
.newInsert(ContactsContract.Data.CONTENT_URI)
|
.newInsert(ContactsContract.Data.CONTENT_URI)
|
||||||
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
|
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
|
||||||
.withValue(Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
.withValue(Data.MIMETYPE, mimeType)
|
||||||
.withValue(Data.DATA1, contact.uri.substringAfter(":"))
|
.withValue(Data.DATA1, contact.uri.substringAfter(":"))
|
||||||
.build())
|
.build())
|
||||||
if (contact.avatarImage != null) {
|
if (contact.avatarImage != null) {
|
||||||
@@ -460,37 +465,45 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAndroidContact(rawContactId: Long, contact: Contact) {
|
private fun updateAndroidContact(rawContactId: Long, contact: Contact) {
|
||||||
if (updateAndroidSipUri(rawContactId, contact.uri) == 0)
|
if (updateAndroidUri(rawContactId, contact.uri) == 0)
|
||||||
addAndroidSipUri(rawContactId, contact.uri)
|
addAndroidUri(rawContactId, contact.uri)
|
||||||
if (updateAndroidPhoto(rawContactId, contact.avatarImage) == 0)
|
if (updateAndroidPhoto(rawContactId, contact.avatarImage) == 0)
|
||||||
if (contact.avatarImage != null)
|
if (contact.avatarImage != null)
|
||||||
addAndroidPhoto(rawContactId, contact.avatarImage!!)
|
addAndroidPhoto(rawContactId, contact.avatarImage!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAndroidSipUri(rawContactId: Long, sipUri: String) {
|
private fun addAndroidUri(rawContactId: Long, uri: String) {
|
||||||
|
val mimeType = if (uri.startsWith("sip:"))
|
||||||
|
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
|
||||||
|
else
|
||||||
|
CommonDataKinds.Phone.CONTENT_ITEM_TYPE
|
||||||
val ops = ArrayList<ContentProviderOperation>()
|
val ops = ArrayList<ContentProviderOperation>()
|
||||||
ops.add(ContentProviderOperation
|
ops.add(ContentProviderOperation
|
||||||
.newInsert(ContactsContract.Data.CONTENT_URI)
|
.newInsert(ContactsContract.Data.CONTENT_URI)
|
||||||
.withValue(Data.RAW_CONTACT_ID, rawContactId)
|
.withValue(Data.RAW_CONTACT_ID, rawContactId)
|
||||||
.withValue(Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
.withValue(Data.MIMETYPE, mimeType)
|
||||||
.withValue(Data.DATA1, sipUri.substringAfter(":"))
|
.withValue(Data.DATA1, uri.substringAfter(":"))
|
||||||
.build())
|
.build())
|
||||||
try {
|
try {
|
||||||
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Adding of SIP URI $sipUri failed")
|
Log.e(TAG, "Adding of SIP URI $uri failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAndroidSipUri(rawContactId: Long, sipUri: String): Int {
|
private fun updateAndroidUri(rawContactId: Long, uri: String): Int {
|
||||||
|
val mimeType = if (uri.startsWith("sip:"))
|
||||||
|
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
|
||||||
|
else
|
||||||
|
CommonDataKinds.Phone.CONTENT_ITEM_TYPE
|
||||||
val contentValues = ContentValues()
|
val contentValues = ContentValues()
|
||||||
contentValues.put(ContactsContract.Data.DATA1, sipUri)
|
contentValues.put(ContactsContract.Data.DATA1, uri)
|
||||||
val where = "${ContactsContract.Data.RAW_CONTACT_ID}=$rawContactId and " +
|
val where = "${ContactsContract.Data.RAW_CONTACT_ID}=$rawContactId and " +
|
||||||
"${ContactsContract.Data.MIMETYPE}='${CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}'"
|
"${ContactsContract.Data.MIMETYPE}='$mimeType'"
|
||||||
return try {
|
return try {
|
||||||
contentResolver.update(ContactsContract.Data.CONTENT_URI, contentValues, where, null)
|
contentResolver.update(ContactsContract.Data.CONTENT_URI, contentValues, where, null)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Adding of SIP URI $sipUri failed")
|
Log.e(TAG, "Adding of SIP URI $uri failed")
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -555,13 +568,16 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
fun logAndroidSipContacts(ctx: Context): HashMap<Long, MutableList<String>> {
|
fun logAndroidContacts(ctx: Context, type: String): HashMap<Long, MutableList<String>> {
|
||||||
|
val mimeType = if (type == "sip")
|
||||||
|
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
|
||||||
|
else
|
||||||
|
CommonDataKinds.Phone.CONTENT_ITEM_TYPE
|
||||||
val contacts = HashMap<Long, MutableList<String>>()
|
val contacts = HashMap<Long, MutableList<String>>()
|
||||||
val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME,
|
val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME,
|
||||||
ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1,
|
ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1,
|
||||||
ContactsContract.Data.PHOTO_THUMBNAIL_URI)
|
ContactsContract.Data.PHOTO_THUMBNAIL_URI)
|
||||||
val selection = ContactsContract.Data.MIMETYPE + "='" +
|
val selection = ContactsContract.Data.MIMETYPE + "='" + mimeType + "'"
|
||||||
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "'"
|
|
||||||
val cur: Cursor? = ctx.contentResolver.query(ContactsContract.Data.CONTENT_URI, projection,
|
val cur: Cursor? = ctx.contentResolver.query(ContactsContract.Data.CONTENT_URI, projection,
|
||||||
selection, null, null)
|
selection, null, null)
|
||||||
while (cur != null && cur.moveToNext()) {
|
while (cur != null && cur.moveToNext()) {
|
||||||
@@ -574,6 +590,7 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
when (mime) {
|
when (mime) {
|
||||||
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE -> kind = "sip"
|
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE -> kind = "sip"
|
||||||
CommonDataKinds.Photo.CONTENT_ITEM_TYPE -> kind = "thumb"
|
CommonDataKinds.Photo.CONTENT_ITEM_TYPE -> kind = "thumb"
|
||||||
|
CommonDataKinds.Phone.CONTENT_ITEM_TYPE -> kind = "tel"
|
||||||
}
|
}
|
||||||
Log.d(TAG, "got $id, $name, $kind - $data")
|
Log.d(TAG, "got $id, $name, $kind - $data")
|
||||||
var info: MutableList<String>
|
var info: MutableList<String>
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.*
|
||||||
import android.widget.ImageButton
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -85,7 +82,7 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
|
|||||||
} else {
|
} else {
|
||||||
BaresipService.activities.clear()
|
BaresipService.activities.clear()
|
||||||
i.putExtra("uap", ua.uap)
|
i.putExtra("uap", ua.uap)
|
||||||
i.putExtra("peer", Contact.contacts()[position].uri)
|
i.putExtra("peer", contact.uri)
|
||||||
(ctx as Activity).startActivity(i)
|
(ctx as Activity).startActivity(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,19 +89,18 @@ class ContactsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun findContactURI(name: String): String {
|
fun findContactUri(name: String): String? {
|
||||||
for (c in Contact.contacts())
|
for (c in Contact.contacts())
|
||||||
if (c.name == name)
|
if (c.name.equals(name, ignoreCase = true))
|
||||||
return c.uri.removePrefix("<")
|
return c.uri.removePrefix("<")
|
||||||
.replaceAfter(">", "")
|
.replaceAfter(">", "")
|
||||||
.replace(">", "")
|
.replace(">", "")
|
||||||
return name
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findContact(uri: String): Contact? {
|
fun findContact(uri: String): Contact? {
|
||||||
for (c in Contact.contacts())
|
for (c in Contact.contacts())
|
||||||
if ((Utils.uriUserPart(c.uri) == Utils.uriUserPart(uri)) &&
|
if (Utils.uriMatch(c.uri, uri))
|
||||||
(Utils.uriHostPart(c.uri) == Utils.uriHostPart(uri)))
|
|
||||||
return c
|
return c
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -112,17 +111,14 @@ class ContactsActivity : AppCompatActivity() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return contact name of uri or uri itself if contact with uri is not found
|
||||||
fun contactName(uri: String): String {
|
fun contactName(uri: String): String {
|
||||||
val uriUser = Utils.uriUserPart(uri)
|
val userPart = Utils.uriUserPart(uri)
|
||||||
val uriHost = Utils.uriHostPart(uri)
|
return if (Utils.isTelNumber(userPart))
|
||||||
for (c in Contact.contacts()) {
|
findContact("tel:$userPart")?.name ?: uri
|
||||||
val contactUser = Utils.uriUserPart(c.uri)
|
else
|
||||||
if ((contactUser == uriUser) &&
|
findContact(uri)?.name ?: uri
|
||||||
(Utils.isE164Number(contactUser) ||
|
|
||||||
(Utils.uriHostPart(c.uri) == uriHost)))
|
|
||||||
return c.name
|
|
||||||
}
|
|
||||||
return uri
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -763,22 +763,36 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return
|
return
|
||||||
val uri: Uri? = intent.data
|
val uri: Uri? = intent.data
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
val uriStr = URLDecoder.decode(uri.toString(), "UTF-8").replace(" ", "")
|
|
||||||
when (uri.scheme) {
|
when (uri.scheme) {
|
||||||
"sip" -> {
|
"sip" -> {
|
||||||
|
val uriStr = URLDecoder.decode(uri.toString(), "UTF-8")
|
||||||
var ua = UserAgent.ofDomain(Utils.uriHostPart(uriStr))
|
var ua = UserAgent.ofDomain(Utils.uriHostPart(uriStr))
|
||||||
if (ua == null)
|
if (ua == null && BaresipService.uas.size > 0)
|
||||||
ua = BaresipService.uas[0]
|
ua = BaresipService.uas[0]
|
||||||
|
if (ua == null) {
|
||||||
|
Log.w(TAG, "No accounts for '$uriStr'")
|
||||||
|
return
|
||||||
|
}
|
||||||
spinToAor(ua.account.aor)
|
spinToAor(ua.account.aor)
|
||||||
resumeAction = "call"
|
resumeAction = "call"
|
||||||
ua.account.resumeUri = uriStr
|
ua.account.resumeUri = uriStr
|
||||||
}
|
}
|
||||||
"tel" -> {
|
"tel" -> {
|
||||||
val acc = BaresipService.uas[0].account
|
val uriStr = URLDecoder.decode(uri.toString(), "UTF-8")
|
||||||
spinToAor(acc.aor)
|
.filterNot{setOf('-', ' ').contains(it)}
|
||||||
|
var account: Account? = null
|
||||||
|
for (a in Account.accounts())
|
||||||
|
if (a.telProvider != "") {
|
||||||
|
account = a
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (account == null) {
|
||||||
|
Log.w(TAG, "No telephony providers for '$uriStr'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
spinToAor(account.aor)
|
||||||
resumeAction = "call"
|
resumeAction = "call"
|
||||||
acc.resumeUri = uriStr.replace("tel", "sip") + "@" +
|
account.resumeUri = uriStr
|
||||||
Utils.uriHostPart(acc.aor)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.w(TAG, "Unsupported URI scheme ${uri.scheme}")
|
Log.w(TAG, "Unsupported URI scheme ${uri.scheme}")
|
||||||
@@ -1369,16 +1383,18 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setPositiveButton(R.string.transfer) { dialog, _ ->
|
setPositiveButton(R.string.transfer) { dialog, _ ->
|
||||||
imm.hideSoftInputFromWindow(transferUri.windowToken, 0)
|
imm.hideSoftInputFromWindow(transferUri.windowToken, 0)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
val uriText = transferUri.text.toString().trim()
|
var uriText = transferUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
val uri = Utils.uriComplete(
|
uriText = ContactsActivity.findContactUri(uriText) ?: uriText
|
||||||
ContactsActivity.findContactURI(uriText)
|
if (Utils.isTelNumber(uriText))
|
||||||
.filterNot { it.isWhitespace() },
|
uriText = "tel:$uriText"
|
||||||
Utils.aorDomain(ua.account.aor)
|
val uri = if (Utils.isTelUri(uriText))
|
||||||
)
|
Utils.telToSip(uriText, ua.account)
|
||||||
if (!Utils.checkSipUri(uri)) {
|
else
|
||||||
|
Utils.uriComplete(uriText, Utils.aorDomain(ua.account.aor))
|
||||||
|
if (!Utils.checkUri(uri)) {
|
||||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||||
String.format(getString(R.string.invalid_sip_uri), uri))
|
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||||
} else {
|
} else {
|
||||||
if (Call.uaCalls(ua, "").size > 0) {
|
if (Call.uaCalls(ua, "").size > 0) {
|
||||||
Call.uaCalls(ua, "")[0].transfer(uri)
|
Call.uaCalls(ua, "")[0].transfer(uri)
|
||||||
@@ -1655,17 +1671,38 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||||
val aor = ua.account.aor
|
val aor = ua.account.aor
|
||||||
if (Call.calls().isEmpty()) {
|
if (Call.calls().isEmpty()) {
|
||||||
val uriText = callUri.text.toString().trim()
|
var uriText = callUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
val uri = Utils.uriComplete(
|
uriText = ContactsActivity.findContactUri(uriText) ?: uriText
|
||||||
ContactsActivity.findContactURI(uriText)
|
if (Utils.isTelNumber(uriText))
|
||||||
.filterNot { it.isWhitespace() },
|
uriText = "tel:$uriText"
|
||||||
Utils.aorDomain(aor)
|
val uri = if (Utils.isTelUri(uriText)) {
|
||||||
)
|
if (ua.account.telProvider == "") {
|
||||||
if (!Utils.checkSipUri(uri)) {
|
val telAccounts = Account.telProviderAccounts()
|
||||||
Utils.alertView(
|
if (telAccounts.isEmpty()) {
|
||||||
this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
String.format(getString(R.string.invalid_sip_uri), uri)
|
getString(R.string.no_telephony_providers))
|
||||||
|
} else {
|
||||||
|
val builder = AlertDialog.Builder(this)
|
||||||
|
with(builder) {
|
||||||
|
setTitle(getString(R.string.choose_telephony_provider_account))
|
||||||
|
setItems(telAccounts) { _, which ->
|
||||||
|
spinToAor("sip:${telAccounts[which]}")
|
||||||
|
makeCall()
|
||||||
|
}
|
||||||
|
setPositiveButton("Cancel") { _: DialogInterface, _: Int -> }
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Utils.telToSip(uriText, ua.account)
|
||||||
|
} else {
|
||||||
|
Utils.uriComplete(uriText, Utils.aorDomain(aor))
|
||||||
|
}
|
||||||
|
if (!Utils.checkUri(uri)) {
|
||||||
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
|
String.format(getString(R.string.invalid_sip_or_tel_uri), uri)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
callUri.isFocusable = false
|
callUri.isFocusable = false
|
||||||
@@ -1686,8 +1723,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (latest != null)
|
if (latest != null)
|
||||||
callUri.setText(
|
callUri.setText(
|
||||||
Utils.friendlyUri(
|
Utils.friendlyUri(
|
||||||
ContactsActivity.contactName(latest.peerUri),
|
ContactsActivity.contactName(latest.peerUri), Utils.aorDomain(aor)
|
||||||
Utils.aorDomain(ua.account.aor)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,15 @@ object Utils {
|
|||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun uriMatch(firstUri: String, secondUri: String): Boolean {
|
||||||
|
if (firstUri.startsWith("tel:"))
|
||||||
|
return firstUri == secondUri
|
||||||
|
if (firstUri.startsWith("sip:"))
|
||||||
|
return uriUserPart(firstUri) == uriUserPart(secondUri) &&
|
||||||
|
uriHostPart(firstUri) == uriHostPart(secondUri)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun uriParams(uri: String): List<String> {
|
private fun uriParams(uri: String): List<String> {
|
||||||
val params = uri.split(";")
|
val params = uri.split(";")
|
||||||
return if (params.size == 1) listOf() else params.subList(1, params.size)
|
return if (params.size == 1) listOf() else params.subList(1, params.size)
|
||||||
@@ -121,7 +130,7 @@ object Utils {
|
|||||||
return if (u.contains("@")) {
|
return if (u.contains("@")) {
|
||||||
val user = uriUserPart(u)
|
val user = uriUserPart(u)
|
||||||
val host = uriHostPart(u)
|
val host = uriHostPart(u)
|
||||||
if (isE164Number(user) || host == domain)
|
if (isTelNumber(user) || host == domain)
|
||||||
user
|
user
|
||||||
else
|
else
|
||||||
"$user@$host"
|
"$user@$host"
|
||||||
@@ -164,10 +173,6 @@ object Utils {
|
|||||||
checkTransport(uri.substringAfter("?"), setOf("udp", "tcp")))
|
checkTransport(uri.substringAfter("?"), setOf("udp", "tcp")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isE164Number(no: String): Boolean {
|
|
||||||
return Regex("^[+][1-9][0-9]{0,14}\$").matches(no)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkIpV4(ip: String): Boolean {
|
fun checkIpV4(ip: String): Boolean {
|
||||||
return Regex("^(([0-1]?[0-9]{1,2}\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$").matches(ip)
|
return Regex("^(([0-1]?[0-9]{1,2}\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$").matches(ip)
|
||||||
}
|
}
|
||||||
@@ -256,6 +261,12 @@ object Utils {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun paramExists(params: String, name: String): Boolean {
|
||||||
|
for (param in params.split(";"))
|
||||||
|
if (param.substringBefore("=") == name) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fun checkHostPortParams(hpp: String) : Boolean {
|
fun checkHostPortParams(hpp: String) : Boolean {
|
||||||
val restParams = hpp.split(";", limit = 2)
|
val restParams = hpp.split(";", limit = 2)
|
||||||
return if (restParams.size == 1)
|
return if (restParams.size == 1)
|
||||||
@@ -264,16 +275,40 @@ object Utils {
|
|||||||
checkHostPort(restParams[0]) && checkParams(restParams[1])
|
checkHostPort(restParams[0]) && checkParams(restParams[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkSipUri(uri: String): Boolean {
|
private fun checkSipUri(uri: String): Boolean {
|
||||||
if (!uri.startsWith("sip:")) return false
|
return if (uri.startsWith("sip:")) {
|
||||||
val userRest = uri.substring(4).split("@")
|
val userRest = uri.substring(4).split("@")
|
||||||
return when (userRest.size) {
|
when (userRest.size) {
|
||||||
1 ->
|
1 ->
|
||||||
checkHostPortParams(userRest[0])
|
checkHostPortParams(userRest[0])
|
||||||
2 ->
|
2 ->
|
||||||
checkUriUser(userRest[0]) && checkHostPortParams(userRest[1])
|
checkUriUser(userRest[0]) && checkHostPortParams(userRest[1])
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isTelNumber(no: String): Boolean {
|
||||||
|
return Regex("^([+][1-9])?[0-9- ]{0,15}\$").matches(no)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isTelUri(uri: String): Boolean {
|
||||||
|
return uri.startsWith("tel:") && isTelNumber(uri.substring(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkUri(uri: String): Boolean {
|
||||||
|
return checkSipUri(uri) || isTelUri(uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun telToSip(telUri: String, account: Account): String {
|
||||||
|
val hostPart = if (account.telProvider != "")
|
||||||
|
account.telProvider
|
||||||
|
else
|
||||||
|
aorDomain(account.aor)
|
||||||
|
return "sip:" + telUri.substring(4).filterNot{setOf('-', ' ').contains(it)} +
|
||||||
|
"@" + hostPart + ";user=phone"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkName(name: String): Boolean {
|
fun checkName(name: String): Boolean {
|
||||||
|
|||||||
@@ -178,6 +178,12 @@
|
|||||||
android:paddingTop="8dp" >
|
android:paddingTop="8dp" >
|
||||||
</Spinner>
|
</Spinner>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/Stun"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/StunServerTitle"
|
android:id="@+id/StunServerTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -242,6 +248,8 @@
|
|||||||
</androidx.appcompat.widget.AppCompatEditText>
|
</androidx.appcompat.widget.AppCompatEditText>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/DtmfModeTitle"
|
android:id="@+id/DtmfModeTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -293,6 +301,25 @@
|
|||||||
android:layout_width="fill_parent">
|
android:layout_width="fill_parent">
|
||||||
</EditText>
|
</EditText>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/TelephonyProviderTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/telephony_provider" >
|
||||||
|
</TextView>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/telephonyProvider"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/telephony_provider_hint"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:inputType="textUri"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:layout_width="fill_parent">
|
||||||
|
</EditText>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -63,19 +63,19 @@
|
|||||||
</EditText>
|
</EditText>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/SipUriTitle"
|
android:id="@+id/SipOrTelUriTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:text="@string/sip_uri" >
|
android:text="@string/sip_or_tel_uri" >
|
||||||
</TextView>
|
</TextView>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/Uri"
|
android:id="@+id/Uri"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/sip_uri"
|
android:hint="@string/user_domain_or_number"
|
||||||
android:inputType="textEmailAddress"
|
android:inputType="textEmailAddress"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:importantForAutofill="no"
|
android:importantForAutofill="no"
|
||||||
|
|||||||
@@ -182,6 +182,13 @@
|
|||||||
messages (Message Waiting Indications) are not subscribed to.
|
messages (Message Waiting Indications) are not subscribed to.
|
||||||
</string>
|
</string>
|
||||||
<string name="invalid_voicemail_uri">Invalid Voicemail URI \'%1$s\'</string>
|
<string name="invalid_voicemail_uri">Invalid Voicemail URI \'%1$s\'</string>
|
||||||
|
<string name="telephony_provider">Telephony Provider</string>
|
||||||
|
<string name="telephony_provider_help">SIP URI host part used in calls to telephone numbers.
|
||||||
|
Factory default is account\'s domain. If not given, this account cannot be used to call
|
||||||
|
telephone numbers.
|
||||||
|
</string>
|
||||||
|
<string name="telephony_provider_hint">SIP URI host part</string>
|
||||||
|
<string name="invalid_sip_uri_hostpart">Invalid SIP URI host part \'%1$s\'</string>
|
||||||
<string name="default_account">Default Account</string>
|
<string name="default_account">Default Account</string>
|
||||||
<string name="default_account_help">If checked, this account is selected when baresip is started.
|
<string name="default_account_help">If checked, this account is selected when baresip is started.
|
||||||
</string>
|
</string>
|
||||||
@@ -247,7 +254,7 @@
|
|||||||
<string name="today">Today</string>
|
<string name="today">Today</string>
|
||||||
<string name="you">You</string>
|
<string name="you">You</string>
|
||||||
<string name="new_chat_peer">New Chat Peer</string>
|
<string name="new_chat_peer">New Chat Peer</string>
|
||||||
<string name="invalid_chat_peer_uri">Invalid SIP URI</string>
|
<string name="invalid_chat_peer_uri">Invalid chat peer URI</string>
|
||||||
<string name="long_chat_question">Do you want to delete chat with peer \'%1$s\' or
|
<string name="long_chat_question">Do you want to delete chat with peer \'%1$s\' or
|
||||||
add peer to contacts?</string>
|
add peer to contacts?</string>
|
||||||
<string name="short_chat_question">Do you want to delete chat with \'%1$s\'?</string>
|
<string name="short_chat_question">Do you want to delete chat with \'%1$s\'?</string>
|
||||||
@@ -341,6 +348,8 @@
|
|||||||
<string name="contact">Contact</string>
|
<string name="contact">Contact</string>
|
||||||
<string name="new_contact">New Contact</string>
|
<string name="new_contact">New Contact</string>
|
||||||
<string name="contact_name">Name</string>
|
<string name="contact_name">Name</string>
|
||||||
|
<string name="sip_or_tel_uri">SIP or tel URI</string>
|
||||||
|
<string name="user_domain_or_number">user@domain or telephone number</string>
|
||||||
<string name="invalid_contact">Invalid contact name \'%1$s\'</string>
|
<string name="invalid_contact">Invalid contact name \'%1$s\'</string>
|
||||||
<string name="contact_already_exists">Contact \'%1$s\' already exists.</string>
|
<string name="contact_already_exists">Contact \'%1$s\' already exists.</string>
|
||||||
<string name="invalid_contact_uri">Invalid SIP URI</string>
|
<string name="invalid_contact_uri">Invalid SIP URI</string>
|
||||||
@@ -353,6 +362,7 @@
|
|||||||
<string name="send_message">Send Message</string>
|
<string name="send_message">Send Message</string>
|
||||||
<string name="contact_delete_question">Do you want to delete contact \'%1$s\'?</string>
|
<string name="contact_delete_question">Do you want to delete contact \'%1$s\'?</string>
|
||||||
<string name="contacts_exceeded">Your maximum number of contacts %1$d has been exceeded.</string>
|
<string name="contacts_exceeded">Your maximum number of contacts %1$d has been exceeded.</string>
|
||||||
|
<string name="no_telephony_providers">Telephony Provider has not been configured for any account.</string>
|
||||||
<!-- Generic -->
|
<!-- Generic -->
|
||||||
<string name="alert">Alert</string>
|
<string name="alert">Alert</string>
|
||||||
<string name="info">Info</string>
|
<string name="info">Info</string>
|
||||||
@@ -376,6 +386,7 @@
|
|||||||
<string name="confirmation">Confirmation</string>
|
<string name="confirmation">Confirmation</string>
|
||||||
<string name="dots" translatable="false">…</string>
|
<string name="dots" translatable="false">…</string>
|
||||||
<string name="bullet_item" translatable="false">\u2022 %1$s</string>
|
<string name="bullet_item" translatable="false">\u2022 %1$s</string>
|
||||||
|
<string name="invalid_sip_or_tel_uri">Invalid SIP or tel URI \'%1$s\'</string>
|
||||||
<!-- Main Activity -->
|
<!-- Main Activity -->
|
||||||
<string name="backup">Backup</string>
|
<string name="backup">Backup</string>
|
||||||
<string name="restore">Restore</string>
|
<string name="restore">Restore</string>
|
||||||
@@ -386,6 +397,7 @@
|
|||||||
<string name="incoming_call_from_dots">Call from …</string>
|
<string name="incoming_call_from_dots">Call from …</string>
|
||||||
<string name="transferring_call_to_dots">Transferring call to …</string>
|
<string name="transferring_call_to_dots">Transferring call to …</string>
|
||||||
<string name="invalid_sip_uri">Invalid SIP URI \'%1$s\'</string>
|
<string name="invalid_sip_uri">Invalid SIP URI \'%1$s\'</string>
|
||||||
|
<string name="choose_telephony_provider_account">Choose Telephony Provider account.</string>
|
||||||
<string name="callee">Callee</string>
|
<string name="callee">Callee</string>
|
||||||
<string name="hangup">Hangup</string>
|
<string name="hangup">Hangup</string>
|
||||||
<string name="video_call">Video call</string>
|
<string name="video_call">Video call</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user