From 59d22b12abcbe712141365514f0a1245fa717554 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 29 Jul 2018 16:32:27 +0300 Subject: [PATCH] improved calls/messages/contacts implemtation used vector image assets --- .gitignore | 2 + README.md | 7 +- app/src/main/AndroidManifest.xml | 4 +- .../com/tutpro/baresip/BaresipService.kt | 11 +- .../baresip/{History.kt => CallHistory.kt} | 8 +- ...storyListAdapter.kt => CallListAdapter.kt} | 11 +- .../baresip/{HistoryRow.kt => CallRow.kt} | 3 +- .../{HistoryActivity.kt => CallsActivity.kt} | 58 ++--- .../main/kotlin/com/tutpro/baresip/Codec.kt | 3 - .../com/tutpro/baresip/ContactActivity.kt | 31 ++- .../com/tutpro/baresip/ContactListAdapter.kt | 17 -- .../com/tutpro/baresip/ContactsActivity.kt | 66 ++--- .../kotlin/com/tutpro/baresip/MainActivity.kt | 129 ++++++---- .../com/tutpro/baresip/MessageActivity.kt | 23 +- .../com/tutpro/baresip/MessageListAdapter.kt | 8 +- .../com/tutpro/baresip/MessagesActivity.kt | 33 ++- .../res/drawable-hdpi/ic_action_speaker.png | Bin 1131 -> 1087 bytes .../res/drawable-mdpi/ic_action_speaker.png | Bin 794 -> 752 bytes .../res/drawable-xhdpi/ic_action_speaker.png | Bin 1807 -> 1332 bytes .../res/drawable-xxhdpi/ic_action_speaker.png | Bin 3129 -> 2144 bytes app/src/main/res/drawable/call.png | Bin 3952 -> 0 bytes app/src/main/res/drawable/call.xml | 5 + app/src/main/res/drawable/call_green.xml | 5 + app/src/main/res/drawable/contacts.xml | 5 + app/src/main/res/drawable/hangup.png | Bin 2970 -> 0 bytes app/src/main/res/drawable/hangup.xml | 5 + app/src/main/res/drawable/hold.png | Bin 2323 -> 0 bytes app/src/main/res/drawable/pause.xml | 4 + app/src/main/res/drawable/play.xml | 4 + app/src/main/res/drawable/resume.png | Bin 2408 -> 0 bytes app/src/main/res/drawable/speaker.png | Bin 1650 -> 0 bytes app/src/main/res/layout/activity_contacts.xml | 47 ++-- app/src/main/res/layout/activity_main.xml | 230 ++++++++++-------- app/src/main/res/layout/activity_message.xml | 30 ++- app/src/main/res/layout/activity_messages.xml | 4 +- app/src/main/res/layout/contact_row.xml | 13 - app/src/main/res/menu/main_menu.xml | 3 - app/src/main/res/values/strings.xml | 3 +- 38 files changed, 435 insertions(+), 337 deletions(-) rename app/src/main/kotlin/com/tutpro/baresip/{History.kt => CallHistory.kt} (67%) rename app/src/main/kotlin/com/tutpro/baresip/{HistoryListAdapter.kt => CallListAdapter.kt} (76%) rename app/src/main/kotlin/com/tutpro/baresip/{HistoryRow.kt => CallRow.kt} (57%) rename app/src/main/kotlin/com/tutpro/baresip/{HistoryActivity.kt => CallsActivity.kt} (75%) delete mode 100644 app/src/main/kotlin/com/tutpro/baresip/Codec.kt delete mode 100644 app/src/main/res/drawable/call.png create mode 100644 app/src/main/res/drawable/call.xml create mode 100644 app/src/main/res/drawable/call_green.xml create mode 100644 app/src/main/res/drawable/contacts.xml delete mode 100644 app/src/main/res/drawable/hangup.png create mode 100644 app/src/main/res/drawable/hangup.xml delete mode 100644 app/src/main/res/drawable/hold.png create mode 100644 app/src/main/res/drawable/pause.xml create mode 100644 app/src/main/res/drawable/play.xml delete mode 100644 app/src/main/res/drawable/resume.png delete mode 100644 app/src/main/res/drawable/speaker.png 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 3e48febbb0031fcdd87c5a17b01c81d51405d3be..d6a602db751317718073c5f313e94a696e96ff29 100644 GIT binary patch literal 1087 zcmV-F1i<@=P)8Y0z+)IDJ$6A^h89^O4mgQVhCA2g+5Zke&onE$PJKji^?UmP{ z@A!7v{l1y+&3kVEdg!5t9u5+EH-DDT=k-V=@>V<^U$50_>xWJNBASs% zS66RVDwUUAv(T$-(+b66v0AU!uTn}El)QK&7K^>twH#1w(+SGu@(TdC3jmACqj5sW zsh|bmF34|tk8@t9l->h?nv&RO^7*_TSPtxjyf+7u$z&uNjh@pq?fYV}_(Xj-olYk- zP5Vsw-ZzL?*!LaSgKZLpLg8{cold9^=I7^^0N^(zJke^QjaNO8Qr-)&NFUR6{bSp< zuc$lGXf%GIlx7)YntQAcWipx9OQq6ZU2i4YRN$kI<9wj5Zn<233;@gCTo6Je52P2` zfrtblWLVvN0C=Fp-VCJx7g;sXY&IV%g>4|T0uXWA>gu}w%-b(XDNlq}0AuX98mrgq z>xkI&h&&Qz3+)L9E`U<{OpTeQc~nZNdo1*_<2ukSNGX?nlK6P3RPuJT|Ag5>b3RFY zQpuBACmi={JrlM5<<)Xz>GSe?*NOrT<(exqT<(113*qm@}JdR z+RvF7+l`WbL%km%%d(C!#y$st0nZWpcxr0utLf=!C(xn3m7UsI(Isy(#x4NBu!p?U zY&LJWGeWS1Y!7yVR4Vlv0G#)dcaP3r+mYYbV^j$7W2Yi)+a5Aa^D<*>MA?zb=;-ME zLwT`9DSZS0w>al(2ht0*veU%GgdwH;1QEaFoacOQsMkhZCsuD{f#0(*%-RUC{afNgK10wzrx^~*NlV1zn0Dwiq zFuvxTU)wGDuJ=MCBO}dfwfdc57!MHfIrPv&4?P@u{0r;6nhOrRDfs{Z002ovPDHLk FV1kYP@lyZ* literal 1131 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

a&5f(vzJHyK&Kmu)TZz7$ zR%1z#65b5w47aPK{OIDn&m3QhF+H=n)j8Jb_C=Gjn>^GEHLd7YP&2l=8w|@XP8;P}j0-goZjxbUtI@z|+%b98PAr!~60 z9_`*1gF!#bhFGyriaD)KEjYO&@TKMFySMhv#8r-JvMK_a)u$Tb^0LZ#hbC~oYEtI7 z`o?Rh8k5aw9zXj57G{o8_<|#Ii#*}qk9P&N&}8|}EA-1g$LG&*;m4om!nqIfj>RPe zII(z|hbE6OKfTDy*T2q{H(p_N;|_zeSFu!PF1%oQv$j71PyOuDQcO7l+nt`IYWmS} z$J|SMxd0u#VV|weI_sM&Otua&Gr2&$XklWsnk|mapI~lsk*1sB=%G`*=h64`f%iPa z#KZ*svPW;w1&pId7CF6mmLrEwBFVGW*`(duqCXf=mRUjsCsqsoj&poz`MC!oFmCgC z;aMp|$-|8p&M7I8w`$H;-BodT`n>_KUVjDn8wSG;Pn~<3qYs@x%qT+O;S-OrxNwZ5 ziAKFa5j>_Td$sDw!@+=11m1b-EDLiBoLPF5e|i3kJb(G$`QH88;0&a>%g_VFTxNjr zt^>1*NG(;X5y`ym(s)_xoFl2x>vwti+Di;$WUI5ug>yg6>BUE>)ta=Lo~g-63?Ze& zaM)+pT%NZQnpZB(MuVBDGej*}zVjMaZob4CS^wZ~qwI)G|YKYf8#>-eA35qd{CCGq&Y}1ch zL>)qIb%62UWU)Vm#!_)FSdpENs&hy;cT<7JhFYxY1p5)xaPq1|4EK`lyywJ5w6k>)GM+lzn z?k3-S^;w?1_yumo#7=jbWDl$tqs2Y`b%7WW0|?Bf8!m8kMNEorme!@F!iQl&TO)9!Y-yS~cpyH~k#^ED@zaQ18|t@t?4e7Mu~DjyWHIkV zM+3gN4Ai;tV<+1+!Hq{!LBt&Zpi!?`Qj=P}CLx5KnLy-+{;1SB!BK$!?`v+H))fHf zofN?ng4@5HZnm0z6WKg8Jr&#SLD4C?sOrv2o1?letFg4Y> zC*q!)duZliC*fqL*OQpi&Tw!15X<}fW3s&c%loIod#e}nX0yR_HP5|$02YqStO}c- z?{tQe=vNpz1jcAKmFaW zTm<;kXFtTJKK|?utA6gv@A1*If5v-1@bFS|s`hxO`A6_F1Gv1jv%LxX!!8SZuqdRO zvQUz3#9@4W*oiNG{a>%${Ok+A#mArc%l&379GjN!-QFsIDPS6CRunD#@0P%BC<^p| zEns{8*hG2vcE|ShwdO>PUT3(6?S4eQe!H<5FM}Erfqo}H + + 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 75786e9ed820d182d9b3113471082f301a75d56f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2970 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 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 ac313acab2ea85fd7f95747aa695ccbf2aa9a068..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2323 zcmV+u3GDWXP)0b000McNliru;sqHD1P}sft4II<2&73wK~z}7 zg_v7x9n}?vzrAPX%(?k;Y{zl!I0+O7(*%)5%Q-%mx$M=4*&fev({_$z z&)J&2)?WYm*T2>r#Z|5!^GtgG)2(uwx}6aQsL)FXP-T%N=9!k0>hx0!SKGC5srIiw zBxZu&1Mrg_vX>DVW>5`Dg)(^x-C{1JO8BUGj)L%5dyPG+9G)E!*g$NP!$KE{=^LB&0>a0{`M; zs+7s&y3WnKpnkFV()h~Z)T#qd@I3DUqutTB|l@{Iw?`0fRB$) zo;*c5=%hrEB8D0*1nsF_`i%G4xp$lI@g7fb92e>UJXs3&sYhj3L_mP1n_XN_Hzj;r z6rj?CC9EX4MgX_~fzY*AmMPoCaY3H{=N!4ZRktbh3-DGQt+h z_;{8xjs+?CxHy(iIeHktrOGlIg(}K*e17~~V%d3|lYG}5+s%V=F!t-T=;9i#XD2-r z$fbr8<2rSq(P+EkQ>1`Ur%sIHsX?k^pNxHR!aR<161cs>!*W3SL+UtO&nVmJBL5$z zb^2G^QqvYVO(#AvmkDsuni7V;oot*$14zFdG@~I+po=fFoo;+wJiH7nnd-HXxVGGU zd_0Eu3KfJVA!bw#O21{%cXr4D`DR>bu}Uwy8KpNxK983HBuTVN;c;-uAqW~QiC6hN zx$|Xq-~6c+7i6y-l43}R!w@&ngKsxO6_W&sL($%Wp+*E41Wkz?ArMgHCYHENh{h|b zLu!T@7tDz4kNq`Z7bEoIJQ*Pw$%)a9}|*im?6rzDcZscSBPlRBp^N)+UMjBXm4YG0rGRT6 zQRzA7nWavZn0`zfL`~MHra9P%LE+G09Z13Sy3!#zv37QOyIpvEF|XtrlS5}Gt5j4M}%xbPWMCRRTc~ zr@>~i77Veigm#)5z)8g;J4FbsbDk|Ly$CRfrVYcx5^7~9pdQ;|y%V+l=W zS4@o-8juEyT9%|KC_?H)_9016t8wut;^VZP^Xlu#&cuO2kftoTGB14!hdN&n+D^OS zA`#>~4qn@oxp`eO(_hE}H5?RDW8Rf%83KnI3j|iMOe)eYIea1`DNBS&ZZ2`geP!XnS=G|MLyHS^(uspZj0QA=)M*hAa7|_i zbQs#SZiww?hQHHHG@&K4uPnGA(;R2a&j(CWVJ99j5t=3?9=7Ercyy%>I(dZ9!s60N zj3Fi>BH#jlMw5r8oM1YcP0z{^_UgQ*&PVieD?T9_$kDs0@RTKK_aO=w4=~A|kk1%UHz{q1 zsUZ|8rZ1WYr_GBvi7Cx@5D zk%&o1NX)04XibDc%N6lb`zRXxWf*DAkw~;!-Qyd*!c`>z_d5t~HH~{yTxSPA=4n_?TO=3Jc=%T|8 z>B&UeqRI*@ggE4r*W2^z7;o|Bt7}i&s@Aj zbDFBoCmiLC*FI>s^WWd}&+#JTawmt>e(ft9a%n5wm>=x?(c*+0QEzjF75@K^A@>tA z!3+TR?qDw?3^OQ0szO;ZKZd9#HCa+~Tw<1K&b~eau!CE0GN-?agXFr8*V6lYw{jb| ts}Tky^K*_`VqT^>$?4Y@uC{CA`Zug`5hPfiRQUh^002ovPDHLkV1i|~EQ + + 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 71337126b690a1fdbbd95af4d3a16099ecc4db63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2408 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 diff --git a/app/src/main/res/drawable/speaker.png b/app/src/main/res/drawable/speaker.png deleted file mode 100644 index 54fa9b74d94fdbf62693c25591813331c1a5e249..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1650 zcmV-&295cNP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt010qNS#tmY4c7nw4c7reD4Tcy000McNliru;sp#09xaXPx-S3# z1!YM@K~!ko&6-_o6-5-s|FgXmF<7l1K!FGFqbdmkS^@^4piPJYLcxco!8>~kN_?Q0 zKrGQfT0Uw5N+K2>_l!ivQfU&^c@u7EjXQ4p5 zcb4sW`k$HZ+21`gJ9}oj41t??9@EikZ7aJO{Js1EmW%(Slrr&E*d$$AZC|ljIu?J{ zUlb!a!1y4mfzNaOtbzXGM1leo1=z`l>WCCj7R6gQpa(FJEH3Nw^m;yDUp(!IG(hg) z6Lm(^Jka!<{6z(%qjaKIA&NI-GtXB5$r>v!WExf5Kvx;VKSTv*4qgh2&2>N`8V^^#E#_i=qh49>85U#&d0e8nP&spqghn zcoHkj<&gRSGeq3fFMAW8b|DRa&oo`ZEOV7!Kmh4E&c|5wHO?DLd7|k&&UG_XtE`9} z(~JiIXONeMETZLDdK)4(npFYZwkNiT8hF37eqZb{4+4SiqkC@VK~_SkPR$L}R2d;7 ziuXjDxF{;sHohAx99=MMHW1)e|6Z1u$kzY>s&Lu-#BEPjQ!yXYso4_j2r-MSz>y!( zt8ROF3X5#b3usiB1KmvNC5uO7jl0AE=Fjx2tz~J5h~|D&+nSHa;hxTfqo#)XxSXz} zeU9_C+9SWVGmIDFkA#R=Wud}x#?b(`Cw2kHI~6zBh)~x>^AH`eQRDFDdIj*t zS#r@Kl&Jq>O-wD=r4fUG0SXmTO&B)FB~_p z5~K7U-kC>g@@Z(Kb~@`c@}+I;&t(lXTZOxdoUfT|#E~0ssGjXKKu1R)Ki{001R)MObuXVRU6W zV{&C-bY%cCFflkSFf}bPGE^}#Ix{djG&L(QGdeIZUBIT=0000bbVXQnWMOn=I&E)c wX=Zr - + 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