- added support detecting (mwi) and listening of voicemails
- activated via account's voicemail uri
This commit is contained in:
@@ -10,6 +10,10 @@ class Account(val accp: String) {
|
||||
var audioCodec = ArrayList<String>()
|
||||
var regint = account_regint(accp)
|
||||
var mediaenc = account_mediaenc(accp)
|
||||
var vmUri = account_vm_uri(accp)
|
||||
var vmNew = 0
|
||||
var vmOld = 0
|
||||
var missedCalls = false
|
||||
|
||||
init {
|
||||
var i = 0
|
||||
@@ -69,11 +73,45 @@ class Account(val accp: String) {
|
||||
|
||||
if (mediaenc != "") res = res + ";mediaenc=${mediaenc}"
|
||||
|
||||
if (vmUri == "")
|
||||
res = res + ";mwi=no"
|
||||
else
|
||||
res = res + ";vm_uri=\"$vmUri\""
|
||||
|
||||
res = res + ";ptime=20;regint=${regint};regq=0.5;pubint=0;answermode=manual"
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fun vmMessage() : String {
|
||||
var new = ""
|
||||
var old = ""
|
||||
if (vmNew > 0)
|
||||
if (vmNew == 1)
|
||||
new = "$vmNew new message"
|
||||
else
|
||||
new = "$vmNew new messages"
|
||||
if (vmOld > 0)
|
||||
if (vmOld == 1)
|
||||
old = "$vmOld old message"
|
||||
else
|
||||
old = "$vmOld old messages"
|
||||
var msg = "You have"
|
||||
if (new != "") {
|
||||
msg = "$msg $new"
|
||||
if (old != "") msg = "$msg and $old"
|
||||
} else {
|
||||
if (old != "")
|
||||
msg = "$msg $old"
|
||||
else
|
||||
msg = "$msg no messages"
|
||||
}
|
||||
return "$msg."
|
||||
}
|
||||
|
||||
fun host() : String {
|
||||
return aor.split("@")[1]
|
||||
}
|
||||
companion object {
|
||||
|
||||
fun accounts(): ArrayList<Account> {
|
||||
@@ -124,4 +162,6 @@ external fun account_regint(acc: String): Int
|
||||
external fun account_set_regint(acc: String, regint: Int): Int
|
||||
external fun account_mediaenc(acc: String): String
|
||||
external fun account_set_mediaenc(acc: String, mencid: String): Int
|
||||
external fun account_set_audio_codecs(acc: String, codecs: String): Int
|
||||
external fun account_set_audio_codecs(acc: String, codecs: String): Int
|
||||
external fun account_set_mwi(acc: String, value: String): Int
|
||||
external fun account_vm_uri(acc: String): String
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout.LayoutParams
|
||||
import android.widget.*
|
||||
import kotlinx.android.synthetic.main.activity_account.*
|
||||
|
||||
class AccountActivity : AppCompatActivity() {
|
||||
|
||||
@@ -21,6 +22,7 @@ class AccountActivity : AppCompatActivity() {
|
||||
internal lateinit var outbound2: EditText
|
||||
internal lateinit var regCheck: CheckBox
|
||||
internal lateinit var mediaEnc: String
|
||||
internal lateinit var vmUri: EditText
|
||||
|
||||
private var newCodecs = ArrayList<String>()
|
||||
private var save = false
|
||||
@@ -113,6 +115,10 @@ class AccountActivity : AppCompatActivity() {
|
||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||
}
|
||||
}
|
||||
|
||||
vmUri = findViewById(R.id.voicemailUri) as EditText
|
||||
vmUri.setText(acc.vmUri)
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
@@ -259,6 +265,24 @@ class AccountActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
var vmUri = voicemailUri.text.toString().trim()
|
||||
if (vmUri != acc.vmUri) {
|
||||
if (vmUri != "") {
|
||||
if (!vmUri.startsWith("sip:")) vmUri = "sip:$vmUri"
|
||||
if (!vmUri.contains("@")) vmUri = "$vmUri@${acc.host()}"
|
||||
if (!Utils.checkSipUri(vmUri)) {
|
||||
Utils.alertView(this, "Notice",
|
||||
"Invalid Voicemail URI: $vmUri")
|
||||
return false
|
||||
}
|
||||
account_set_mwi(acc.accp, "yes")
|
||||
} else {
|
||||
account_set_mwi(acc.accp, "no")
|
||||
}
|
||||
acc.vmUri = vmUri
|
||||
save = true
|
||||
}
|
||||
|
||||
if (save) {
|
||||
AccountsActivity.saveAccounts()
|
||||
if (UserAgent.ua_update_account(MainActivity.uas[uaIndex].uap) != 0)
|
||||
@@ -308,6 +332,10 @@ class AccountActivity : AppCompatActivity() {
|
||||
Utils.alertView(this, "Media Encryption",
|
||||
getText(R.string.mediaEnc).toString())
|
||||
}
|
||||
findViewById(R.id.VoicemailUriTitle) as TextView -> {
|
||||
Utils.alertView(this, "Voicemail URI",
|
||||
getText(R.string.vmUri).toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ import android.support.v4.content.LocalBroadcastManager
|
||||
import android.os.Build
|
||||
import android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE
|
||||
import java.nio.charset.StandardCharsets
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import java.io.InputStream
|
||||
|
||||
class BaresipService: Service() {
|
||||
|
||||
@@ -125,6 +124,25 @@ class BaresipService: Service() {
|
||||
Utils.copyAssetToFile(applicationContext, a, "$path/$a")
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Asset $a already copied")
|
||||
if (a == "config") {
|
||||
val inputStream: InputStream = file.inputStream()
|
||||
var contents = inputStream.bufferedReader().use { it.readText() }
|
||||
inputStream.close()
|
||||
var write = false
|
||||
if (!contents.contains("zrtp_hash")) {
|
||||
contents = "${contents}zrtp_hash yes\n"
|
||||
write = true
|
||||
}
|
||||
if (contents.contains(Regex("#module_app[ ]+mwi.so"))) {
|
||||
contents = contents.replace(Regex("#module_app[ ]+mwi.so"),
|
||||
"module_app mwi.so")
|
||||
write = true
|
||||
}
|
||||
if (write) {
|
||||
Log.d(LOG_TAG, "Writing $contents")
|
||||
Utils.putFileContents(file, contents)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +257,7 @@ class BaresipService: Service() {
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Ua ${ua.account.aor} is NOT registered")
|
||||
MainActivity.images.add(R.drawable.dot_yellow)
|
||||
ua.register()
|
||||
// ua.register()
|
||||
}
|
||||
val intent = Intent("service event")
|
||||
intent.putExtra("event", "ua added")
|
||||
|
||||
@@ -31,6 +31,8 @@ class CallsActivity : AppCompatActivity() {
|
||||
val listview = findViewById(R.id.calls) as ListView
|
||||
|
||||
val aor = intent.extras.getString("aor")
|
||||
val ua = Account.findUa(aor)
|
||||
|
||||
aorGenerateHistory(aor)
|
||||
|
||||
val adapter = CallListAdapter(this, uaHistory)
|
||||
@@ -84,6 +86,7 @@ class CallsActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
listview.isLongClickable = true
|
||||
ua!!.account.missedCalls = false
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
||||
@@ -2,8 +2,7 @@ package com.tutpro.baresip
|
||||
|
||||
import android.Manifest
|
||||
import android.app.NotificationManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Intent
|
||||
import android.content.*
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
@@ -12,8 +11,6 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.media.AudioManager
|
||||
@@ -46,6 +43,7 @@ class MainActivity : AppCompatActivity() {
|
||||
internal lateinit var answerButton: ImageButton
|
||||
internal lateinit var rejectButton: ImageButton
|
||||
internal lateinit var holdButton: ImageButton
|
||||
internal lateinit var voicemailButton: ImageButton
|
||||
internal lateinit var contactsButton: ImageButton
|
||||
internal lateinit var messagesButton: ImageButton
|
||||
internal lateinit var callsButton: ImageButton
|
||||
@@ -84,6 +82,7 @@ class MainActivity : AppCompatActivity() {
|
||||
rejectButton = findViewById(R.id.rejectButton) as ImageButton
|
||||
holdButton = findViewById(R.id.holdButton) as ImageButton
|
||||
dtmf = findViewById(R.id.dtmf) as EditText
|
||||
voicemailButton = findViewById(R.id.voicemailButton) as ImageButton
|
||||
contactsButton = findViewById(R.id.contactsButton) as ImageButton
|
||||
messagesButton = findViewById(R.id.messagesButton) as ImageButton
|
||||
callsButton = findViewById(R.id.callsButton) as ImageButton
|
||||
@@ -196,6 +195,19 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
else
|
||||
voicemailButton.setImageResource(R.drawable.voicemail)
|
||||
voicemailButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
voicemailButton.visibility = View.INVISIBLE
|
||||
}
|
||||
if (acc.missedCalls)
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
else
|
||||
callsButton.setImageResource(R.drawable.calls)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||
@@ -339,14 +351,45 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
voicemailButton.setOnClickListener {
|
||||
if (aorSpinner.selectedItemPosition >= 0) {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val acc = ua.account
|
||||
if (acc.vmUri != "") {
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
val callIntent = Intent(this, MainActivity::class.java)
|
||||
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
callIntent.putExtra("action", "call")
|
||||
callIntent.putExtra("uap", ua.uap)
|
||||
callIntent.putExtra("peer", acc.vmUri)
|
||||
startActivity(callIntent)
|
||||
}
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
val builder = AlertDialog.Builder(this@MainActivity,
|
||||
R.style.Theme_AppCompat)
|
||||
builder.setTitle("Voicemail Messages")
|
||||
builder.setMessage(acc.vmMessage())
|
||||
.setPositiveButton("Cancel", dialogClickListener)
|
||||
.setNegativeButton("Check", dialogClickListener)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contactsButton.setOnClickListener {
|
||||
val i = Intent(this@MainActivity, ContactsActivity::class.java)
|
||||
val b = Bundle()
|
||||
if (aorSpinner.selectedItemPosition >= 0)
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
else
|
||||
b.putString("aor", "")
|
||||
i.putExtras(b)
|
||||
val b = Bundle()
|
||||
if (aorSpinner.selectedItemPosition >= 0)
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
else
|
||||
b.putString("aor", "")
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, CONTACTS_CODE)
|
||||
}
|
||||
|
||||
@@ -366,7 +409,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val b = Bundle()
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, HISTORY_CODE)
|
||||
startActivityForResult(i, CALLS_CODE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,6 +482,10 @@ class MainActivity : AppCompatActivity() {
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, peer_uri, "in", false))
|
||||
acc.missedCalls = true
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
} else {
|
||||
Log.d("Baresip", "Incoming call $uap/$callp/$peer_uri")
|
||||
calls.add(new_call)
|
||||
@@ -600,9 +647,14 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
calls.remove(call)
|
||||
if (!call.hasHistory) {
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, call.peerURI, call.dir,false))
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, call.peerURI, call.dir,false))
|
||||
if (call.dir == "in") {
|
||||
acc.missedCalls = true
|
||||
if (ua == uas[aorSpinner.selectedItemPosition])
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
}
|
||||
if (calls.size == 0) am.mode = AudioManager.MODE_NORMAL
|
||||
if (am.isSpeakerphoneOn) {
|
||||
@@ -635,6 +687,22 @@ class MainActivity : AppCompatActivity() {
|
||||
startActivity(i)
|
||||
}
|
||||
}
|
||||
"mwi notify" -> {
|
||||
val lines = ev[1].split("\n")
|
||||
for (line in lines) {
|
||||
if (line.startsWith("Voice-Message:")) {
|
||||
val counts = (line.split(" ")[1]).split("/")
|
||||
acc.vmNew = counts[0].toInt()
|
||||
acc.vmOld = counts[1].toInt()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (ua == uas[aorSpinner.selectedItemPosition])
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
else
|
||||
voicemailButton.setImageResource(R.drawable.voicemail)
|
||||
}
|
||||
else -> Log.w("Baresip", "Unknown event '${ev[0]}'")
|
||||
}
|
||||
break
|
||||
@@ -727,7 +795,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Log.d("Baresip", "Resumed")
|
||||
Log.d("Baresip", "Resumed")
|
||||
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
|
||||
visible = true
|
||||
if (answerCall != "") {
|
||||
@@ -814,10 +882,33 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
ACCOUNTS_CODE -> {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
else
|
||||
voicemailButton.setImageResource(R.drawable.voicemail)
|
||||
voicemailButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
voicemailButton.visibility = View.INVISIBLE
|
||||
}
|
||||
baresipService.setAction("UpdateNotification")
|
||||
startService(baresipService)
|
||||
}
|
||||
|
||||
ACCOUNT_CODE -> {
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
else
|
||||
voicemailButton.setImageResource(R.drawable.voicemail)
|
||||
voicemailButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
voicemailButton.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
CONTACTS_CODE -> {
|
||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
ContactsActivity.contacts.map{Contact -> Contact.name}))
|
||||
@@ -834,7 +925,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
HISTORY_CODE -> {
|
||||
CALLS_CODE -> {
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (data != null) {
|
||||
(findViewById(R.id.uri) as EditText).setText(data.getStringExtra("peer_uri"))
|
||||
@@ -842,10 +934,11 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
if (resultCode == RESULT_CANCELED) {
|
||||
Log.d("Baresip", "History canceled")
|
||||
if (CallHistory.aorHistory(history, uas[aorSpinner.selectedItemPosition].account.aor) == 0) {
|
||||
if (CallHistory.aorHistory(history, acc.aor) == 0) {
|
||||
holdButton.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
callsButton.setImageResource(R.drawable.calls)
|
||||
}
|
||||
|
||||
ABOUT_CODE -> {
|
||||
@@ -972,7 +1065,7 @@ class MainActivity : AppCompatActivity() {
|
||||
const val ACCOUNTS_CODE = 1
|
||||
const val CONTACTS_CODE = 2
|
||||
const val EDIT_CONFIG_CODE = 3
|
||||
const val HISTORY_CODE = 4
|
||||
const val CALLS_CODE = 4
|
||||
const val ABOUT_CODE = 5
|
||||
const val ACCOUNT_CODE = 6
|
||||
const val CONTACT_CODE = 7
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
Reference in New Issue
Block a user