improved calls/messages/contacts implemtation

used vector image assets
This commit is contained in:
Juha Heinanen
2018-07-29 16:32:27 +03:00
parent 5de8d43578
commit 59d22b12ab
38 changed files with 435 additions and 337 deletions

2
.gitignore vendored
View File

@ -11,3 +11,5 @@ local.properties
build
/captures
.externalNativeBuild
app/release

View File

@ -6,9 +6,10 @@ PCMU/PCMA and opus voice codecs, as well as ZRTP and (DTLS) SRTP media
encapsulation.
The static libraries and include files in distribution directory have
been produced using https://github.com/alfredh/baresip-android after
applying reg.c-patch to re/src/sipreg/reg.c. The patch is needed due to
re timer sometimes firing too late.
been produced using https://github.com/alfredh/baresip-android. Use
latest versions of baresip, re, and rem. Then apply reg.c-patch to
re/src/sipreg/reg.c. The patch is needed due to re timer sometimes
firing too late.
After cloning the project, in android-studio:

View File

@ -93,7 +93,7 @@
android:value="com.tutpro.baresip.MainActivity" />
</activity>
<activity
android:name=".HistoryActivity"
android:name=".CallsActivity"
android:label="Call History"
android:parentActivityName=".MainActivity">
<meta-data
@ -110,7 +110,7 @@
</activity>
<activity
android:name=".MessageActivity"
android:label="Message"
android:label="Message or Call"
android:parentActivityName=".MessagesActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"

View File

@ -115,7 +115,7 @@ class BaresipService: Service() {
val fis = FileInputStream(file)
val ois = ObjectInputStream(fis)
@SuppressWarnings("unchecked")
MainActivity.history = ois.readObject() as ArrayList<History>
MainActivity.history = ois.readObject() as ArrayList<CallHistory>
Log.d(LOG_TAG, "Restored History of ${MainActivity.history.size} entries")
ois.close()
fis.close()
@ -233,6 +233,13 @@ class BaresipService: Service() {
fun uaEvent(event: String, uap: String, callp: String) {
Log.d(LOG_TAG, "updateStatus got event $event/$uap/$callp")
if (!IS_SERVICE_RUNNING) return
if (event == "exit") {
val intent = Intent("service event")
intent.putExtra("event", event)
intent.putExtra("params", arrayListOf<String>())
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
return
}
val ua = UserAgent.find(MainActivity.uas, uap)
if (ua == null) {
Log.w(LOG_TAG, "updateStatus did not find ua $uap")
@ -411,7 +418,7 @@ class BaresipService: Service() {
}
private fun cleanStop() {
HistoryActivity.saveHistory()
CallsActivity.saveHistory()
MessagesActivity.saveMessages()
MainActivity.uas.clear()
MainActivity.images.clear()

View File

@ -3,14 +3,14 @@ package com.tutpro.baresip
import java.io.Serializable
import java.util.GregorianCalendar
class History(val aor: String, val peerURI: String, val direction: String,
class CallHistory(val aor: String, val peerURI: String, val direction: String,
val connected: Boolean) : Serializable {
val time: GregorianCalendar = GregorianCalendar()
companion object {
fun aorHistory(history: ArrayList<History>, aor: String): Int {
fun aorHistory(history: ArrayList<CallHistory>, aor: String): Int {
var size = 0;
for (h in history) {
if (h.aor == aor) size++
@ -18,7 +18,7 @@ class History(val aor: String, val peerURI: String, val direction: String,
return size
}
fun aorRemoveHistory(history: ArrayList<History>, aor: String) {
fun aorRemoveHistory(history: ArrayList<CallHistory>, aor: String) {
for (h in history) {
if (h.aor == aor) {
history.remove(h)
@ -27,7 +27,7 @@ class History(val aor: String, val peerURI: String, val direction: String,
}
}
fun aorLatestHistory(history: ArrayList<History>, aor: String): History? {
fun aorLatestHistory(history: ArrayList<CallHistory>, aor: String): CallHistory? {
for (h in history.reversed())
if (h.aor == aor) return h
return null

View File

@ -10,8 +10,8 @@ import android.widget.LinearLayout
import android.widget.TextView
import java.util.*
class HistoryListAdapter(private val cxt: Context, private val rows: ArrayList<HistoryRow>) :
ArrayAdapter<HistoryRow>(cxt, R.layout.history_row, rows) {
class CallListAdapter(private val cxt: Context, private val rows: ArrayList<CallRow>) :
ArrayAdapter<CallRow>(cxt, R.layout.history_row, rows) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val row = rows[position]
@ -35,7 +35,12 @@ class HistoryListAdapter(private val cxt: Context, private val rows: ArrayList<H
count++
}
val peerURIView = rowView.findViewById(R.id.peer_uri) as TextView
peerURIView.text = row.peerURI
val contactName = ContactsActivity.contactName(row.peerURI)
if (contactName.startsWith("sip:") &&
(Utils.uriHostPart(row.peerURI) == Utils.uriHostPart(row.aor)))
peerURIView.text = Utils.uriUserPart(row.peerURI)
else
peerURIView.text = contactName
val timeView = rowView.findViewById(R.id.time) as TextView
timeView.text = row.time
return rowView

View File

@ -1,7 +1,6 @@
package com.tutpro.baresip
class HistoryRow(val peerURI: String, val peerDomain: String, val direction: Int, val time: String,
val index: Int) {
class CallRow(val aor: String, val peerURI: String, val direction: Int, val time: String, val index: Int) {
val directions = ArrayList<Int>()
val indexes = ArrayList<Int>()

View File

@ -20,9 +20,9 @@ import java.util.ArrayList
import java.util.Calendar
import java.util.GregorianCalendar
class HistoryActivity : AppCompatActivity() {
class CallsActivity : AppCompatActivity() {
internal var uaHistory = ArrayList<HistoryRow>()
internal var uaHistory = ArrayList<CallRow>()
internal var aor: String = ""
public override fun onCreate(savedInstanceState: Bundle?) {
@ -34,15 +34,16 @@ class HistoryActivity : AppCompatActivity() {
aor = intent.extras.getString("aor")
aorGenerateHistory(aor)
val adapter = HistoryListAdapter(this, uaHistory)
val adapter = CallListAdapter(this, uaHistory)
listview.adapter = adapter
listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
val i = Intent()
i.putExtra("peer_uri", uaHistory[position].peerURI)
setResult(Activity.RESULT_OK, i)
finish()
listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
val i = Intent(this@CallsActivity, MessageActivity::class.java)
val b = Bundle()
b.putString("aor", aor)
b.putString("peer", uaHistory[pos].peerURI)
i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE)
}
listview.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) {
@ -51,11 +52,7 @@ class HistoryActivity : AppCompatActivity() {
val b = Bundle()
b.putBoolean("new", true)
b.putString("name", "New Name")
if (uaHistory[pos].peerDomain == "")
b.putString("uri", uaHistory[pos].peerURI)
else
b.putString("uri", "sip:${uaHistory[pos].peerURI}@" +
uaHistory[pos].peerDomain)
i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE)
}
@ -72,14 +69,19 @@ class HistoryActivity : AppCompatActivity() {
}
}
}
val builder = AlertDialog.Builder(this@HistoryActivity,
R.style.Theme_AppCompat)
val builder = AlertDialog.Builder(this@CallsActivity, R.style.Theme_AppCompat)
if (ContactsActivity.contactName(uaHistory[pos].peerURI).startsWith("sip:"))
builder.setMessage("Do you want to add ${uaHistory[pos].peerURI} to contacs or " +
"delete it from call history?")
"delete call(s) from history?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener)
.setNeutralButton("Add Contact", dialogClickListener)
.show()
else
builder.setMessage("Do you want to delete call(s) from history?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener)
.show()
true
}
@ -89,7 +91,7 @@ class HistoryActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
Log.d("Baresip", "Back array was pressed at History")
Log.d("Baresip", "Back array was pressed at Calls")
val i = Intent()
setResult(Activity.RESULT_CANCELED, i)
finish()
@ -103,12 +105,6 @@ class HistoryActivity : AppCompatActivity() {
for (i in MainActivity.history.indices.reversed()) {
val h = MainActivity.history[i]
if (h.aor == aor) {
var peer_uri = h.peerURI
var peer_domain = ""
if (Utils.uriHostPart(peer_uri) == Utils.uriHostPart(aor)) {
peer_uri = Utils.uriUserPart(peer_uri)
peer_domain = Utils.uriHostPart(aor)
}
var direction: Int
if (h.direction == "in")
if (h.connected)
@ -120,7 +116,7 @@ class HistoryActivity : AppCompatActivity() {
direction = R.drawable.arrow_up_green
else
direction = R.drawable.arrow_up_red
if (uaHistory.isNotEmpty() && (uaHistory.last().peerURI == peer_uri)) {
if (uaHistory.isNotEmpty() && (uaHistory.last().peerURI == h.peerURI)) {
uaHistory.last().directions.add(direction)
uaHistory.last().indexes.add(i)
} else {
@ -132,7 +128,7 @@ class HistoryActivity : AppCompatActivity() {
val fmt = SimpleDateFormat("dd.MM")
time = fmt.format(h.time.time)
}
uaHistory.add(HistoryRow(peer_uri, peer_domain, direction, time, i))
uaHistory.add(CallRow(h.aor, h.peerURI, direction, time, i))
}
}
}

View File

@ -1,3 +0,0 @@
package com.tutpro.baresip
class Codec(val name: String, val rate: Int, val channels: Int) {}

View File

@ -17,26 +17,23 @@ class ContactActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contact)
new = intent.extras.getBoolean("new")
val name: String
val uri: String
if (new) {
name = intent.extras.getString("name")
uri = intent.extras.getString("uri")
nameView = findViewById(R.id.Name) as EditText
uriView = findViewById(R.id.Uri) as EditText
if (intent.extras.getBoolean("new")) {
setTitle("New Contact")
nameView.setText("")
nameView.hint = "Contact name"
nameView.setSelection(nameView.text.length)
uriView.setText("")
uriView.hint = "SIP URI"
} else {
index = intent.extras.getInt("index")
name = ContactsActivity.contacts[index].name
uri = ContactsActivity.contacts[index].uri
}
val name = ContactsActivity.contacts[index].name
setTitle(name)
nameView = findViewById(R.id.Name) as EditText
nameView.setText(name)
if (new) nameView.setSelection(nameView.text.length)
uriView = findViewById(R.id.Uri) as EditText
uriView.setText(uri)
uriView.setText(ContactsActivity.contacts[index].uri)
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@ -34,23 +34,6 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
i.putExtras(b)
(cxt as Activity).startActivityForResult(i, MainActivity.CONTACT_CODE)
}
val actionView = rowView.findViewById(R.id.contactAction) as ImageButton
actionView.setImageResource(R.drawable.action_remove)
actionView.setOnClickListener { _ ->
Log.d("Baresip", "Delete button clicked")
val deleteDialog = AlertDialog.Builder(cxt)
deleteDialog.setMessage("Do you want to delete contact ${row.name}")
deleteDialog.setPositiveButton("Delete") { dialog, _ ->
ContactsActivity.contacts.removeAt(position)
ContactsActivity.saveContacts()
this.notifyDataSetChanged()
dialog.dismiss()
}
deleteDialog.setNegativeButton("No") { dialog, _ ->
dialog.dismiss()
}
deleteDialog.create().show()
}
return rowView
}
}

View File

@ -1,57 +1,63 @@
package com.tutpro.baresip
import android.app.Activity
import android.content.Intent
import android.content.*
import android.os.Bundle
import android.os.SystemClock
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.MenuItem
import android.widget.*
import android.widget.AdapterView
import android.widget.ImageButton
import android.widget.ListView
import java.io.File
import java.util.ArrayList
class ContactsActivity : AppCompatActivity() {
internal lateinit var layout: LinearLayout
internal var name: String = ""
lateinit var clAdapter: ContactListAdapter
internal lateinit var clAdapter: ContactListAdapter
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contacts)
val listview = findViewById(R.id.contacts) as ListView
val listView = findViewById(R.id.contacts) as ListView
Log.d("Baresip", "Got ${contacts.size} contacts")
clAdapter = ContactListAdapter(this, contacts)
listview.adapter = clAdapter
listView.adapter = clAdapter
val addContactButton = findViewById(R.id.addContact) as ImageButton
val newNameView = findViewById(R.id.newName) as EditText
addContactButton.setOnClickListener{
val name = newNameView.text.toString().trim()
if (!Utils.checkName(name)) {
Log.e("Baresip", "Invalid contact name $name")
Utils.alertView(this, "Notice",
"Invalid contact name: $name")
} else if (nameExists(name)) {
Utils.alertView(this, "Notice",
"Contact $name already exists")
} else {
newNameView.setText("")
newNameView.hint = "Contact name"
newNameView.clearFocus()
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) {
DialogInterface.BUTTON_NEGATIVE -> {
ContactsActivity.contacts.removeAt(pos)
ContactsActivity.saveContacts()
clAdapter.notifyDataSetChanged()
}
DialogInterface.BUTTON_POSITIVE -> {
}
}
}
val builder = AlertDialog.Builder(this@ContactsActivity,
R.style.Theme_AppCompat)
builder.setMessage("Do you want to delete ${contacts[pos].name}?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete Contact", dialogClickListener)
.show()
true
}
val plusButton = findViewById(R.id.plusButton) as ImageButton
plusButton.setOnClickListener {
val i = Intent(this, ContactActivity::class.java)
val b = Bundle()
b.putBoolean("new", true)
b.putString("name", name)
b.putString("uri", "")
i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == RESULT_OK) {

View File

@ -40,6 +40,7 @@ class MainActivity : AppCompatActivity() {
internal lateinit var securityButton: ImageButton
internal lateinit var callButton: ImageButton
internal lateinit var holdButton: ImageButton
internal lateinit var contactsButton: ImageButton
internal lateinit var messagesButton: ImageButton
internal lateinit var callsButton: ImageButton
internal lateinit var dtmf: EditText
@ -72,6 +73,7 @@ class MainActivity : AppCompatActivity() {
securityButton = findViewById(R.id.securityButton) as ImageButton
callButton = findViewById(R.id.callButton) as ImageButton
holdButton = findViewById(R.id.holdButton) as ImageButton
contactsButton = findViewById(R.id.contactsButton) as ImageButton
messagesButton = findViewById(R.id.messagesButton) as ImageButton
callsButton = findViewById(R.id.callsButton) as ImageButton
dtmf = findViewById(R.id.dtmf) as EditText
@ -115,7 +117,7 @@ class MainActivity : AppCompatActivity() {
callee.text.clear()
callee.hint = "Callee"
callButton.tag = "Call"
callButton.setImageResource(R.drawable.call)
callButton.setImageResource(R.drawable.call_green)
securityButton.visibility = View.INVISIBLE
dtmf.visibility = View.INVISIBLE
} else {
@ -123,9 +125,9 @@ class MainActivity : AppCompatActivity() {
callButton.tag = callsOut[0].status
if (callsOut[0].status == "Hangup") {
if (callsOut[0].hold) {
holdButton.setImageResource(R.drawable.resume)
holdButton.setImageResource(R.drawable.play)
} else {
holdButton.setImageResource(R.drawable.hold)
holdButton.setImageResource(R.drawable.pause)
}
holdButton.visibility = View.VISIBLE
securityButton.setImageResource(callsOut[0].security)
@ -144,8 +146,8 @@ class MainActivity : AppCompatActivity() {
}
val view_count = layout.childCount
// Log.d("Baresip", "View count is $view_count")
if (view_count > 8)
layout.removeViews(8, view_count - 8)
if (view_count > 6)
layout.removeViews(6, view_count - 6)
for (c in Call.uaCalls(calls, ua, "in"))
for (call_index in Call.uaCalls(calls, ua, "in").indices) {
val startIndex = (call_index + 1) * 10
@ -192,10 +194,6 @@ class MainActivity : AppCompatActivity() {
}
}
callee.threshold = 2
callee.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
ContactsActivity.contacts.map { Contact -> Contact.name }))
securityButton.setOnClickListener {
when (securityButton.tag) {
"red" -> {
@ -248,7 +246,7 @@ class MainActivity : AppCompatActivity() {
}
call(ua, uri)
} else {
val latest = History.aorLatestHistory(history, aor)
val latest = CallHistory.aorLatestHistory(history, aor)
if (latest != null)
if (Utils.uriHostPart(latest.peerURI) == Utils.uriHostPart(aor))
callee.setText(Utils.uriUserPart(latest.peerURI))
@ -286,11 +284,16 @@ class MainActivity : AppCompatActivity() {
call_unhold(call.callp)
call.hold = false
holdButton.tag = "Hold"
holdButton.setImageResource(R.drawable.hold)
holdButton.setImageResource(R.drawable.pause)
}
}
}
contactsButton.setOnClickListener {
val i = Intent(this@MainActivity, ContactsActivity::class.java)
startActivityForResult(i, CONTACTS_CODE)
}
messagesButton.setOnClickListener {
val i = Intent(this@MainActivity, MessagesActivity::class.java)
val b = Bundle()
@ -299,9 +302,8 @@ class MainActivity : AppCompatActivity() {
startActivityForResult(i, MESSAGES_CODE)
}
callsButton.visibility = View.VISIBLE
callsButton.setOnClickListener {
val i = Intent(this@MainActivity, HistoryActivity::class.java)
val i = Intent(this@MainActivity, CallsActivity::class.java)
val b = Bundle()
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
i.putExtras(b)
@ -314,11 +316,26 @@ class MainActivity : AppCompatActivity() {
startService(baresipService)
}
callee.threshold = 2
callee.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
ContactsActivity.contacts.map { Contact -> Contact.name }))
if (intent.hasExtra("onStartup"))
moveTaskToBack(true)
}
private fun handleServiceEvent(event: String, params: ArrayList<String>) {
if (event == "exit") {
if (BaresipService.IS_SERVICE_RUNNING) {
baresipService.setAction("Stop");
startService(baresipService)
}
Toast.makeText(getApplicationContext(),
"Baresip has stopped! Check your network connectivity.",
Toast.LENGTH_SHORT).show()
finish()
return
}
val uap = params[0]
val ua = UserAgent.find(uas, uap)
if (ua == null) {
@ -346,9 +363,9 @@ class MainActivity : AppCompatActivity() {
if (ONE_CALL_ONLY && (calls.size > 0)) {
Log.d("Baresip", "Auto-rejecting incoming call $uap/$callp/$peer_uri")
ua_hangup(uap, callp, 486, "Busy Here")
if (History.aorHistory(history, aor) > HISTORY_SIZE)
History.aorRemoveHistory(history, aor)
history.add(History(aor, peer_uri, "in", false))
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
CallHistory.aorRemoveHistory(history, aor)
history.add(CallHistory(aor, peer_uri, "in", false))
} else {
Log.d("Baresip", "Incoming call $uap/$callp/$peer_uri")
calls.add(new_call)
@ -381,7 +398,7 @@ class MainActivity : AppCompatActivity() {
callButton.tag = "Hangup"
callButton.setImageResource(R.drawable.hangup)
holdButton.tag = "Hold"
holdButton.setImageResource(R.drawable.hold)
holdButton.setImageResource(R.drawable.pause)
holdButton.visibility = View.VISIBLE
if (acc.mediaenc == "") {
securityButton.visibility = View.INVISIBLE
@ -396,7 +413,7 @@ class MainActivity : AppCompatActivity() {
dtmf.requestFocus()
dtmf.addTextChangedListener(call.dtmfWatcher)
}
history.add(History(aor, call.peerURI, "out", true))
history.add(CallHistory(aor, call.peerURI, "out", true))
call.hasHistory = true
} else {
Log.d("Baresip", "Inbound call $callp established")
@ -412,10 +429,10 @@ class MainActivity : AppCompatActivity() {
securityButton.visibility = View.VISIBLE
val rejectButton = findViewById(view_id + 3) as ImageButton
rejectButton.tag = "Hold"
rejectButton.setImageResource(R.drawable.hold)
rejectButton.setImageResource(R.drawable.pause)
}
}
history.add(History(aor, call.peerURI, "in", true))
history.add(CallHistory(aor, call.peerURI, "in", true))
call.hasHistory = true
}
if (rtTimer != null) {
@ -428,8 +445,8 @@ class MainActivity : AppCompatActivity() {
// am.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
// (am.getStreamMaxVolume(STREAM_VOICE_CALL) / 2) + 1,
// AudioManager.STREAM_VOICE_CALL)
if (History.aorHistory(history, aor) > HISTORY_SIZE)
History.aorRemoveHistory(history, aor)
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
CallHistory.aorRemoveHistory(history, aor)
}
"call verify" -> {
val callp = params[1]
@ -545,12 +562,11 @@ class MainActivity : AppCompatActivity() {
addCallViews(ua, callsIn[i], (i + 1) * 10)
}
}
callsButton.visibility = View.VISIBLE
}
if (!call.hasHistory) {
if (History.aorHistory(history, aor) > HISTORY_SIZE)
History.aorRemoveHistory(history, aor)
history.add(History(aor, call.peerURI, "in", false))
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
CallHistory.aorRemoveHistory(history, aor)
history.add(CallHistory(aor, call.peerURI, "in", false))
}
stopRinging()
} else {
@ -558,7 +574,7 @@ class MainActivity : AppCompatActivity() {
call.peerURI)
if (ua == uas[aorSpinner.selectedItemPosition]) {
callButton.tag = "Call"
callButton.setImageResource(R.drawable.call)
callButton.setImageResource(R.drawable.call_green)
callButton.isEnabled = true
callee.setText("")
callee.hint = "Callee"
@ -569,14 +585,12 @@ class MainActivity : AppCompatActivity() {
securityButton.visibility = View.INVISIBLE
dtmf.removeTextChangedListener(call.dtmfWatcher)
dtmf.visibility = View.INVISIBLE
messagesButton.visibility = View.VISIBLE
callsButton.visibility = View.VISIBLE
}
calls.remove(call)
if (!call.hasHistory) {
if (History.aorHistory(history, aor) > HISTORY_SIZE)
History.aorRemoveHistory(history, aor)
history.add(History(aor, call.peerURI, "out",
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
CallHistory.aorRemoveHistory(history, aor)
history.add(CallHistory(aor, call.peerURI, "out",
false))
}
}
@ -613,6 +627,29 @@ class MainActivity : AppCompatActivity() {
val action = intent.getStringExtra("action")
Log.d("Baresip", "Got onNewIntent action $action")
when (action) {
"call" -> {
if (!calls.isEmpty()) {
Toast.makeText(getApplicationContext(), "You already have an active call!",
Toast.LENGTH_SHORT).show()
return
}
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(MainActivity.uas, uap)
if (ua == null) {
Log.e("Baresip", "onNewIntent did not find ua $uap")
return
}
val aor = ua.account.aor
if (ua != uas[aorSpinner.selectedItemPosition]) {
for (account_index in uas.indices) {
if (uas[account_index].account.aor == aor) {
aorSpinner.setSelection(account_index)
break
}
}
}
makeCall = intent.getStringExtra("peer")
}
"answer" -> {
answerCall = intent.getStringExtra("callp")
}
@ -673,18 +710,23 @@ class MainActivity : AppCompatActivity() {
// Log.d("Baresip", "Resumed")
imm.hideSoftInputFromWindow(callee.windowToken, 0)
visible = true
if ((answerCall != "") && (layout.childCount > 8)) {
if ((answerCall != "") && (layout.childCount > 6)) {
answerCall = ""
/* if multiple calls, right answer button needs to be searched */
val answerButton = layout.findViewById(10 + 5) as ImageButton
answerButton.performClick()
}
if ((rejectCall != "") && (layout.childCount > 8)) {
if ((rejectCall != "") && (layout.childCount > 6)) {
rejectCall = ""
/* if multiple calls, right reject button needs to be searched */
val rejectButton = layout.findViewById(10 + 6) as ImageButton
rejectButton.performClick()
}
if (makeCall != "") {
callee.setText(makeCall)
makeCall = ""
callButton.performClick()
}
}
override fun onBackPressed() {
@ -789,7 +831,7 @@ class MainActivity : AppCompatActivity() {
}
if (resultCode == RESULT_CANCELED) {
Log.d("Baresip", "History canceled")
if (History.aorHistory(history, uas[aorSpinner.selectedItemPosition].account.aor) == 0) {
if (CallHistory.aorHistory(history, uas[aorSpinner.selectedItemPosition].account.aor) == 0) {
holdButton.visibility = View.INVISIBLE
}
}
@ -922,9 +964,10 @@ class MainActivity : AppCompatActivity() {
val answer_button = ImageButton(applicationContext)
answer_button.tag = call.status
if (call.status == "Answer")
answer_button.setImageResource(R.drawable.call)
answer_button.setImageResource(R.drawable.call_green)
else
answer_button.setImageResource(R.drawable.hangup)
answer_button.background = null
answer_button.id = answer_row.id + 1
answer_button.setOnClickListener { v ->
when ((v as ImageButton).tag) {
@ -938,7 +981,7 @@ class MainActivity : AppCompatActivity() {
answer_button.setImageResource(R.drawable.hangup)
val reject_button = layout.findViewById(answer_button.id + 1) as ImageButton
reject_button.tag = "Hold"
reject_button.setImageResource(R.drawable.hold)
reject_button.setImageResource(R.drawable.pause)
}
}
"Hangup" -> {
@ -964,12 +1007,13 @@ class MainActivity : AppCompatActivity() {
} else {
if (call.hold) {
reject_button.tag = "Resume"
reject_button.setImageResource(R.drawable.resume)
reject_button.setImageResource(R.drawable.play)
} else {
reject_button.tag = "Hold"
reject_button.setImageResource(R.drawable.hold)
reject_button.setImageResource(R.drawable.pause)
}
}
reject_button.background = null
reject_button.id = answer_button.id + 1
reject_button.setOnClickListener { v ->
when ((v as ImageButton).tag) {
@ -985,7 +1029,7 @@ class MainActivity : AppCompatActivity() {
"Resume" -> {
call_unhold(call.callp)
v.tag = "Hold"
reject_button.setImageResource(R.drawable.hold)
reject_button.setImageResource(R.drawable.pause)
call.hold = false
}
}
@ -1023,7 +1067,7 @@ class MainActivity : AppCompatActivity() {
call_hold(call.callp)
call.hold = true
button.tag = "Resume"
button.setImageResource(R.drawable.resume)
button.setImageResource(R.drawable.play)
}
private fun startRinging() {
@ -1062,11 +1106,12 @@ class MainActivity : AppCompatActivity() {
var uas = ArrayList<UserAgent>()
internal var images = ArrayList<Int>()
var history: ArrayList<History> = ArrayList()
var history: ArrayList<CallHistory> = ArrayList()
internal var calls = ArrayList<Call>()
internal var messages = ArrayList<Message>()
var filesPath = ""
var visible = true
var makeCall = ""
var answerCall = ""
var rejectCall = ""

View File

@ -15,6 +15,7 @@ class MessageActivity : AppCompatActivity() {
internal lateinit var receiver: AutoCompleteTextView
internal lateinit var message: EditText
internal lateinit var sendButton: ImageButton
internal lateinit var callButton: ImageButton
internal lateinit var imm: InputMethodManager
override fun onCreate(savedInstanceState: Bundle?) {
@ -24,7 +25,7 @@ class MessageActivity : AppCompatActivity() {
val aor = intent.extras.getString("aor")
val peerURI = intent.extras.getString("peer")
val reply = intent.extras.getBoolean("reply")
Log.d("Baresip", "peerURI is $peerURI")
val ua = Account.findUa(aor)
if (ua == null) {
@ -39,10 +40,7 @@ class MessageActivity : AppCompatActivity() {
receiver = findViewById(R.id.receiver) as AutoCompleteTextView
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (reply)
title.text = "Message reply to ..."
else
title.text = "Message to ..."
title.text = "Message or call to ..."
if (peerURI == "") {
receiver.threshold = 2
receiver.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
@ -52,7 +50,6 @@ class MessageActivity : AppCompatActivity() {
receiver.setText(ContactsActivity.contactName(peerURI), false)
message.requestFocus()
}
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)
sendButton = findViewById(R.id.sendButton) as ImageButton
sendButton.setOnClickListener {
@ -85,6 +82,20 @@ class MessageActivity : AppCompatActivity() {
}
}
}
callButton = findViewById(R.id.callButton) as ImageButton
callButton.setOnClickListener {
imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0)
imm.hideSoftInputFromWindow(message.getWindowToken(), 0)
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", ContactsActivity.contactName(peerURI))
startActivity(callIntent)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import java.text.SimpleDateFormat
import java.util.*
@ -22,7 +23,12 @@ class MessageListAdapter(private val cxt: Context, private val rows: ArrayList<M
val directionView = messageView.findViewById(R.id.direction) as ImageView
directionView.setImageResource(message.direction)
val peerView = messageView.findViewById(R.id.peer) as TextView
peerView.text = ContactsActivity.contactName(message.peerURI)
val contactName = ContactsActivity.contactName(message.peerURI)
if (contactName.startsWith("sip:") &&
(Utils.uriHostPart(message.peerURI) == Utils.uriHostPart(message.aor)))
peerView.text = Utils.uriUserPart(message.peerURI)
else
peerView.text = contactName
val timeView = messageView.findViewById(R.id.time) as TextView
val time: String
val cal = GregorianCalendar()

View File

@ -11,6 +11,7 @@ import android.view.MenuItem
import android.widget.AdapterView
import android.widget.ImageButton
import android.widget.ListView
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
@ -28,7 +29,7 @@ class MessagesActivity: AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_messages)
val listView = findViewById(R.id.message) as ListView
val listView = findViewById(R.id.messages) as ListView
plusButton = findViewById(R.id.plusButton) as ImageButton
aor = intent.extras.getString("aor")
@ -43,7 +44,6 @@ class MessagesActivity: AppCompatActivity() {
val b = Bundle()
b.putString("aor", aor)
b.putString("peer", uaMessages[pos].peerURI)
b.putBoolean("reply", uaMessages[pos].direction == R.drawable.arrow_down_green)
i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE)
}
@ -51,6 +51,15 @@ class MessagesActivity: AppCompatActivity() {
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) {
DialogInterface.BUTTON_NEUTRAL -> {
val i = Intent(this, ContactActivity::class.java)
val b = Bundle()
b.putBoolean("new", true)
b.putString("name", "New Name")
b.putString("uri", uaMessages[pos].peerURI)
i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE)
}
DialogInterface.BUTTON_NEGATIVE -> {
MainActivity.messages.remove(uaMessages[pos])
uaMessages.removeAt(pos)
@ -68,10 +77,17 @@ class MessagesActivity: AppCompatActivity() {
val builder = AlertDialog.Builder(this@MessagesActivity,
R.style.Theme_AppCompat)
builder.setMessage("Delete message from " +
ContactsActivity.contactName(uaMessages[pos].peerURI) + "?")
if (ContactsActivity.contactName(uaMessages[pos].peerURI).startsWith("sip:"))
builder.setMessage("Do you want to add ${uaMessages[pos].peerURI} to contacs or " +
"delete message from history?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener)
.setNeutralButton("Add Contact", dialogClickListener)
.show()
else
builder.setMessage("Do you want to delete message from history?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener)
.show()
true
}
@ -91,7 +107,6 @@ class MessagesActivity: AppCompatActivity() {
val b = Bundle()
b.putString("aor", aor)
b.putString("peer", peer)
b.putBoolean("reply", true)
i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 B

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,5 @@
<vector android:height="36dp" android:tint="#00ACC1"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="36dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#01DF01"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#00ACC1"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#DF0101"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,9c-1.6,0 -3.15,0.25 -4.6,0.72v3.1c0,0.39 -0.23,0.74 -0.56,0.9 -0.98,0.49 -1.87,1.12 -2.66,1.85 -0.18,0.18 -0.43,0.28 -0.7,0.28 -0.28,0 -0.53,-0.11 -0.71,-0.29L0.29,13.08c-0.18,-0.17 -0.29,-0.42 -0.29,-0.7 0,-0.28 0.11,-0.53 0.29,-0.71C3.34,8.78 7.46,7 12,7s8.66,1.78 11.71,4.67c0.18,0.18 0.29,0.43 0.29,0.71 0,0.28 -0.11,0.53 -0.29,0.71l-2.48,2.48c-0.18,0.18 -0.43,0.29 -0.71,0.29 -0.27,0 -0.52,-0.11 -0.7,-0.28 -0.79,-0.74 -1.69,-1.36 -2.67,-1.85 -0.33,-0.16 -0.56,-0.5 -0.56,-0.9v-3.1C15.15,9.25 13.6,9 12,9z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,4 @@
<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M9,16h2L11,8L9,8v8zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM13,16h2L15,8h-2v8z"/>
</vector>

View File

@ -0,0 +1,4 @@
<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10,16.5l6,-4.5 -6,-4.5v9zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,49 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.tutpro.baresip.ContactsActivity">
tools:context=".ContactsActivity">
<ListView
android:id="@+id/contacts"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/newName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="20sp"
android:inputType="textPersonName"
android:layout_alignParentStart="true"
android:layout_marginStart="0dp"
android:hint="Name of Contact" >
</EditText>
android:layout_height="fill_parent" />
<ImageButton
android:id="@+id/addContact"
android:id="@+id/plusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@drawable/plus"
android:background="@null"
android:layout_alignParentEnd="true"
android:layout_marginLeft="6dp"
android:src="@drawable/action_add"
android:scaleType="centerCrop" >
android:layout_alignParentBottom="true" >
</ImageButton>
</RelativeLayout>
</LinearLayout>

View File

@ -1,7 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
tools:context=".MainActivity">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -73,7 +78,8 @@
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:padding="0dp"
android:src="@drawable/call" >
android:background="@null"
android:src="@drawable/call_green" >
</ImageButton>
<ImageButton
@ -82,7 +88,8 @@
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:padding="0dp"
android:src="@drawable/hold"
android:src="@drawable/pause"
android:background="@null"
android:layout_marginStart="70dp"
android:visibility="invisible" >
</ImageButton>
@ -99,33 +106,42 @@
android:visibility="invisible" >
</EditText>
</RelativeLayout>
</ScrollView>
<ImageButton
android:id="@+id/contactsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/contacts"
android:layout_toStartOf="@id/messagesButton"
android:layout_marginEnd="10dp"
android:layout_alignParentBottom="true" >
</ImageButton>
<ImageButton
android:id="@+id/messagesButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:layout_toStartOf="@id/callsButton"
android:padding="0dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:background="@null"
android:src="@drawable/messages"
android:visibility="visible" >
android:layout_toStartOf="@id/callsButton"
android:layout_marginEnd="10dp"
android:layout_alignParentBottom="true" >
</ImageButton>
<ImageButton
android:id="@+id/callsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:padding="0dp"
android:background="@null"
android:src="@drawable/calls"
android:layout_marginEnd="0dp"
android:layout_alignParentEnd="true"
android:visibility="visible" >
android:layout_marginEnd="10dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" >
</ImageButton>
</RelativeLayout>
</ScrollView>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -38,13 +39,30 @@
android:hint="Message">
</EditText>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<ImageButton
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:src="@drawable/send"
android:background="@null" >
</ImageButton>
<ImageButton
android:id="@+id/callButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/call"
android:background="@null" >
</ImageButton>
</LinearLayout>
</LinearLayout>

View File

@ -7,10 +7,10 @@
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.tutpro.baresip.MessagesActivity">
tools:context=".MessagesActivity">
<ListView
android:id="@+id/message"
android:id="@+id/messages"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@ -13,17 +13,4 @@
android:layout_marginBottom="6dp">
</TextView>
<ImageButton
android:id="@+id/contactAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:layout_marginStart="6dp"
android:icon="@android:drawable/ic_menu_delete"
android:scaleType="centerCrop" >
</ImageButton>
</RelativeLayout>

View File

@ -3,9 +3,6 @@
<item android:id="@+id/accounts"
android:title="Accounts" />
<item android:id="@+id/contacts"
android:title="Contacts" />
<item android:id="@+id/config"
android:title="Config" />

View File

@ -8,7 +8,8 @@
<b>Usage Hints</b>\n\n
- start by creating an account (click item titles for help)\n
- usually there is no need to edit the config\n
- history entries can be removed or added to contacts by long clicks\n
- contacts and history entries can be removed and added to contacts by long clicks\n
- contacts can be removed by long clicks\n
- call click when callee has not been given can be used for re-dial\n\n
</string>
<string name="noAccounts">No accounts</string>