Introduced new string mobile_service_not_available and corresponding alert

Fixed restore of call and message history
This commit is contained in:
Juha Heinanen
2026-08-08 11:29:32 +03:00
parent 677b02b020
commit 2eeaea706e
12 changed files with 93 additions and 57 deletions

View File

@ -588,6 +588,8 @@ class BaresipService: Service() {
CallHistoryNew.clearRecordings()
CallHistoryNew.save()
Message.save()
Blocked.save()
BlockRule.save()
if (recordings.exists())
recordings.deleteRecursively()
restored.delete()
@ -595,28 +597,21 @@ class BaresipService: Service() {
File(filesDir, "recordings").mkdir()
File(filesDir, "tmp").mkdir()
}.start()
hotSpotAddresses = Utils.hotSpotAddresses()
linkAddresses = linkAddresses()
var addresses = ""
for (la in linkAddresses)
addresses = "$addresses;${la.key};${la.value}"
Log.i(TAG, "Link addresses: $addresses")
activeNetwork = cm.activeNetwork
Log.i(TAG, "Active network: $activeNetwork")
hotSpotAddresses = Utils.hotSpotAddresses()
linkAddresses = linkAddresses()
var addresses = ""
for (la in linkAddresses)
addresses = "$addresses;${la.key};${la.value}"
Log.i(TAG, "Link addresses: $addresses")
registerPhoneAccount()
val userAgent = Config.variable("user_agent")
val software = if (userAgent != "")
userAgent
else
"baresip v${BuildConfig.VERSION_NAME} " +
"(Android ${VERSION.RELEASE}/${System.getProperty("os.arch") ?: "?"})"
Log.i(TAG, "AEC/AGC/NS available = $aecAvailable/$agcAvailable/$nsAvailable")
val userAgent = Config.variable("user_agent")
val software = if (userAgent != "")
userAgent
else
"baresip v${BuildConfig.VERSION_NAME} " +
"(Android ${VERSION.RELEASE}/${System.getProperty("os.arch") ?: "?"})"
Thread {
baresipStart(
filesPath,
addresses.removePrefix(";"),
@ -627,6 +622,15 @@ class BaresipService: Service() {
isServiceRunning = true
activeNetwork = cm.activeNetwork
Log.i(TAG, "Active network: $activeNetwork")
registerPhoneAccount()
Log.i(TAG, "AEC/AGC/NS available = $aecAvailable/$agcAvailable/$nsAvailable")
isServiceRunning = true
if (linkAddresses.isEmpty())
toast(getString(R.string.no_network), Toast.LENGTH_LONG)
@ -1796,11 +1800,15 @@ class BaresipService: Service() {
@Keep
fun started() {
Log.d(TAG, "Received 'started' from baresip")
isNativeReady = true
Handler(Looper.getMainLooper()).post {
isNativeReady = true
addMobileUserAgent()
Account.saveAccounts()
CallHistoryNew.save()
Message.save()
Blocked.save()
BlockRule.save()
if (VERSION.SDK_INT >= 29)
updateMobileStatus()
@ -2400,15 +2408,13 @@ class BaresipService: Service() {
mobileUa.let { ua ->
val isAirplaneModeOn = Utils.isAirplaneModeOn(this)
val status = newStatus ?: if (ua.status == circleGreen.getValue(colorblind))
ua.status
else if (isAirplaneModeOn)
val status = newStatus ?: if (isAirplaneModeOn)
R.drawable.circle_white
else if (ua.status == R.drawable.circle_white)
// Show "Red" (not yet in service)
circleRed.getValue(colorblind)
else if (previousMobileServiceState == ServiceState.STATE_IN_SERVICE)
circleGreen.getValue(colorblind)
else
ua.status
circleRed.getValue(colorblind)
if (ua.status != status) {
Log.d(TAG, "Updating Mobile status to $status")
ua.updateStatus(status)
@ -3222,6 +3228,8 @@ class BaresipService: Service() {
var addressFamily = ""
var dnsServers = listOf<InetAddress>()
val messagesLock = Any()
// <aor, password> of those accounts that have auth username without auth password
val aorPasswords = mutableMapOf<String, String>()
var aecAvailable = false

View File

@ -26,6 +26,7 @@ class BlockRule(val aor: String = "", val pattern: String) {
}
fun save() {
if (!BaresipService.isNativeReady) return
Log.d(TAG, "Saving ${BaresipService.blockRules.size} block rules")
val file = File(BaresipService.filesPath + "/blocking")
try {
@ -46,7 +47,11 @@ class BlockRule(val aor: String = "", val pattern: String) {
if (file.exists())
try {
val jsonString = file.readText()
BaresipService.blockRules = Json.decodeFromString<MutableList<BlockRule>>(jsonString)
val blockRules = Json.decodeFromString<List<BlockRule>>(jsonString)
synchronized(BaresipService.blockRules) {
BaresipService.blockRules.clear()
BaresipService.blockRules.addAll(blockRules)
}
Log.d(TAG, "Restored ${BaresipService.blockRules.size} block rules")
} catch (e: Exception) {
Log.e(TAG, "Deserialization exception: $e")

View File

@ -33,6 +33,7 @@ class Blocked (
}
fun save() {
if (!BaresipService.isNativeReady) return
Log.d(TAG, "Saving ${BaresipService.blocked.size} blocked calls and messages")
val file = File(BaresipService.filesPath + "/blocked")
try {
@ -54,7 +55,10 @@ class Blocked (
try {
val jsonString = file.readText()
val blockedList = Json.decodeFromString<List<Blocked>>(jsonString)
BaresipService.blocked = ArrayList(blockedList)
synchronized(BaresipService.blocked) {
BaresipService.blocked.clear()
BaresipService.blocked.addAll(blockedList)
}
Log.d(TAG, "Restored ${BaresipService.blocked.size} blocked calls and messages")
} catch (e: Exception) {
Log.e(TAG, "Deserialization exception: $e")

View File

@ -76,6 +76,7 @@ class CallHistoryNew(val aor: String, val peerUri: String, val direction: String
}
fun save() {
if (!BaresipService.isNativeReady) return
val historyCopy = synchronized(BaresipService.callHistory) {
ArrayList(BaresipService.callHistory)
}
@ -105,7 +106,10 @@ class CallHistoryNew(val aor: String, val peerUri: String, val direction: String
if (content.startsWith("[")) {
try {
val restoredHistory = Json.decodeFromString<List<CallHistoryNew>>(content)
BaresipService.callHistory = ArrayList(restoredHistory)
synchronized(BaresipService.callHistory) {
BaresipService.callHistory.clear()
BaresipService.callHistory.addAll(restoredHistory)
}
Log.d(TAG, "Restored history of ${BaresipService.callHistory.size} calls from JSON")
return
} catch (e: Exception) {
@ -118,7 +122,10 @@ class CallHistoryNew(val aor: String, val peerUri: String, val direction: String
@Suppress("UNCHECKED_CAST")
val restoredHistory = ois.readObject() as? List<CallHistoryNew>
if (restoredHistory != null) {
BaresipService.callHistory = ArrayList(restoredHistory)
synchronized(BaresipService.callHistory) {
BaresipService.callHistory.clear()
BaresipService.callHistory.addAll(restoredHistory)
}
Log.d(TAG, "Restored history of ${BaresipService.callHistory.size} calls from Java")
save()
}

View File

@ -341,7 +341,7 @@ private fun Calls(
secondAction.value = {
if (ua.account.isMobile && ua.status != circleGreen.getValue(colorblind)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.airplane_mode)
alertMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showAlert.value = true
}
else {
@ -357,8 +357,7 @@ private fun Calls(
if (ua.account.isMobile) {
if (ua.status != circleGreen.getValue(colorblind)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value =
ctx.getString(R.string.airplane_mode)
alertMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showAlert.value = true
}
else if (!Utils.isDefaultSmsApp(ctx)) {

View File

@ -488,7 +488,6 @@ private fun NewMessage(
val showDialog = remember { mutableStateOf(false) }
val dialogMessage = remember { mutableStateOf("") }
val airplaneMode = stringResource(R.string.airplane_mode)
val messageFailed = stringResource(R.string.message_failed)
val noTelephonyProvider = stringResource(R.string.no_telephony_provider)
@ -570,7 +569,7 @@ private fun NewMessage(
addMessage(msg)
if (ua.account.isMobile) {
if (ua.status != circleGreen.getValue(colorblind)) {
dialogMessage.value = airplaneMode
dialogMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showDialog.value = true
}
else {

View File

@ -732,7 +732,7 @@ private fun UrisSection(
onClick = {
if (ua.account.isMobile && ua.status != circleGreen.getValue(colorblind)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.airplane_mode)
alertMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showAlert.value = true
}
else if (ua.account.isMobile && !Utils.isDefaultSmsApp(ctx)) {
@ -770,7 +770,7 @@ private fun UrisSection(
onClick = {
if (ua.account.isMobile && ua.status != circleGreen.getValue(colorblind)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.airplane_mode)
alertMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showAlert.value = true
}
else {

View File

@ -2119,7 +2119,7 @@ private fun makeCall(ctx: Context, viewModel: ViewModel, uriText: String,
}
else if (ua.account.isMobile && ua.status != circleGreen.getValue(colorblind)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.airplane_mode)
alertMessage.value = Utils.mobileStatusMessage(ctx, ua.status)
showAlert.value = true
return
}

View File

@ -10,7 +10,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
var new: Boolean): java.io.Serializable {
fun add() {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
updatedMessages.add(this)
@ -26,18 +26,18 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
if (remove != null)
updatedMessages.remove(remove)
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
}
fun delete() {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
updatedMessages.remove(this)
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
@ -55,25 +55,25 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun clearMessagesOfAor(aor: String) {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
val it = updatedMessages.iterator()
while (it.hasNext()) if (it.next().aor == aor) it.remove()
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
}
fun deleteAorMessage(aor: String, time: Long) {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
for (message in updatedMessages.reversed())
if (message.aor == aor && message.timeStamp == time) {
updatedMessages.remove(message)
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
@ -82,13 +82,13 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun updateAorMessage(aor: String, time: Long) {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
for (message in updatedMessages.reversed())
if (message.aor == aor && message.timeStamp == time) {
message.new = false
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
@ -97,7 +97,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun unreadMessages(aor: String): Boolean {
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
for (message in BaresipService.messages.reversed())
if (message.aor == aor && message.new)
return true
@ -106,7 +106,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun unreadMessagesFromPeer(aor: String, peerUri: String): Boolean {
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
for (message in BaresipService.messages.reversed())
if (message.aor == aor && message.peerUri == peerUri && message.new)
return true
@ -115,7 +115,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun updateMessagesFromPearRead(aor: String, peerUri: String): Boolean {
val updatedMessages = synchronized(BaresipService.messages) {
val updatedMessages = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toMutableList()
}
var updated = false
@ -125,7 +125,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
updated = true
}
if (updated) {
synchronized(BaresipService.messages) {
synchronized(BaresipService.messagesLock) {
BaresipService.messages = updatedMessages.toList()
}
save()
@ -134,7 +134,8 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
}
fun save() {
val messagesCopy = synchronized(BaresipService.messages) {
if (!BaresipService.isNativeReady) return
val messagesCopy = synchronized(BaresipService.messagesLock) {
BaresipService.messages.toList()
}
val file = File(BaresipService.filesPath, "messages")
@ -143,7 +144,7 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
file.writeText(jsonString)
Log.d(TAG, "Saved ${messagesCopy.size} messages in JSON")
} catch (e: Exception) {
Log.e(TAG, "Serialization exception", e)
Log.e(TAG, "Serialization exception: $e")
try {
val fos = FileOutputStream(file)
val oos = ObjectOutputStream(fos)
@ -164,7 +165,9 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
if (content.startsWith("[")) {
try {
val restoredMessages = Json.decodeFromString<List<Message>>(content)
BaresipService.messages = restoredMessages
synchronized(BaresipService.messagesLock) {
BaresipService.messages = restoredMessages
}
Log.d(TAG, "Restored ${BaresipService.messages.size} messages from JSON")
return
} catch (e: Exception) {
@ -177,7 +180,9 @@ class Message(val aor: String, val peerUri: String, val message: String, val tim
@Suppress("UNCHECKED_CAST")
val restoredMessages = ois.readObject() as? List<Message>
if (restoredMessages != null) {
BaresipService.messages = restoredMessages
synchronized(BaresipService.messagesLock) {
BaresipService.messages = restoredMessages
}
Log.d(TAG, "Restored ${BaresipService.messages.size} messages from Java")
save()
}

View File

@ -903,6 +903,13 @@ object Utils {
) != 0
}
fun mobileStatusMessage(ctx: Context, status: Int): String {
return if (status == R.drawable.circle_white)
ctx.getString(R.string.airplane_mode)
else
ctx.getString(R.string.mobile_service_not_available)
}
@Suppress("unused")
fun isPSTNCallActive(ctx: Context): Boolean {
val tm = ctx.getSystemService(Context.TELECOM_SERVICE) as? TelecomManager ?: return false

View File

@ -642,6 +642,7 @@
<string name="no_notifications">Et voi käyttää tätä sovellusta ilman Ilmoitukset-lupaa.</string>
<string name="airplane_mode">Laite on lentotilassa. Poista lentotila, jos haluat käyttää
mobiilitiliä.</string>
<string name="mobile_service_not_available">Mobiilipalvelu ei ole käytettävissä.</string>
<string name="no_calls">Et voi soittaa puheluita tai vastata niihin ilman Mikrofoni-lupaa.</string>
<string name="no_video_calls">Salli Kamera-lupa jotta voit soittaa videopuheluita ja vastata niihin.</string>
<string name="no_backup">Et voi tallentaa sovelluksen tietoja ilman Tallennustila-lupaa.</string>

View File

@ -627,6 +627,7 @@
<string name="no_notifications">You are not able to use this application without \"Notifications\"
permission.</string>
<string name="airplane_mode">Airplane mode is ON. Turn it OFF to use mobile account.</string>
<string name="mobile_service_not_available">Mobile service is not available.</string>
<string name="no_calls">baresip needs \"Microphone\" permission for voice calls.</string>
<string name="no_video_calls">Grant \"Camera\" permission to make or answer video calls.</string>
<string name="no_backup">You are not able create backup without \"Storage\" permission.</string>