diff --git a/.gitignore b/.gitignore index 589dd22c..1b938652 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ local.properties build /captures .externalNativeBuild +app/release + diff --git a/README.md b/README.md index c745cc7d..5e692104 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5ed8cf75..d2949099 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -93,7 +93,7 @@ android:value="com.tutpro.baresip.MainActivity" /> + MainActivity.history = ois.readObject() as ArrayList 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()) + 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() diff --git a/app/src/main/kotlin/com/tutpro/baresip/History.kt b/app/src/main/kotlin/com/tutpro/baresip/CallHistory.kt similarity index 67% rename from app/src/main/kotlin/com/tutpro/baresip/History.kt rename to app/src/main/kotlin/com/tutpro/baresip/CallHistory.kt index 327cf2f9..c5f47fd0 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/History.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallHistory.kt @@ -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, aor: String): Int { + fun aorHistory(history: ArrayList, 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, aor: String) { + fun aorRemoveHistory(history: ArrayList, 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, aor: String): History? { + fun aorLatestHistory(history: ArrayList, aor: String): CallHistory? { for (h in history.reversed()) if (h.aor == aor) return h return null diff --git a/app/src/main/kotlin/com/tutpro/baresip/HistoryListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt similarity index 76% rename from app/src/main/kotlin/com/tutpro/baresip/HistoryListAdapter.kt rename to app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt index 3b0d3ce2..9fad06ab 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/HistoryListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt @@ -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) : - ArrayAdapter(cxt, R.layout.history_row, rows) { +class CallListAdapter(private val cxt: Context, private val rows: ArrayList) : + ArrayAdapter(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() val indexes = ArrayList() diff --git a/app/src/main/kotlin/com/tutpro/baresip/HistoryActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt similarity index 75% rename from app/src/main/kotlin/com/tutpro/baresip/HistoryActivity.kt rename to app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt index 750d3b66..476ffdd5 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/HistoryActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt @@ -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() + internal var uaHistory = ArrayList() 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) + b.putString("uri", uaHistory[pos].peerURI) 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) - builder.setMessage("Do you want to add ${uaHistory[pos].peerURI} to contacs or " + - "delete it from call history?") - .setPositiveButton("Cancel", dialogClickListener) - .setNegativeButton("Delete History", dialogClickListener) - .setNeutralButton("Add Contact", dialogClickListener) - .show() + 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 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)) } } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Codec.kt b/app/src/main/kotlin/com/tutpro/baresip/Codec.kt deleted file mode 100644 index 1a8157b6..00000000 --- a/app/src/main/kotlin/com/tutpro/baresip/Codec.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.tutpro.baresip - -class Codec(val name: String, val rate: Int, val channels: Int) {} \ No newline at end of file diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt index a590b447..5f6d0cf0 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt @@ -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.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 { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt index 134f95d8..dd62f4b1 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt @@ -34,23 +34,6 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList - 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 } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt index 4687b0ba..ddbcf1d8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt @@ -1,55 +1,61 @@ 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() - 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) + 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("uri", "") + i.putExtras(b) + startActivityForResult(i, MainActivity.CONTACT_CODE) } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index bf154ba5..f96b9d15 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -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) { + 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() internal var images = ArrayList() - var history: ArrayList = ArrayList() + var history: ArrayList = ArrayList() internal var calls = ArrayList() internal var messages = ArrayList() var filesPath = "" var visible = true + var makeCall = "" var answerCall = "" var rejectCall = "" diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt index a82e0cc6..28123be8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt @@ -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 { diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt index b381a6c8..b82eee9c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt @@ -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 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,11 +77,18 @@ class MessagesActivity: AppCompatActivity() { val builder = AlertDialog.Builder(this@MessagesActivity, R.style.Theme_AppCompat) - builder.setMessage("Delete message from " + - ContactsActivity.contactName(uaMessages[pos].peerURI) + "?") - .setPositiveButton("Cancel", dialogClickListener) - .setNegativeButton("Delete", dialogClickListener) - .show() + 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 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) } @@ -204,4 +219,4 @@ class MessagesActivity: AppCompatActivity() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/res/drawable-hdpi/ic_action_speaker.png b/app/src/main/res/drawable-hdpi/ic_action_speaker.png index 3e48febb..d6a602db 100644 Binary files a/app/src/main/res/drawable-hdpi/ic_action_speaker.png and b/app/src/main/res/drawable-hdpi/ic_action_speaker.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_speaker.png b/app/src/main/res/drawable-mdpi/ic_action_speaker.png index ccb84c1b..599196f0 100644 Binary files a/app/src/main/res/drawable-mdpi/ic_action_speaker.png and b/app/src/main/res/drawable-mdpi/ic_action_speaker.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_speaker.png b/app/src/main/res/drawable-xhdpi/ic_action_speaker.png index adf989ae..4a70e2d0 100644 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_speaker.png and b/app/src/main/res/drawable-xhdpi/ic_action_speaker.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_speaker.png b/app/src/main/res/drawable-xxhdpi/ic_action_speaker.png index 022cece9..262d6e12 100644 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_speaker.png and b/app/src/main/res/drawable-xxhdpi/ic_action_speaker.png differ diff --git a/app/src/main/res/drawable/call.png b/app/src/main/res/drawable/call.png deleted file mode 100644 index 13226723..00000000 Binary files a/app/src/main/res/drawable/call.png and /dev/null differ diff --git a/app/src/main/res/drawable/call.xml b/app/src/main/res/drawable/call.xml new file mode 100644 index 00000000..e4c39f0e --- /dev/null +++ b/app/src/main/res/drawable/call.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/call_green.xml b/app/src/main/res/drawable/call_green.xml new file mode 100644 index 00000000..69937a37 --- /dev/null +++ b/app/src/main/res/drawable/call_green.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/contacts.xml b/app/src/main/res/drawable/contacts.xml new file mode 100644 index 00000000..d6f676b5 --- /dev/null +++ b/app/src/main/res/drawable/contacts.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/hangup.png b/app/src/main/res/drawable/hangup.png deleted file mode 100644 index 75786e9e..00000000 Binary files a/app/src/main/res/drawable/hangup.png and /dev/null differ diff --git a/app/src/main/res/drawable/hangup.xml b/app/src/main/res/drawable/hangup.xml new file mode 100644 index 00000000..99e44bfa --- /dev/null +++ b/app/src/main/res/drawable/hangup.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/hold.png b/app/src/main/res/drawable/hold.png deleted file mode 100644 index ac313aca..00000000 Binary files a/app/src/main/res/drawable/hold.png and /dev/null differ diff --git a/app/src/main/res/drawable/pause.xml b/app/src/main/res/drawable/pause.xml new file mode 100644 index 00000000..a83a1fb3 --- /dev/null +++ b/app/src/main/res/drawable/pause.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/play.xml b/app/src/main/res/drawable/play.xml new file mode 100644 index 00000000..61315924 --- /dev/null +++ b/app/src/main/res/drawable/play.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/drawable/resume.png b/app/src/main/res/drawable/resume.png deleted file mode 100644 index 71337126..00000000 Binary files a/app/src/main/res/drawable/resume.png and /dev/null differ diff --git a/app/src/main/res/drawable/speaker.png b/app/src/main/res/drawable/speaker.png deleted file mode 100644 index 54fa9b74..00000000 Binary files a/app/src/main/res/drawable/speaker.png and /dev/null differ diff --git a/app/src/main/res/layout/activity_contacts.xml b/app/src/main/res/layout/activity_contacts.xml index b2faf043..8f4fefdc 100644 --- a/app/src/main/res/layout/activity_contacts.xml +++ b/app/src/main/res/layout/activity_contacts.xml @@ -1,49 +1,30 @@ - + tools:context=".ContactsActivity"> - - + android:layout_height="fill_parent" /> - - + + + + - - - - - - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 18273238..f6edfd04 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,131 +1,147 @@ - + android:layout_marginBottom="10dp" + tools:context=".MainActivity"> - + - - - - + android:focusable="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"> - + - - - + android:textColor="@android:color/black" + android:text="Outgoing call to ..." > + + + + + + + + + + + + + android:id="@+id/callButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/calleeRow" + android:padding="0dp" + android:background="@null" + android:src="@drawable/call_green" > - + + - - + + - - + - - + - - + + - - + + - + + - + diff --git a/app/src/main/res/layout/activity_message.xml b/app/src/main/res/layout/activity_message.xml index 3c661bf2..57478e2a 100644 --- a/app/src/main/res/layout/activity_message.xml +++ b/app/src/main/res/layout/activity_message.xml @@ -1,5 +1,6 @@ - - - + android:orientation="horizontal" > + + + + + + + + + diff --git a/app/src/main/res/layout/activity_messages.xml b/app/src/main/res/layout/activity_messages.xml index 61b01871..51aec5bb 100644 --- a/app/src/main/res/layout/activity_messages.xml +++ b/app/src/main/res/layout/activity_messages.xml @@ -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"> diff --git a/app/src/main/res/layout/contact_row.xml b/app/src/main/res/layout/contact_row.xml index 3ad299c4..8ea85410 100644 --- a/app/src/main/res/layout/contact_row.xml +++ b/app/src/main/res/layout/contact_row.xml @@ -13,17 +13,4 @@ android:layout_marginBottom="6dp"> - - - diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml index bef4a07a..3f19c822 100644 --- a/app/src/main/res/menu/main_menu.xml +++ b/app/src/main/res/menu/main_menu.xml @@ -3,9 +3,6 @@ - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b965faf2..65083b00 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,7 +8,8 @@ Usage Hints\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 No accounts