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 build
/captures /captures
.externalNativeBuild .externalNativeBuild
app/release

View File

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

View File

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

View File

@ -115,7 +115,7 @@ class BaresipService: Service() {
val fis = FileInputStream(file) val fis = FileInputStream(file)
val ois = ObjectInputStream(fis) val ois = ObjectInputStream(fis)
@SuppressWarnings("unchecked") @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") Log.d(LOG_TAG, "Restored History of ${MainActivity.history.size} entries")
ois.close() ois.close()
fis.close() fis.close()
@ -233,6 +233,13 @@ class BaresipService: Service() {
fun uaEvent(event: String, uap: String, callp: String) { fun uaEvent(event: String, uap: String, callp: String) {
Log.d(LOG_TAG, "updateStatus got event $event/$uap/$callp") Log.d(LOG_TAG, "updateStatus got event $event/$uap/$callp")
if (!IS_SERVICE_RUNNING) return 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) val ua = UserAgent.find(MainActivity.uas, uap)
if (ua == null) { if (ua == null) {
Log.w(LOG_TAG, "updateStatus did not find ua $uap") Log.w(LOG_TAG, "updateStatus did not find ua $uap")
@ -411,7 +418,7 @@ class BaresipService: Service() {
} }
private fun cleanStop() { private fun cleanStop() {
HistoryActivity.saveHistory() CallsActivity.saveHistory()
MessagesActivity.saveMessages() MessagesActivity.saveMessages()
MainActivity.uas.clear() MainActivity.uas.clear()
MainActivity.images.clear() MainActivity.images.clear()

View File

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

View File

@ -10,8 +10,8 @@ import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import java.util.* import java.util.*
class HistoryListAdapter(private val cxt: Context, private val rows: ArrayList<HistoryRow>) : class CallListAdapter(private val cxt: Context, private val rows: ArrayList<CallRow>) :
ArrayAdapter<HistoryRow>(cxt, R.layout.history_row, rows) { ArrayAdapter<CallRow>(cxt, R.layout.history_row, rows) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val row = rows[position] val row = rows[position]
@ -35,7 +35,12 @@ class HistoryListAdapter(private val cxt: Context, private val rows: ArrayList<H
count++ count++
} }
val peerURIView = rowView.findViewById(R.id.peer_uri) as TextView 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 val timeView = rowView.findViewById(R.id.time) as TextView
timeView.text = row.time timeView.text = row.time
return rowView return rowView

View File

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

View File

@ -20,9 +20,9 @@ import java.util.ArrayList
import java.util.Calendar import java.util.Calendar
import java.util.GregorianCalendar import java.util.GregorianCalendar
class HistoryActivity : AppCompatActivity() { class CallsActivity : AppCompatActivity() {
internal var uaHistory = ArrayList<HistoryRow>() internal var uaHistory = ArrayList<CallRow>()
internal var aor: String = "" internal var aor: String = ""
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
@ -34,15 +34,16 @@ class HistoryActivity : AppCompatActivity() {
aor = intent.extras.getString("aor") aor = intent.extras.getString("aor")
aorGenerateHistory(aor) aorGenerateHistory(aor)
val adapter = HistoryListAdapter(this, uaHistory) val adapter = CallListAdapter(this, uaHistory)
listview.adapter = adapter listview.adapter = adapter
listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
val i = Intent() val i = Intent(this@CallsActivity, MessageActivity::class.java)
i.putExtra("peer_uri", uaHistory[position].peerURI) val b = Bundle()
setResult(Activity.RESULT_OK, i) b.putString("aor", aor)
finish() b.putString("peer", uaHistory[pos].peerURI)
i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE)
} }
listview.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ -> listview.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val dialogClickListener = DialogInterface.OnClickListener { _, which -> val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) { when (which) {
@ -51,11 +52,7 @@ class HistoryActivity : AppCompatActivity() {
val b = Bundle() val b = Bundle()
b.putBoolean("new", true) b.putBoolean("new", true)
b.putString("name", "New Name") b.putString("name", "New Name")
if (uaHistory[pos].peerDomain == "") b.putString("uri", uaHistory[pos].peerURI)
b.putString("uri", uaHistory[pos].peerURI)
else
b.putString("uri", "sip:${uaHistory[pos].peerURI}@" +
uaHistory[pos].peerDomain)
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE) startActivityForResult(i, MainActivity.CONTACT_CODE)
} }
@ -72,14 +69,19 @@ class HistoryActivity : AppCompatActivity() {
} }
} }
} }
val builder = AlertDialog.Builder(this@HistoryActivity, val builder = AlertDialog.Builder(this@CallsActivity, R.style.Theme_AppCompat)
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 " + 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) .setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener) .setNegativeButton("Delete History", dialogClickListener)
.setNeutralButton("Add Contact", dialogClickListener) .setNeutralButton("Add Contact", dialogClickListener)
.show() .show()
else
builder.setMessage("Do you want to delete call(s) from history?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete History", dialogClickListener)
.show()
true true
} }
@ -89,7 +91,7 @@ class HistoryActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { 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() val i = Intent()
setResult(Activity.RESULT_CANCELED, i) setResult(Activity.RESULT_CANCELED, i)
finish() finish()
@ -103,12 +105,6 @@ class HistoryActivity : AppCompatActivity() {
for (i in MainActivity.history.indices.reversed()) { for (i in MainActivity.history.indices.reversed()) {
val h = MainActivity.history[i] val h = MainActivity.history[i]
if (h.aor == aor) { 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 var direction: Int
if (h.direction == "in") if (h.direction == "in")
if (h.connected) if (h.connected)
@ -120,7 +116,7 @@ class HistoryActivity : AppCompatActivity() {
direction = R.drawable.arrow_up_green direction = R.drawable.arrow_up_green
else else
direction = R.drawable.arrow_up_red 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().directions.add(direction)
uaHistory.last().indexes.add(i) uaHistory.last().indexes.add(i)
} else { } else {
@ -132,7 +128,7 @@ class HistoryActivity : AppCompatActivity() {
val fmt = SimpleDateFormat("dd.MM") val fmt = SimpleDateFormat("dd.MM")
time = fmt.format(h.time.time) 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) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contact) setContentView(R.layout.activity_contact)
new = intent.extras.getBoolean("new") nameView = findViewById(R.id.Name) as EditText
val name: String uriView = findViewById(R.id.Uri) as EditText
val uri: String
if (new) { if (intent.extras.getBoolean("new")) {
name = intent.extras.getString("name") setTitle("New Contact")
uri = intent.extras.getString("uri") nameView.setText("")
nameView.hint = "Contact name"
nameView.setSelection(nameView.text.length)
uriView.setText("")
uriView.hint = "SIP URI"
} else { } else {
index = intent.extras.getInt("index") index = intent.extras.getInt("index")
name = ContactsActivity.contacts[index].name val name = ContactsActivity.contacts[index].name
uri = ContactsActivity.contacts[index].uri setTitle(name)
nameView.setText(name)
uriView.setText(ContactsActivity.contacts[index].uri)
} }
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)
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { 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) i.putExtras(b)
(cxt as Activity).startActivityForResult(i, MainActivity.CONTACT_CODE) (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 return rowView
} }
} }

View File

@ -1,55 +1,61 @@
package com.tutpro.baresip package com.tutpro.baresip
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.*
import android.os.Bundle import android.os.Bundle
import android.os.SystemClock import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.util.Log import android.util.Log
import android.view.MenuItem 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.io.File
import java.util.ArrayList import java.util.ArrayList
class ContactsActivity : AppCompatActivity() { class ContactsActivity : AppCompatActivity() {
internal lateinit var layout: LinearLayout internal lateinit var clAdapter: ContactListAdapter
internal var name: String = ""
lateinit var clAdapter: ContactListAdapter
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contacts) 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") Log.d("Baresip", "Got ${contacts.size} contacts")
clAdapter = ContactListAdapter(this, contacts) clAdapter = ContactListAdapter(this, contacts)
listview.adapter = clAdapter listView.adapter = clAdapter
val addContactButton = findViewById(R.id.addContact) as ImageButton listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val newNameView = findViewById(R.id.newName) as EditText val dialogClickListener = DialogInterface.OnClickListener { _, which ->
addContactButton.setOnClickListener{ when (which) {
val name = newNameView.text.toString().trim() DialogInterface.BUTTON_NEGATIVE -> {
if (!Utils.checkName(name)) { ContactsActivity.contacts.removeAt(pos)
Log.e("Baresip", "Invalid contact name $name") ContactsActivity.saveContacts()
Utils.alertView(this, "Notice", clAdapter.notifyDataSetChanged()
"Invalid contact name: $name") }
} else if (nameExists(name)) { DialogInterface.BUTTON_POSITIVE -> {
Utils.alertView(this, "Notice", }
"Contact $name already exists") }
} else {
newNameView.setText("")
newNameView.hint = "Contact name"
newNameView.clearFocus()
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)
} }
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("uri", "")
i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE)
} }
} }

View File

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

View File

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

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* 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 val directionView = messageView.findViewById(R.id.direction) as ImageView
directionView.setImageResource(message.direction) directionView.setImageResource(message.direction)
val peerView = messageView.findViewById(R.id.peer) as TextView 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 timeView = messageView.findViewById(R.id.time) as TextView
val time: String val time: String
val cal = GregorianCalendar() val cal = GregorianCalendar()

View File

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

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

View File

@ -1,131 +1,147 @@
<?xml version="1.0" encoding="utf-8"?> <?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" xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fillViewport="true" > android:layout_marginBottom="10dp"
tools:context=".MainActivity">
<RelativeLayout <ScrollView
android:id="@+id/mainActivityLayout" android:id="@+id/scrollView"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:focusable="true" android:fillViewport="true" >
android:focusableInTouchMode="true"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<Spinner <RelativeLayout
android:id="@+id/AoRList" android:id="@+id/mainActivityLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/btn_dropdown"
android:spinnerMode="dropdown"/>
<TextView
android:id="@+id/outTitle"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/AoRList" android:focusable="true"
android:paddingTop="16dp" android:focusableInTouchMode="true"
android:paddingStart="3dp" android:paddingBottom="@dimen/activity_vertical_margin"
android:textSize="20sp" android:paddingLeft="@dimen/activity_horizontal_margin"
android:textColor="@android:color/black" android:paddingRight="@dimen/activity_horizontal_margin"
android:text="Outgoing call to ..." > android:paddingTop="@dimen/activity_vertical_margin">
</TextView>
<LinearLayout <Spinner
android:id="@+id/calleeRow" android:id="@+id/AoRList"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:background="@android:drawable/btn_dropdown"
android:layout_below="@id/outTitle" > android:spinnerMode="dropdown"/>
<AutoCompleteTextView <TextView
android:id="@+id/callee" android:id="@+id/outTitle"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight = "1" android:layout_below="@id/AoRList"
android:inputType="textEmailAddress" android:paddingTop="16dp"
android:paddingStart="3dp"
android:textSize="20sp" android:textSize="20sp"
android:hint="Callee" > android:textColor="@android:color/black"
<!-- <requestFocus /> --> android:text="Outgoing call to ..." >
</AutoCompleteTextView> </TextView>
<LinearLayout
android:id="@+id/calleeRow"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/outTitle" >
<AutoCompleteTextView
android:id="@+id/callee"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight = "1"
android:inputType="textEmailAddress"
android:textSize="20sp"
android:hint="Callee" >
<!-- <requestFocus /> -->
</AutoCompleteTextView>
<ImageButton
android:id="@+id/securityButton"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_weight = "0"
android:layout_gravity = "center_vertical"
android:visibility="invisible"
android:contentDescription="@string/app_name" >
</ImageButton>
</LinearLayout>
<ImageButton <ImageButton
android:id="@+id/securityButton" android:id="@+id/callButton"
android:layout_width="24dp" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="wrap_content"
android:layout_weight = "0" android:layout_below="@id/calleeRow"
android:layout_gravity = "center_vertical" android:padding="0dp"
android:visibility="invisible" android:background="@null"
android:contentDescription="@string/app_name" > android:src="@drawable/call_green" >
</ImageButton> </ImageButton>
</LinearLayout> <ImageButton
android:id="@+id/holdButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:padding="0dp"
android:src="@drawable/pause"
android:background="@null"
android:layout_marginStart="70dp"
android:visibility="invisible" >
</ImageButton>
<ImageButton <EditText
android:id="@+id/callButton" android:id="@+id/dtmf"
android:layout_width="wrap_content" android:layout_width="@dimen/button_width"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/calleeRow" android:layout_below="@id/calleeRow"
android:padding="0dp" android:layout_marginStart="140dp"
android:src="@drawable/call" > android:inputType="phone"
</ImageButton> android:textSize="20sp"
android:hint="DTMF"
android:visibility="invisible" >
</EditText>
<ImageButton </RelativeLayout>
android:id="@+id/holdButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:padding="0dp"
android:src="@drawable/hold"
android:layout_marginStart="70dp"
android:visibility="invisible" >
</ImageButton>
<EditText </ScrollView>
android:id="@+id/dtmf"
android:layout_width="@dimen/button_width"
android:layout_height="wrap_content"
android:layout_below="@id/calleeRow"
android:layout_marginStart="140dp"
android:inputType="phone"
android:textSize="20sp"
android:hint="DTMF"
android:visibility="invisible" >
</EditText>
<ImageButton <ImageButton
android:id="@+id/messagesButton" android:id="@+id/contactsButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/calleeRow" android:background="@null"
android:layout_toStartOf="@id/callsButton" android:src="@drawable/contacts"
android:padding="0dp" android:layout_toStartOf="@id/messagesButton"
android:layout_marginTop="4dp" android:layout_marginEnd="10dp"
android:layout_marginEnd="4dp" android:layout_alignParentBottom="true" >
android:background="@null" </ImageButton>
android:src="@drawable/messages"
android:visibility="visible" >
</ImageButton>
<ImageButton <ImageButton
android:id="@+id/callsButton" android:id="@+id/messagesButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/calleeRow" android:background="@null"
android:padding="0dp" android:src="@drawable/messages"
android:background="@null" android:layout_toStartOf="@id/callsButton"
android:src="@drawable/calls" android:layout_marginEnd="10dp"
android:layout_marginEnd="0dp" android:layout_alignParentBottom="true" >
android:layout_alignParentEnd="true" </ImageButton>
android:visibility="visible" >
</ImageButton>
</RelativeLayout> <ImageButton
android:id="@+id/callsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="0dp"
android:background="@null"
android:src="@drawable/calls"
android:layout_marginEnd="10dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" >
</ImageButton>
</ScrollView> </RelativeLayout>

View File

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

View File

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

View File

@ -13,17 +13,4 @@
android:layout_marginBottom="6dp"> android:layout_marginBottom="6dp">
</TextView> </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> </RelativeLayout>

View File

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

View File

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