diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 033be8c5..eef152f5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -35,14 +35,13 @@
-
-
+
@@ -50,16 +49,14 @@
-
+ android:parentActivityName=".MainActivity" >
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt
new file mode 100644
index 00000000..f95e9d88
--- /dev/null
+++ b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt
@@ -0,0 +1,82 @@
+package com.tutpro.baresip
+
+import android.content.Intent
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
+import android.widget.*
+
+class ContactActivity : AppCompatActivity() {
+
+ lateinit var nameView: EditText
+ lateinit var uriView: EditText
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_contact)
+
+ index = intent.extras.getInt("index")
+ val name = ContactsActivity.contactNames[index]
+ val uri = ContactsActivity.contactURIs[index]
+ setTitle(name)
+
+ nameView = findViewById(R.id.Name) as EditText
+ nameView.setText(name)
+
+ uriView = findViewById(R.id.Uri) as EditText
+ uriView.setText(uri)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ super.onCreateOptionsMenu(menu)
+ val inflater = menuInflater
+ inflater.inflate(R.menu.check_icon, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+
+ val i = Intent(this, MainActivity::class.java)
+
+ if (item.itemId == R.id.checkIcon) {
+
+ val name = nameView.text.toString().trim()
+ if (!Utils.checkName(name)) {
+ Utils.alertView(this, "Notice",
+ "Invalid contact name: $name")
+ return false
+ }
+
+ var uri = uriView.text.toString().trim()
+ if (!uri.startsWith("<")) {
+ if (!uri.startsWith("sip:")) uri = "sip:$uri"
+ if (!Utils.checkUri(uri)) {
+ Utils.alertView(this, "Notice","Invalid contact URI: $uri")
+ return false
+ }
+ }
+
+ ContactsActivity.contactNames[index] = name
+ ContactsActivity.contactURIs[index] = uri
+ ContactsActivity.saveContacts()
+ setResult(RESULT_OK, i)
+ finish()
+ return true
+
+ } else if (item.itemId == android.R.id.home) {
+
+ Log.d("Baresip", "Back array was pressed at Contact")
+ setResult(RESULT_CANCELED, i)
+ finish()
+ return true
+
+ } else return super.onOptionsItemSelected(item)
+ }
+
+ companion object {
+ internal var index = 0
+ }
+
+}
diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt
new file mode 100644
index 00000000..37c8a7e2
--- /dev/null
+++ b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt
@@ -0,0 +1,57 @@
+package com.tutpro.baresip
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.support.v7.app.AlertDialog
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import android.widget.ImageButton
+import android.widget.TextView
+
+import java.util.*
+
+class ContactListAdapter(private val cxt: Context, private val rows: ArrayList) :
+ ArrayAdapter(cxt, R.layout.contact_row, rows) {
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val row = rows[position]
+ val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ val rowView = inflater.inflate(R.layout.contact_row, parent, false)
+ val nameView = rowView.findViewById(R.id.contactName) as TextView
+ nameView.text = row
+ nameView.textSize = 20f
+ nameView.setPadding(6, 6, 0, 6)
+ nameView.setOnClickListener { _ ->
+ val i = Intent(cxt, ContactActivity::class.java)
+ val b = Bundle()
+ b.putInt("index", position)
+ i.putExtras(b)
+ (cxt as Activity).startActivityForResult(i, MainActivity.CONTACT_CODE)
+ }
+ val actionView = rowView.findViewById(R.id.contactAction) as ImageButton
+ actionView.setImageResource(R.drawable.action_remove)
+ actionView.setOnClickListener { _ ->
+ Log.d("Baresip", "Delete button clicked")
+ val deleteDialog = AlertDialog.Builder(cxt)
+ deleteDialog.setMessage("Do you want to delete contact ${row}")
+ deleteDialog.setPositiveButton("Delete") { dialog, _ ->
+ ContactsActivity.contactNames.removeAt(position)
+ ContactsActivity.contactURIs.removeAt(position)
+ ContactsActivity.posAtContacts.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
new file mode 100644
index 00000000..b74febda
--- /dev/null
+++ b/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt
@@ -0,0 +1,124 @@
+package com.tutpro.baresip
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.os.SystemClock
+import android.support.v7.app.AppCompatActivity
+import android.util.Log
+import android.view.MenuItem
+import android.widget.*
+
+import java.io.File
+import java.util.ArrayList
+
+class ContactsActivity : AppCompatActivity() {
+
+ internal lateinit var layout: LinearLayout
+ internal var name: String = ""
+ 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
+ Log.d("Baresip", "Got ${contactNames.size} contacts")
+ clAdapter = ContactListAdapter(this, contactNames)
+ 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 (contactNames.contains(name)) {
+ Log.e("Baresip", "Contact name $name already exists")
+ Utils.alertView(this, "Notice",
+ "Contact $name already exists")
+ } else {
+ newNameView.setText("")
+ newNameView.hint = "Contact name"
+ newNameView.clearFocus()
+ contactNames.add(name)
+ contactURIs.add("")
+ posAtContacts.add(contactNames.size)
+ clAdapter.notifyDataSetChanged()
+ saveContacts()
+ val i = Intent(this, ContactActivity::class.java)
+ val b = Bundle()
+ b.putInt("index", contactNames.size - 1)
+ i.putExtras(b)
+ startActivityForResult(i, MainActivity.CONTACT_CODE)
+ }
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ Log.d("Baresip", "Back array was pressed at Contacts")
+ val i = Intent()
+ setResult(Activity.RESULT_OK, i)
+ finish()
+ }
+ }
+ return true
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (resultCode == RESULT_OK) {
+ Log.d("Baresip", "Notifying clAdapter")
+ clAdapter.notifyDataSetChanged()
+ }
+ }
+
+ companion object {
+
+ var contactNames = ArrayList()
+ var contactURIs = ArrayList()
+ var posAtContacts = ArrayList()
+
+ fun generateContacts(path: String) {
+ val content = Utils.getFileContents(File(path))
+ MainActivity.contacts_remove()
+ contactNames.clear()
+ contactURIs.clear()
+ posAtContacts.clear()
+ var i = 0
+ content.lines().forEach {
+ val parts = it.split("\"")
+ if (parts.size == 3) {
+ val name = parts[1]
+ var uri = parts[2].trim()
+ MainActivity.contact_add("\"$name\" $uri")
+ contactNames.add(name)
+ contactURIs.add(uri)
+ posAtContacts.add(i++)
+ }
+ }
+ }
+
+ fun saveContacts() {
+ var contents = ""
+ for (i in contactNames.indices)
+ contents += "\"${contactNames[i]}\" ${contactURIs[i]}\n"
+ val path = MainActivity.filesPath + "/contacts"
+ Utils.putFileContents(File(path), contents)
+ Log.d("Baresip", "Saved contacts '${contents}' to '$path")
+ }
+
+ fun findContactURI(name: String): String {
+ for (i in contactNames.indices)
+ if (contactNames[i] == name)
+ return contactURIs[i].removePrefix("<")
+ .replaceAfter(">", "")
+ .replace(">", "")
+ return name
+ }
+ }
+
+}
diff --git a/app/src/main/res/layout/activity_contact.xml b/app/src/main/res/layout/activity_contact.xml
new file mode 100644
index 00000000..edcb6555
--- /dev/null
+++ b/app/src/main/res/layout/activity_contact.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_contacts.xml b/app/src/main/res/layout/activity_contacts.xml
new file mode 100644
index 00000000..cfc56cac
--- /dev/null
+++ b/app/src/main/res/layout/activity_contacts.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/contact_row.xml b/app/src/main/res/layout/contact_row.xml
new file mode 100644
index 00000000..3ad299c4
--- /dev/null
+++ b/app/src/main/res/layout/contact_row.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+