- new implementation of messaging

- fixed possible crash when messages arrive before accounts are created
- other minor fixes and improvements
This commit is contained in:
Juha Heinanen
2018-11-18 09:37:22 +02:00
parent ec12536fd9
commit 49d9d8c311
25 changed files with 457 additions and 358 deletions
+2 -2
View File
@@ -7,8 +7,8 @@ android {
applicationId = 'com.tutpro.baresip' applicationId = 'com.tutpro.baresip'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 27 targetSdkVersion 27
versionCode = 32 versionCode = 33
versionName = '3.2.3' versionName = '4.0.0'
externalNativeBuild { externalNativeBuild {
cmake { cmake {
cFlags '-DHAVE_INTTYPES_H' cFlags '-DHAVE_INTTYPES_H'
+12 -39
View File
@@ -47,76 +47,49 @@
android:name=".AccountsActivity" android:name=".AccountsActivity"
android:label="Accounts" android:label="Accounts"
android:parentActivityName=".MainActivity"> android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".AccountActivity" android:name=".AccountActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
android:label="Account" android:label="Account"
android:parentActivityName=".MainActivity"> android:parentActivityName=".AccountsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".ContactsActivity" android:name=".ContactsActivity"
android:label="Contacts" android:label="Contacts"
android:parentActivityName=".MainActivity" android:windowSoftInputMode="adjustPan"
android:windowSoftInputMode="adjustPan"> android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".ContactActivity" android:name=".ContactActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
android:label="Contact" android:label="Contact"
android:parentActivityName=".MainActivity"> android:parentActivityName=".ContactsActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".EditConfigActivity" android:name=".EditConfigActivity"
android:label="Edit Config" android:label="Edit Config"
android:parentActivityName=".MainActivity"> android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".CallsActivity" android:name=".CallsActivity"
android:label="Call History" android:label="Call History"
android:parentActivityName=".MainActivity"> android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".MessagesActivity" android:name=".ChatsActivity"
android:label="Message History" android:label="Chat History"
android:parentActivityName=".MainActivity"> android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".MessageActivity" android:name=".ChatActivity"
android:label="Message or Call" android:label="Messages of a Chat"
android:parentActivityName=".MessagesActivity" > android:parentActivityName=".ChatsActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<activity <activity
android:name=".AboutActivity" android:name=".AboutActivity"
android:label="About" android:label="About"
android:parentActivityName=".MainActivity"> android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.tutpro.baresip.MainActivity" />
</activity> </activity>
<service <service
+1 -1
View File
@@ -1033,7 +1033,7 @@ Java_com_tutpro_baresip_MainActivity_call_1send_1digit(JNIEnv *env, jobject thiz
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_com_tutpro_baresip_MessageActivity_message_1send(JNIEnv *env, jobject thiz, jstring javaUA, Java_com_tutpro_baresip_ChatActivity_message_1send(JNIEnv *env, jobject thiz, jstring javaUA,
jstring javaPeer, jstring javaMsg, jstring javaPeer, jstring javaMsg,
jstring javaTime) { jstring javaTime) {
struct ua *ua; struct ua *ua;
@@ -77,18 +77,12 @@ class AccountsActivity : AppCompatActivity() {
companion object { companion object {
var accounts = ArrayList<AccountRow>() var accounts = ArrayList<AccountRow>()
var posAtAccounts = ArrayList<Int>()
fun generateAccounts() { fun generateAccounts() {
accounts.clear() accounts.clear()
posAtAccounts.clear() for (ua in MainActivity.uas)
var i = 0;
for (ua in MainActivity.uas) {
accounts.add(AccountRow(ua.account.aor.replace("sip:", ""), accounts.add(AccountRow(ua.account.aor.replace("sip:", ""),
R.drawable.action_remove)) R.drawable.action_remove))
posAtAccounts.add(i)
i++
}
} }
fun saveAccounts() { fun saveAccounts() {
@@ -40,7 +40,7 @@ class CallsActivity : AppCompatActivity() {
val adapter = CallListAdapter(this, uaHistory) val adapter = CallListAdapter(this, uaHistory)
listview.adapter = adapter listview.adapter = adapter
listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
val i = Intent(this@CallsActivity, MessageActivity::class.java) val i = Intent(this@CallsActivity, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", aor) b.putString("aor", aor)
b.putString("peer", uaHistory[pos].peerURI) b.putString("peer", uaHistory[pos].peerURI)
@@ -0,0 +1,205 @@
package com.tutpro.baresip
import android.app.Activity
import android.content.*
import android.os.Bundle
import android.support.v4.content.LocalBroadcastManager
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.*
class ChatActivity : AppCompatActivity() {
internal lateinit var chatMessages: ArrayList<Message>
internal lateinit var mlAdapter: MessageListAdapter
internal lateinit var newMessage: EditText
internal lateinit var sendButton: ImageButton
internal lateinit var imm: InputMethodManager
internal lateinit var aor: String
internal lateinit var peerUri: String
internal lateinit var ua: UserAgent
internal lateinit var messageResponseReceiver: BroadcastReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
aor = intent.extras.getString("aor")
peerUri = intent.extras.getString("peer")
val reply = intent.extras.getBoolean("reply")
val userAgent = Account.findUa(aor)
if (userAgent == null) {
Log.e("Baresip", "MessageActivity did not find ua of $aor")
val i = Intent()
setResult(Activity.RESULT_CANCELED, i)
finish()
} else {
ua = userAgent
}
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
var chatPeer = ContactsActivity.contactName(peerUri)
if (chatPeer.startsWith("sip:")) {
if (Utils.checkTelNo(Utils.uriUserPart(peerUri)))
chatPeer = Utils.uriUserPart(peerUri)
else
chatPeer = chatPeer.substring(4)
}
setTitle("Chat with $chatPeer")
chatMessages = uaPeerMessages(aor, peerUri)
val listView = findViewById(R.id.messages) as ListView
mlAdapter = MessageListAdapter(this, chatMessages)
listView.adapter = mlAdapter
listView.isLongClickable = true
val footerView = View(applicationContext)
listView.addFooterView(footerView)
listView.smoothScrollToPosition(mlAdapter.count)
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) {
DialogInterface.BUTTON_NEUTRAL -> {
val i = Intent(this, ContactActivity::class.java)
val b = Bundle()
b.putBoolean("new", true)
b.putString("uri", peerUri)
i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE)
}
DialogInterface.BUTTON_NEGATIVE -> {
MainActivity.messages.remove(chatMessages[pos])
chatMessages.removeAt(pos)
mlAdapter.notifyDataSetChanged()
if (chatMessages.size == 0) {
listView.removeFooterView(footerView)
}
}
DialogInterface.BUTTON_POSITIVE -> {
}
}
}
val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat)
if (chatPeer.contains("@") || Utils.checkTelNo(chatPeer))
builder.setMessage("Do you want to delete message or add peer $chatPeer to contacts?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete Message", dialogClickListener)
.setNeutralButton("Add Contact", dialogClickListener)
.show()
else
builder.setMessage("Do you want to delete message?")
.setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete Message", dialogClickListener)
.show()
true
}
newMessage = findViewById(R.id.text) as EditText
if (reply) newMessage.requestFocus()
sendButton = findViewById(R.id.sendButton) as ImageButton
sendButton.setOnClickListener {
val msgText = newMessage.text.toString()
if (msgText.length > 0) {
imm.hideSoftInputFromWindow(newMessage.windowToken, 0)
val time = System.currentTimeMillis()
val msg = Message(aor, peerUri, R.drawable.arrow_up_yellow, msgText, time,true)
MainActivity.messages.add(msg)
chatMessages.add(msg)
mlAdapter.notifyDataSetChanged()
if (message_send(ua!!.uap, peerUri, msgText, time.toString()) != 0)
Toast.makeText(getApplicationContext(), "Sending of message failed!",
Toast.LENGTH_SHORT).show()
else
newMessage.text.clear()
}
}
messageResponseReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
handleMessageResponse(intent.getIntExtra("response code", 0),
intent.getStringExtra("time"))
}
}
LocalBroadcastManager.getInstance(this).registerReceiver(messageResponseReceiver,
IntentFilter("message response"))
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.call_icon, menu)
return true
}
override fun onPause() {
ChatsActivity.saveMessages()
super.onPause()
}
override fun onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageResponseReceiver)
super.onDestroy()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
for (m in chatMessages) if (m.new) m.new = false
imm.hideSoftInputFromWindow(newMessage.windowToken, 0)
val i = Intent()
setResult(Activity.RESULT_OK, i)
}
R.id.callIcon -> {
val intent = Intent(this, MainActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("action", "call")
intent.putExtra("uap", ua.uap)
intent.putExtra("peer", ContactsActivity.contactName(peerUri))
startActivity(intent)
}
}
finish()
return true
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if ((requestCode == MainActivity.CONTACT_CODE) && (resultCode == Activity.RESULT_OK)) {
setTitle("Chat with ${data.getStringExtra("name")}")
}
}
private fun uaPeerMessages(aor: String, peerUri: String): ArrayList<Message> {
val res = ArrayList<Message>()
for (m in MainActivity.messages)
if ((m.aor == aor) && (m.peerUri == peerUri)) res.add(m)
return res
}
private fun handleMessageResponse(responseCode: Int, time: String) {
val timeStamp = time.toLong()
for (m in chatMessages.reversed())
if (m.timeStamp == timeStamp) {
if (responseCode < 300)
m.direction = R.drawable.arrow_up_green
else
m.direction = R.drawable.arrow_up_red
mlAdapter.notifyDataSetChanged()
return
}
}
external fun message_send(uap: String, peer_uri: String, message: String, time: String): Int
}
@@ -0,0 +1,53 @@
package com.tutpro.baresip
import android.content.Context
import android.graphics.Typeface
import android.text.format.DateUtils.isToday
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import java.text.SimpleDateFormat
import java.util.*
class ChatListAdapter(private val cxt: Context, private var rows: ArrayList<Message>) :
ArrayAdapter<Message>(cxt, R.layout.message, rows) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val message = rows[position]
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val messageView = inflater.inflate(R.layout.message, parent, false)
val directionView = messageView.findViewById(R.id.direction) as ImageView
directionView.setImageResource(message.direction)
val peerView = messageView.findViewById(R.id.peer) as TextView
val contactName = ContactsActivity.contactName(message.peerUri)
if (contactName.startsWith("sip:") &&
(Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor)))
peerView.text = Utils.uriUserPart(message.peerUri)
else
peerView.text = contactName
val timeView = messageView.findViewById(R.id.time) as TextView
val time: String
val cal = GregorianCalendar()
cal.timeInMillis = message.timeStamp
if (isToday(message.timeStamp)) {
val fmt = SimpleDateFormat("HH:mm")
time = fmt.format(cal.time)
} else {
val fmt = SimpleDateFormat("dd.MM")
time = fmt.format(cal.time)
}
timeView.text = time
val textView = messageView.findViewById(R.id.text) as TextView
textView.text = message.message
if (message.new) {
textView.setTypeface(null, Typeface.BOLD)
message.new = false
}
return messageView
}
}
@@ -3,14 +3,11 @@ package com.tutpro.baresip
import android.app.Activity import android.app.Activity
import android.content.* import android.content.*
import android.os.Bundle import android.os.Bundle
import android.support.v4.content.LocalBroadcastManager
import android.support.v7.app.AlertDialog import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import android.widget.AdapterView import android.widget.*
import android.widget.ImageButton
import android.widget.ListView
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
@@ -20,32 +17,34 @@ import java.io.ObjectInputStream
import java.io.ObjectOutputStream import java.io.ObjectOutputStream
import java.util.* import java.util.*
class MessagesActivity: AppCompatActivity() { class ChatsActivity: AppCompatActivity() {
internal lateinit var uaMessages: ArrayList<Message>
internal lateinit var aor: String internal lateinit var aor: String
internal lateinit var mlAdapter: MessageListAdapter internal lateinit var listView: ListView
internal lateinit var clAdapter: ChatListAdapter
internal lateinit var peerUri: AutoCompleteTextView
internal lateinit var plusButton: ImageButton internal lateinit var plusButton: ImageButton
internal lateinit var serviceEventReceiver: BroadcastReceiver
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_messages) setContentView(R.layout.activity_chats)
val listView = findViewById(R.id.messages) as ListView listView = findViewById(R.id.chats) as ListView
plusButton = findViewById(R.id.plusButton) as ImageButton plusButton = findViewById(R.id.plusButton) as ImageButton
aor = intent.extras.getString("aor") aor = intent.extras.getString("aor")
uaMessages = uaMessages(aor) uaMessages = uaMessages(aor)
mlAdapter = MessageListAdapter(this, uaMessages) clAdapter = ChatListAdapter(this, uaMessages)
listView.adapter = mlAdapter listView.adapter = clAdapter
listView.isLongClickable = true listView.isLongClickable = true
listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
val i = Intent(this@MessagesActivity, MessageActivity::class.java) val i = Intent(this, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", aor) b.putString("aor", aor)
b.putString("peer", uaMessages[pos].peerURI) b.putString("peer", uaMessages[pos].peerUri)
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE) startActivityForResult(i, MainActivity.MESSAGE_CODE)
} }
@@ -57,55 +56,77 @@ class MessagesActivity: AppCompatActivity() {
val i = Intent(this, ContactActivity::class.java) val i = Intent(this, ContactActivity::class.java)
val b = Bundle() val b = Bundle()
b.putBoolean("new", true) b.putBoolean("new", true)
b.putString("uri", uaMessages[pos].peerURI) b.putString("uri", uaMessages[pos].peerUri)
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MainActivity.CONTACT_CODE) startActivityForResult(i, MainActivity.CONTACT_CODE)
} }
DialogInterface.BUTTON_NEGATIVE -> { DialogInterface.BUTTON_NEGATIVE -> {
MainActivity.messages.remove(uaMessages[pos]) val peerUri = uaMessages[pos].peerUri
saveMessages() val msgs = ArrayList<Message>()
uaMessages.removeAt(pos) for (m in MainActivity.messages)
if (uaMessages.size == 0) { if ((m.aor != aor) || (m.peerUri != peerUri))
val i = Intent() msgs.add(m)
setResult(Activity.RESULT_CANCELED, i) else
finish() clAdapter.remove(m)
} clAdapter.notifyDataSetChanged()
mlAdapter.notifyDataSetChanged() MainActivity.messages = msgs
uaMessages = uaMessages(aor)
} }
DialogInterface.BUTTON_POSITIVE -> { DialogInterface.BUTTON_POSITIVE -> {
} }
} }
} }
val builder = AlertDialog.Builder(this@MessagesActivity, val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat)
R.style.Theme_AppCompat) val peer = ContactsActivity.contactName(uaMessages[pos].peerUri)
if (ContactsActivity.contactName(uaMessages[pos].peerURI).startsWith("sip:")) if (peer.startsWith("sip:"))
builder.setMessage("Do you want to add ${uaMessages[pos].peerURI} to contacs or " + builder.setMessage("Do you want to delete chat with $peer or add peer to contacts?")
"delete message from history?")
.setPositiveButton("Cancel", dialogClickListener) .setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete Message", dialogClickListener) .setNegativeButton("Delete Chat", dialogClickListener)
.setNeutralButton("Add Contact", dialogClickListener) .setNeutralButton("Add Contact", dialogClickListener)
.show() .show()
else else
builder.setMessage("Do you want to delete message from history?") builder.setMessage("Do you want to delete chat with $peer?")
.setPositiveButton("Cancel", dialogClickListener) .setPositiveButton("Cancel", dialogClickListener)
.setNegativeButton("Delete Message", dialogClickListener) .setNegativeButton("Delete Chat", dialogClickListener)
.show() .show()
true true
} }
peerUri = findViewById(R.id.peerUri) as AutoCompleteTextView
peerUri.threshold = 2
peerUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
ContactsActivity.contacts.map{Contact -> Contact.name}))
plusButton.setOnClickListener { plusButton.setOnClickListener {
val i = Intent(this@MessagesActivity, MessageActivity::class.java) val uriText = peerUri.text.toString().trim()
if (uriText.length > 0) {
var uri = ContactsActivity.findContactURI(uriText)
if (!uri.startsWith("sip:")) {
uri = "sip:$uri"
if (!uri.contains("@")) {
val host = aor.substring(aor.indexOf("@") + 1)
uri = "$uri@$host"
}
}
if (!Utils.checkSipUri(uri)) {
Utils.alertView(this, "Notice", "Invalid SIP URI '$uri'")
} else {
peerUri.text.clear()
peerUri.isCursorVisible = false
val i = Intent(this@ChatsActivity, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", aor) b.putString("aor", aor)
b.putString("peer", "") b.putString("peer", uri)
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MainActivity.MESSAGE_CODE) startActivityForResult(i, MainActivity.MESSAGE_CODE)
} }
}
}
val peer = intent.extras.getString("peer") val peer = intent.extras.getString("peer")
if (peer != null) { if (peer != "") {
val i = Intent(this@MessagesActivity, MessageActivity::class.java) val i = Intent(this, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", aor) b.putString("aor", aor)
b.putString("peer", peer) b.putString("peer", peer)
@@ -113,22 +134,17 @@ class MessagesActivity: AppCompatActivity() {
startActivityForResult(i, MainActivity.MESSAGE_CODE) startActivityForResult(i, MainActivity.MESSAGE_CODE)
} }
serviceEventReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
handleMessageResponse(intent.getIntExtra("response code", 0),
intent.getStringExtra("time"))
} }
}
LocalBroadcastManager.getInstance(this).registerReceiver(serviceEventReceiver,
IntentFilter("message response"))
override fun onPause() {
saveMessages()
super.onPause()
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
Log.d("Baresip", "Back array was pressed at Messages") Log.d("Baresip", "Back array was pressed at Chats")
saveMessages()
val i = Intent() val i = Intent()
setResult(Activity.RESULT_CANCELED, i) setResult(Activity.RESULT_CANCELED, i)
finish() finish()
@@ -138,46 +154,32 @@ class MessagesActivity: AppCompatActivity() {
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
Log.d("Baresip", "onActivityResult at Messages") Log.d("Baresip", "onActivityResult $requestCode $resultCode")
when (requestCode) { if ((requestCode == MainActivity.MESSAGE_CODE) && (resultCode == Activity.RESULT_OK)) {
MainActivity.MESSAGE_CODE -> { clAdapter.clear()
if (resultCode == RESULT_OK) { uaMessages = uaMessages(aor)
mlAdapter.notifyDataSetChanged() clAdapter = ChatListAdapter(this, uaMessages)
} listView.adapter = clAdapter
}
}
}
private fun handleMessageResponse(responseCode: Int, time: String) {
if (responseCode < 300)
updateMessageDirection(time.toLong(), R.drawable.arrow_up_green)
else
updateMessageDirection(time.toLong(), R.drawable.arrow_up_red)
mlAdapter.notifyDataSetChanged()
}
fun updateMessageDirection(timeStamp: Long, direction: Int) {
for (m in uaMessages.reversed())
if (m.timeStamp == timeStamp) {
m.direction = direction
return
} }
} }
private fun uaMessages(aor: String) : ArrayList<Message> { private fun uaMessages(aor: String) : ArrayList<Message> {
val res = ArrayList<Message>() val res = ArrayList<Message>()
for (m in MainActivity.messages.reversed()) { for (m in MainActivity.messages.reversed()) {
if (m.aor == aor) { if (m.aor != aor) continue
res.add(m) var found = false
for (r in res)
if (r.peerUri == m.peerUri) {
found = true
break
} }
if (!found) res.add(m)
} }
return res return res
} }
companion object { companion object {
var uaMessages = ArrayList<Message>()
fun archiveUaMessage(aor: String, time: Long) { fun archiveUaMessage(aor: String, time: Long) {
for (i in MainActivity.messages.indices.reversed()) for (i in MainActivity.messages.indices.reversed())
if ((MainActivity.messages[i].aor == aor) && if ((MainActivity.messages[i].aor == aor) &&
@@ -198,18 +200,6 @@ class MessagesActivity: AppCompatActivity() {
} }
} }
fun addMessage(message: Message) {
if ((MainActivity.messages.filter{it.aor == message.aor}).size >=
MainActivity.MESSAGE_HISTORY_SIZE)
for (i in MainActivity.messages.indices)
if (MainActivity.messages[i].aor == message.aor) {
MainActivity.messages.removeAt(i)
break
}
MainActivity.messages.add(message)
saveMessages()
}
fun saveMessages() { fun saveMessages() {
val file = File(MainActivity.filesPath, "messages") val file = File(MainActivity.filesPath, "messages")
try { try {
@@ -1,5 +1,6 @@
package com.tutpro.baresip package com.tutpro.baresip
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
@@ -87,14 +88,15 @@ class ContactActivity : AppCompatActivity() {
ContactsActivity.contacts.sortBy { Contact -> Contact.name } ContactsActivity.contacts.sortBy { Contact -> Contact.name }
ContactsActivity.saveContacts() ContactsActivity.saveContacts()
setResult(RESULT_OK, i) i.putExtra("name", newName)
setResult(Activity.RESULT_OK, i)
finish() finish()
return true return true
} else if (item.itemId == android.R.id.home) { } else if (item.itemId == android.R.id.home) {
Log.d("Baresip", "Back array was pressed at Contact") Log.d("Baresip", "Back array was pressed at Contact")
setResult(RESULT_CANCELED, i) setResult(Activity.RESULT_CANCELED, i)
finish() finish()
return true return true
@@ -31,7 +31,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
nameView.setPadding(6, 6, 0, 6) nameView.setPadding(6, 6, 0, 6)
if (aor != "") { if (aor != "") {
nameView.setOnClickListener {_ -> nameView.setOnClickListener {_ ->
val i = Intent(cxt, MessageActivity::class.java) val i = Intent(cxt, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", aor) b.putString("aor", aor)
b.putString("peer", ContactsActivity.contacts[position].uri) b.putString("peer", ContactsActivity.contacts[position].uri)
@@ -324,12 +324,13 @@ class MainActivity : AppCompatActivity() {
startActivityForResult(i, CONTACTS_CODE) startActivityForResult(i, CONTACTS_CODE)
} }
MessagesActivity.restoreMessages(applicationContext.filesDir.path) ChatsActivity.restoreMessages(applicationContext.filesDir.path)
messagesButton.setOnClickListener { messagesButton.setOnClickListener {
if (aorSpinner.selectedItemPosition >= 0) { if (aorSpinner.selectedItemPosition >= 0) {
val i = Intent(this@MainActivity, MessagesActivity::class.java) val i = Intent(this@MainActivity, ChatsActivity::class.java)
val b = Bundle() val b = Bundle()
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor) b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
b.putString("peer", "")
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MESSAGES_CODE) startActivityForResult(i, MESSAGES_CODE)
} }
@@ -642,20 +643,22 @@ class MainActivity : AppCompatActivity() {
} }
} }
"message" -> { "message" -> {
val peer_uri = params[1] val peerUri = params[1]
val msg = params[2] val msgText = params[2]
val time = params[3] val time = params[3]
val new_message = Message(aor, peer_uri, R.drawable.arrow_down_green, msg, val newMsg = Message(aor, peerUri, R.drawable.arrow_down_green, msgText,
time.toLong(), true) time.toLong(), true)
Log.d("Baresip", "Incoming message $aor/$peer_uri/$msg") Log.d("Baresip", "Incoming message $aor/$peerUri/$msgText")
MessagesActivity.addMessage(new_message) messages.add(newMsg)
ChatsActivity.saveMessages()
if (Utils.isVisible()) { if (Utils.isVisible()) {
if (ua != uas[aorSpinner.selectedItemPosition]) if (ua != uas[aorSpinner.selectedItemPosition])
aorSpinner.setSelection(account_index) aorSpinner.setSelection(account_index)
val i = Intent(applicationContext, MessagesActivity::class.java) val i = Intent(applicationContext, ChatsActivity::class.java)
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val b = Bundle() val b = Bundle()
b.putString("aor", ua.account.aor) b.putString("aor", ua.account.aor)
b.putString("peer", peerUri)
i.putExtras(b) i.putExtras(b)
startActivity(i) startActivity(i)
} }
@@ -670,7 +673,8 @@ class MainActivity : AppCompatActivity() {
break break
} }
} }
if (ua == uas[aorSpinner.selectedItemPosition]) if ((aorSpinner.selectedItemPosition >= 0) &&
(ua == uas[aorSpinner.selectedItemPosition]))
if (acc.vmNew > 0) if (acc.vmNew > 0)
voicemailButton.setImageResource(R.drawable.voicemail_new) voicemailButton.setImageResource(R.drawable.voicemail_new)
else else
@@ -735,7 +739,7 @@ class MainActivity : AppCompatActivity() {
val aor = ua.account.aor val aor = ua.account.aor
when (action) { when (action) {
"reply" -> { "reply" -> {
val i = Intent(this@MainActivity, MessagesActivity::class.java) val i = Intent(this@MainActivity, ChatActivity::class.java)
val b = Bundle() val b = Bundle()
if (ua != uas[aorSpinner.selectedItemPosition]) { if (ua != uas[aorSpinner.selectedItemPosition]) {
for (account_index in uas.indices) { for (account_index in uas.indices) {
@@ -749,15 +753,15 @@ class MainActivity : AppCompatActivity() {
b.putString("peer", intent.getStringExtra("peer")) b.putString("peer", intent.getStringExtra("peer"))
b.putBoolean("reply", true) b.putBoolean("reply", true)
i.putExtras(b) i.putExtras(b)
startActivityForResult(i, MESSAGES_CODE) startActivityForResult(i, MESSAGE_CODE)
} }
"archive" -> { "archive" -> {
MessagesActivity.archiveUaMessage(ua.account.aor, ChatsActivity.archiveUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong()) intent.getStringExtra("time").toLong())
moveTaskToBack(true) moveTaskToBack(true)
} }
"delete" -> { "delete" -> {
MessagesActivity.deleteUaMessage(ua.account.aor, ChatsActivity.deleteUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong()) intent.getStringExtra("time").toLong())
moveTaskToBack(true) moveTaskToBack(true)
} }
@@ -2,6 +2,6 @@ package com.tutpro.baresip
import java.io.Serializable import java.io.Serializable
class Message(val aor: String, val peerURI: String, var direction: Int, val message: String, class Message(val aor: String, val peerUri: String, var direction: Int, val message: String,
val timeStamp: Long, var new: Boolean): Serializable { val timeStamp: Long, var new: Boolean): Serializable {
} }
@@ -1,116 +0,0 @@
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.AppCompatActivity
import android.util.Log
import android.view.MenuItem
import android.view.inputmethod.InputMethodManager
import android.widget.*
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?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_message)
val aor = intent.extras.getString("aor")
val peerURI = intent.extras.getString("peer")
Log.d("Baresip", "peerURI is $peerURI")
val ua = Account.findUa(aor)
if (ua == null) {
Log.e("Baresip", "MessageActivity did not find ua of $aor")
val i = Intent()
setResult(Activity.RESULT_CANCELED, i)
finish()
}
val title = findViewById(R.id.messageToTitle) as TextView
message = findViewById(R.id.text) as EditText
receiver = findViewById(R.id.receiver) as AutoCompleteTextView
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
title.text = "Message or call to ..."
if (peerURI == "") {
receiver.threshold = 2
receiver.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
ContactsActivity.contacts.map { Contact -> Contact.name }))
receiver.requestFocus()
} else {
receiver.setText(ContactsActivity.contactName(peerURI), false)
message.requestFocus()
}
sendButton = findViewById(R.id.sendButton) as ImageButton
sendButton.setOnClickListener {
val receiverText = receiver.text.toString()
val msg = message.text.toString()
if (receiverText.length > 0) {
var uri = ContactsActivity.findContactURI(receiverText)
if (!uri.startsWith("sip:")) uri = "sip:$uri"
if (!uri.contains("@")) {
val host = aor.substring(aor.indexOf("@") + 1)
uri = "$uri@$host"
}
if (msg.length > 0) {
imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0)
imm.hideSoftInputFromWindow(message.getWindowToken(), 0)
val time = System.currentTimeMillis()
val res = message_send(ua!!.uap, uri, msg, time.toString())
if (res != 0) {
Toast.makeText(getApplicationContext(), "Sending of message failed!",
Toast.LENGTH_SHORT).show()
} else {
val new_message = Message(aor, uri, R.drawable.arrow_up_yellow, msg, time,
false)
MessagesActivity.addMessage(new_message)
MessagesActivity.uaMessages.add(0, new_message)
val i = Intent()
setResult(Activity.RESULT_OK, i)
finish()
}
}
}
}
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 {
when (item.itemId) {
android.R.id.home -> {
imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0)
imm.hideSoftInputFromWindow(message.getWindowToken(), 0)
val i = Intent()
setResult(Activity.RESULT_CANCELED, i)
finish()
}
}
return true
}
external fun message_send(uap: String, peer_uri: String, message: String, time: String) : Int
}
@@ -22,13 +22,6 @@ class MessageListAdapter(private val cxt: Context, private val rows: ArrayList<M
val messageView = inflater.inflate(R.layout.message, parent, false) val messageView = inflater.inflate(R.layout.message, parent, false)
val directionView = messageView.findViewById(R.id.direction) as ImageView val directionView = messageView.findViewById(R.id.direction) as ImageView
directionView.setImageResource(message.direction) directionView.setImageResource(message.direction)
val peerView = messageView.findViewById(R.id.peer) as TextView
val contactName = ContactsActivity.contactName(message.peerURI)
if (contactName.startsWith("sip:") &&
(Utils.uriHostPart(message.peerURI) == Utils.uriHostPart(message.aor)))
peerView.text = Utils.uriUserPart(message.peerURI)
else
peerView.text = contactName
val timeView = messageView.findViewById(R.id.time) as TextView val timeView = messageView.findViewById(R.id.time) as TextView
val time: String val time: String
val cal = GregorianCalendar() val cal = GregorianCalendar()
@@ -43,10 +36,7 @@ class MessageListAdapter(private val cxt: Context, private val rows: ArrayList<M
timeView.text = time timeView.text = time
val textView = messageView.findViewById(R.id.text) as TextView val textView = messageView.findViewById(R.id.text) as TextView
textView.text = message.message textView.text = message.message
if (message.new) { if (message.new) textView.setTypeface(null, Typeface.BOLD)
textView.setTypeface(null, Typeface.BOLD)
message.new = false
}
return messageView return messageView
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

+2 -2
View File
@@ -88,7 +88,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="SIP URI of Proxy Server" android:hint="SIP URI of Proxy Server"
android:textSize="18sp" android:textSize="18sp"
android:inputType="textUri" android:inputType="textEmailAddress"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
</EditText> </EditText>
@@ -97,7 +97,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="SIP URI of another Proxy Server" android:hint="SIP URI of another Proxy Server"
android:textSize="18sp" android:textSize="18sp"
android:inputType="textUri" android:inputType="textEmailAddress"
android:layout_width="fill_parent"> android:layout_width="fill_parent">
</EditText> </EditText>
@@ -27,6 +27,7 @@
android:textSize="20sp" android:textSize="20sp"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_marginStart="0dp" android:layout_marginStart="0dp"
android:layout_toLeftOf="@+id/addAccount"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
android:hint="SIP URI user@domain" > android:hint="SIP URI user@domain" >
</EditText> </EditText>
+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".ChatActivity" >
<ListView
android:id="@+id/messages"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:transcriptMode="alwaysScroll"
android:layout_above="@id/text">
</ListView>
<EditText
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:inputType="textMultiLine"
android:scrollHorizontally="false"
android:importantForAutofill="no"
android:layout_alignParentBottom="true"
android:layout_marginTop="10dp"
android:layout_toStartOf="@id/sendButton"
android:hint="New message" >
</EditText>
<ImageButton
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/send"
android:background="@null"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="2dp" >
</ImageButton>
</RelativeLayout>
@@ -7,12 +7,27 @@
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MessagesActivity"> tools:context=".ChatsActivity" >
<ListView <ListView
android:id="@+id/messages" android:id="@+id/chats"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" /> android:layout_height="fill_parent" >
</ListView>
<AutoCompleteTextView
android:id="@+id/peerUri"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="18sp"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="0dp"
android:layout_toStartOf="@+id/plusButton"
android:inputType="textEmailAddress"
android:hint="Chat Peer" >
</AutoCompleteTextView>
<ImageButton <ImageButton
android:id="@+id/plusButton" android:id="@+id/plusButton"
@@ -25,5 +40,3 @@
</ImageButton> </ImageButton>
</RelativeLayout> </RelativeLayout>
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:orientation="vertical"
tools:context="com.tutpro.baresip.MessageActivity" >
<TextView
android:id="@+id/messageToTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@android:color/black"
android:text="Message to ..." >
</TextView>
<AutoCompleteTextView
android:id="@+id/receiver"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:textSize="20sp"
android:hint="Contact name or SIP URI" >
<requestFocus />
</AutoCompleteTextView>
<EditText
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:inputType="textMultiLine"
android:scrollHorizontally="false"
android:hint="Message">
</EditText>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<ImageButton
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/send"
android:background="@null" >
</ImageButton>
<ImageButton
android:id="@+id/callButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/call"
android:background="@null" >
</ImageButton>
</LinearLayout>
</LinearLayout>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/callIcon"
android:title=""
app:showAsAction="always"
android:icon="@drawable/ic_action_call"
/>
</menu>