Included in call history both start and stop time of calls

Improved display of call history time value
This commit is contained in:
Juha Heinanen
2022-01-16 14:42:16 +02:00
parent 8b104e8dea
commit b49a989be8
9 changed files with 108 additions and 55 deletions
@@ -61,7 +61,7 @@ class AccountListAdapter(private val cxt: Context, private val rows: ArrayList<A
viewHolder.aorView.text)) viewHolder.aorView.text))
setPositiveButton(cxt.getText(R.string.delete)) { dialog, _ -> setPositiveButton(cxt.getText(R.string.delete)) { dialog, _ ->
Api.ua_destroy(ua.uap) Api.ua_destroy(ua.uap)
CallHistory.clear(ua.account.aor) NewCallHistory.clear(ua.account.aor)
Message.clear(ua.account.aor) Message.clear(ua.account.aor)
ua.remove() ua.remove()
AccountsActivity.generateAccounts() AccountsActivity.generateAccounts()
@@ -365,7 +365,20 @@ class BaresipService: Service() {
File(filesDir, "history").renameTo(File(filesDir, "calls")) File(filesDir, "history").renameTo(File(filesDir, "calls"))
Contact.restore() Contact.restore()
CallHistory.restore() val history = CallHistory.get()
if (history.isEmpty()) {
NewCallHistory.restore()
} else {
for (old in history) {
val new = NewCallHistory(old.aor, old.peerUri, old.direction)
new.stopTime = old.time
if (old.connected)
new.startTime = GregorianCalendar(0, 0, 0)
callHistory.add(new)
}
NewCallHistory.save()
}
Message.restore() Message.restore()
linkAddresses = linkAddresses() linkAddresses = linkAddresses()
@@ -427,11 +440,8 @@ class BaresipService: Service() {
val peerUri = call.peerUri val peerUri = call.peerUri
val aor = call.ua.account.aor val aor = call.ua.account.aor
Log.d(TAG, "Aor $aor rejected incoming call $callp from $peerUri") Log.d(TAG, "Aor $aor rejected incoming call $callp from $peerUri")
call.rejected = true
Api.ua_hangup(call.ua.uap, callp, 486, "Rejected") Api.ua_hangup(call.ua.uap, callp, 486, "Rejected")
if (call.ua.account.callHistory) {
CallHistory.add(CallHistory(aor, peerUri, "in", false))
CallHistory.save()
}
} }
} }
@@ -603,11 +613,6 @@ class BaresipService: Service() {
!Utils.checkPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO))) { !Utils.checkPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO))) {
Log.d(TAG, "Auto-rejecting incoming call $uap/$callp/$peerUri") Log.d(TAG, "Auto-rejecting incoming call $uap/$callp/$peerUri")
Api.ua_hangup(uap, callp, 486, "Busy Here") Api.ua_hangup(uap, callp, 486, "Busy Here")
if (ua.account.callHistory) {
CallHistory.add(CallHistory(aor, peerUri, "in", false))
CallHistory.save()
ua.account.missedCalls = true
}
playUnInterrupted(R.raw.callwaiting, 1) playUnInterrupted(R.raw.callwaiting, 1)
if (!Utils.isVisible()) if (!Utils.isVisible())
return return
@@ -707,11 +712,8 @@ class BaresipService: Service() {
Log.d(TAG, "AoR $aor call $callp established") Log.d(TAG, "AoR $aor call $callp established")
call.status = "connected" call.status = "connected"
call.onhold = false call.onhold = false
if (ua.account.callHistory) { if (ua.account.callHistory)
CallHistory.add(CallHistory(aor, call.peerUri, call.dir, true)) call.startTime = GregorianCalendar()
CallHistory.save()
call.hasHistory = true
}
if (!Utils.isVisible()) if (!Utils.isVisible())
return return
} }
@@ -832,12 +834,16 @@ class BaresipService: Service() {
am.mode = AudioManager.MODE_NORMAL am.mode = AudioManager.MODE_NORMAL
proximitySensing(false) proximitySensing(false)
} }
if (ua.account.callHistory && !call.hasHistory) { val missed = call.startTime == null && call.dir == "in" && !call.rejected
CallHistory.add(CallHistory(aor, call.peerUri, call.dir, false)) if (ua.account.callHistory) {
CallHistory.save() val history = NewCallHistory(aor, call.peerUri, call.dir)
if (call.dir == "in") ua.account.missedCalls = true history.startTime = call.startTime
history.stopTime = GregorianCalendar()
NewCallHistory.add(history)
NewCallHistory.save()
ua.account.missedCalls = ua.account.missedCalls || missed
} }
if (!Utils.isVisible() && !call.hasHistory && call.dir == "in") { if (!Utils.isVisible() && missed) {
val caller = Utils.friendlyUri(ContactsActivity.contactName(call.peerUri), val caller = Utils.friendlyUri(ContactsActivity.contactName(call.peerUri),
Utils.aorDomain(aor)) Utils.aorDomain(aor))
val intent = Intent(applicationContext, MainActivity::class.java) val intent = Intent(applicationContext, MainActivity::class.java)
@@ -1446,7 +1452,7 @@ class BaresipService: Service() {
val uas = ArrayList<UserAgent>() val uas = ArrayList<UserAgent>()
val status = ArrayList<Int>() val status = ArrayList<Int>()
val calls = ArrayList<Call>() val calls = ArrayList<Call>()
var callHistory = ArrayList<CallHistory>() var callHistory = ArrayList<NewCallHistory>()
var messages = ArrayList<Message>() var messages = ArrayList<Message>()
val contacts = ArrayList<Contact>() val contacts = ArrayList<Contact>()
val chatTexts: MutableMap<String, String> = mutableMapOf() val chatTexts: MutableMap<String, String> = mutableMapOf()
@@ -1,16 +1,17 @@
package com.tutpro.baresip package com.tutpro.baresip
import android.text.TextWatcher import android.text.TextWatcher
import java.util.ArrayList import java.util.*
class Call(val callp: String, val ua: UserAgent, val peerUri: String, val dir: String, class Call(val callp: String, val ua: UserAgent, val peerUri: String, val dir: String,
var status: String, val dtmfWatcher: TextWatcher?) { var status: String, val dtmfWatcher: TextWatcher?) {
var onhold = false var onhold = false
var held = false var held = false
var rejected = false
var security = 0 var security = 0
var zid = "" var zid = ""
var hasHistory = false var startTime: GregorianCalendar? = null // Set when call is established
var referTo = "" var referTo = ""
fun add() { fun add() {
@@ -4,16 +4,17 @@ import java.io.*
import java.util.ArrayList import java.util.ArrayList
import java.util.GregorianCalendar import java.util.GregorianCalendar
class CallHistory(val aor: String, val peerUri: String, val direction: String, class NewCallHistory(val aor: String, val peerUri: String, val direction: String) : Serializable {
val connected: Boolean) : Serializable {
val time: GregorianCalendar = GregorianCalendar() var startTime: GregorianCalendar? = null // Set to time when call is established (if ever)
var stopTime = GregorianCalendar() // Set to time when call is closed
companion object { companion object {
private const val CALL_HISTORY_SIZE = 100 private const val serialVersionUID: Long = 1
private const val CALL_HISTORY_SIZE = 128
fun add(history: CallHistory) { fun add(history: NewCallHistory) {
BaresipService.callHistory.add(history) BaresipService.callHistory.add(history)
if (aorHistorySize(history.aor) > CALL_HISTORY_SIZE) { if (aorHistorySize(history.aor) > CALL_HISTORY_SIZE) {
var i = 0 var i = 0
@@ -35,7 +36,7 @@ class CallHistory(val aor: String, val peerUri: String, val direction: String,
return BaresipService.callHistory.filter { it.aor == aor }.count() return BaresipService.callHistory.filter { it.aor == aor }.count()
} }
fun aorLatestHistory(aor: String): CallHistory? { fun aorLatestHistory(aor: String): NewCallHistory? {
for (h in BaresipService.callHistory.reversed()) for (h in BaresipService.callHistory.reversed())
if (h.aor == aor) return h if (h.aor == aor) return h
return null return null
@@ -43,7 +44,7 @@ class CallHistory(val aor: String, val peerUri: String, val direction: String,
fun save() { fun save() {
Log.d(TAG, "Saving history of ${BaresipService.callHistory.size} calls") Log.d(TAG, "Saving history of ${BaresipService.callHistory.size} calls")
val file = File(BaresipService.filesPath, "calls") val file = File(BaresipService.filesPath, "call_history")
try { try {
val fos = FileOutputStream(file) val fos = FileOutputStream(file)
val oos = ObjectOutputStream(fos) val oos = ObjectOutputStream(fos)
@@ -57,25 +58,56 @@ class CallHistory(val aor: String, val peerUri: String, val direction: String,
} }
fun restore() { fun restore() {
val file = File(BaresipService.filesPath, "calls") val file = File(BaresipService.filesPath, "call_history")
if (file.exists()) if (file.exists()) {
try { try {
val fis = FileInputStream(file) val fis = FileInputStream(file)
val ois = ObjectInputStream(fis) val ois = ObjectInputStream(fis)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
BaresipService.callHistory = ois.readObject() as ArrayList<CallHistory> BaresipService.callHistory = ois.readObject() as ArrayList<NewCallHistory>
ois.close() ois.close()
fis.close() fis.close()
Log.d(TAG, "Restored history of ${BaresipService.callHistory.size} calls") Log.d(TAG, "Restored history of ${BaresipService.callHistory.size} calls")
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "InputStream exception: - $e") Log.e(TAG, "InputStream exception: - $e")
} }
}
} }
@Suppress("UNUSED") @Suppress("UNUSED")
fun print() { fun print() {
for (h in BaresipService.callHistory) for (h in BaresipService.callHistory)
Log.d(TAG, "[${h.aor}, ${h.peerUri}, ${h.direction}, ${h.connected}]") Log.d(TAG, "[${h.aor}, ${h.peerUri}, ${h.direction}, ${h.startTime}, ${h.stopTime}]")
}
}
}
class CallHistory(val aor: String, val peerUri: String, val direction: String,
val connected: Boolean) : Serializable {
val time: GregorianCalendar = GregorianCalendar()
companion object {
fun get(): ArrayList<CallHistory> {
val file = File(BaresipService.filesPath, "calls")
var result = ArrayList<CallHistory>()
if (file.exists()) {
try {
val fis = FileInputStream(file)
val ois = ObjectInputStream(fis)
@Suppress("UNCHECKED_CAST")
result = ois.readObject() as ArrayList<CallHistory>
ois.close()
fis.close()
Log.d(TAG, "Got history of ${result.size} calls")
file.delete()
} catch (e: Exception) {
Log.e(TAG, "InputStream exception: - $e")
}
}
return result
} }
} }
@@ -84,7 +84,7 @@ class CallListAdapter(private val cxt: Context, private val rows: ArrayList<Call
else else
viewHolder.peerURIView.text = contactName viewHolder.peerURIView.text = contactName
viewHolder.timeView.text = callRow.time viewHolder.timeView.text = callRow.stopTime
return rowView return rowView
} }
@@ -1,7 +1,6 @@
package com.tutpro.baresip package com.tutpro.baresip
class CallRow(val aor: String, val peerUri: String, direction: Int, val time: String, class CallRow(val aor: String, val peerUri: String, val direction: Int, val stopTime: String, val index: Int) {
index: Int) {
val directions = ArrayList<Int>() val directions = ArrayList<Int>()
val indexes = ArrayList<Int>() val indexes = ArrayList<Int>()
@@ -10,4 +9,5 @@ class CallRow(val aor: String, val peerUri: String, direction: Int, val time: St
directions.add(direction) directions.add(direction)
indexes.add(index) indexes.add(index)
} }
} }
@@ -16,8 +16,8 @@ import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import com.tutpro.baresip.databinding.ActivityCallsBinding import com.tutpro.baresip.databinding.ActivityCallsBinding
import java.util.ArrayList
import java.text.DateFormat import java.text.DateFormat
import java.util.*
class CallsActivity : AppCompatActivity() { class CallsActivity : AppCompatActivity() {
@@ -25,7 +25,6 @@ class CallsActivity : AppCompatActivity() {
private lateinit var account: Account private lateinit var account: Account
private lateinit var clAdapter: CallListAdapter private lateinit var clAdapter: CallListAdapter
private var uaHistory = ArrayList<CallRow>()
private var aor = "" private var aor = ""
private var lastClick: Long = 0 private var lastClick: Long = 0
@@ -111,7 +110,7 @@ class CallsActivity : AppCompatActivity() {
} }
DialogInterface.BUTTON_POSITIVE -> { DialogInterface.BUTTON_POSITIVE -> {
removeUaHistoryAt(pos) removeUaHistoryAt(pos)
CallHistory.save() NewCallHistory.save()
clAdapter.notifyDataSetChanged() clAdapter.notifyDataSetChanged()
} }
DialogInterface.BUTTON_NEUTRAL -> { DialogInterface.BUTTON_NEUTRAL -> {
@@ -162,8 +161,8 @@ class CallsActivity : AppCompatActivity() {
setMessage(String.format(getString(R.string.delete_history_alert), setMessage(String.format(getString(R.string.delete_history_alert),
aor.substringAfter(":"))) aor.substringAfter(":")))
setPositiveButton(getText(R.string.delete)) { dialog, _ -> setPositiveButton(getText(R.string.delete)) { dialog, _ ->
CallHistory.clear(aor) NewCallHistory.clear(aor)
CallHistory.save() NewCallHistory.save()
aorGenerateHistory(aor) aorGenerateHistory(aor)
clAdapter.notifyDataSetChanged() clAdapter.notifyDataSetChanged()
dialog.dismiss() dialog.dismiss()
@@ -218,10 +217,8 @@ class CallsActivity : AppCompatActivity() {
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.calls_menu, menu) menuInflater.inflate(R.menu.calls_menu, menu)
return true return true
} }
private fun aorGenerateHistory(aor: String) { private fun aorGenerateHistory(aor: String) {
@@ -230,12 +227,12 @@ class CallsActivity : AppCompatActivity() {
val h = BaresipService.callHistory[i] val h = BaresipService.callHistory[i]
if (h.aor == aor) { if (h.aor == aor) {
val direction: Int = if (h.direction == "in") val direction: Int = if (h.direction == "in")
if (h.connected) if (h.startTime != null)
R.drawable.arrow_down_green R.drawable.arrow_down_green
else else
R.drawable.arrow_down_red R.drawable.arrow_down_red
else else
if (h.connected) if (h.startTime != null)
R.drawable.arrow_up_green R.drawable.arrow_up_green
else else
R.drawable.arrow_up_red R.drawable.arrow_up_red
@@ -243,11 +240,21 @@ class CallsActivity : AppCompatActivity() {
uaHistory.last().directions.add(direction) uaHistory.last().directions.add(direction)
uaHistory.last().indexes.add(i) uaHistory.last().indexes.add(i)
} else { } else {
val fmt: DateFormat = if (isToday(h.time.timeInMillis)) var time: String
DateFormat.getTimeInstance(DateFormat.SHORT) if (isToday(h.stopTime.timeInMillis)) {
else val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
DateFormat.getDateInstance(DateFormat.SHORT) time = getString(R.string.today) + "\n" + fmt.format(h.stopTime.time)
val time = fmt.format(h.time.time) } else {
val month = h.stopTime.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault())
val day = h.stopTime.get(Calendar.DAY_OF_MONTH)
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
if (h.stopTime.get(Calendar.YEAR) == currentYear) {
val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
time = "$month $day" + "\n" + fmt.format(h.stopTime.time)
} else {
time = "$month $day" + "\n" + h.stopTime.get(Calendar.YEAR)
}
}
uaHistory.add(CallRow(h.aor, h.peerUri, direction, time, i)) uaHistory.add(CallRow(h.aor, h.peerUri, direction, time, i))
} }
} }
@@ -260,4 +267,8 @@ class CallsActivity : AppCompatActivity() {
uaHistory.removeAt(i) uaHistory.removeAt(i)
} }
companion object {
var uaHistory = ArrayList<CallRow>()
}
} }
@@ -357,10 +357,12 @@ class MainActivity : AppCompatActivity() {
rejectButton.setOnClickListener { rejectButton.setOnClickListener {
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition] val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
val aor = ua.account.aor val aor = ua.account.aor
val callp = Call.uaCalls(ua, "in")[0].callp val call = Call.uaCalls(ua, "in")[0]
val callp = call.callp
Log.d(TAG, "AoR $aor rejecting call $callp from ${callUri.text}") Log.d(TAG, "AoR $aor rejecting call $callp from ${callUri.text}")
answerButton.isEnabled = false answerButton.isEnabled = false
rejectButton.isEnabled = false rejectButton.isEnabled = false
call.rejected = true
Api.ua_hangup(ua.uap, callp, 486, "Rejected") Api.ua_hangup(ua.uap, callp, 486, "Rejected")
} }
@@ -1677,7 +1679,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
} else { } else {
val latest = CallHistory.aorLatestHistory(aor) val latest = NewCallHistory.aorLatestHistory(aor)
if (latest != null) if (latest != null)
callUri.setText( callUri.setText(
Utils.friendlyUri( Utils.friendlyUri(
+2 -1
View File
@@ -63,7 +63,8 @@
android:paddingStart="0dp" android:paddingStart="0dp"
android:paddingEnd="5dp" android:paddingEnd="5dp"
android:textSize="12sp" android:textSize="12sp"
android:maxLines="1" android:lines="2"
android:maxLines="2"
android:text="" > android:text="" >
</TextView> </TextView>