From c66e20a6edeaf33916c17ef5d06edca0df42ab00 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Thu, 6 Jun 2019 11:26:13 +0300 Subject: [PATCH] - New version 9.3.4. - Use communication mode only when call is (being) established. - Introduced 2.5 sec delay to placing of a call in order to avoid loss of audio at the beginning of call. - Fixed initializing default contacts when baresip is started the first time. - Clear call URI when call is closed. --- app/build.gradle | 4 +- .../com/tutpro/baresip/BaresipService.kt | 76 +++++++++++-------- .../com/tutpro/baresip/ContactActivity.kt | 2 +- .../com/tutpro/baresip/ContactListAdapter.kt | 2 +- .../com/tutpro/baresip/ContactsActivity.kt | 14 ++-- .../kotlin/com/tutpro/baresip/MainActivity.kt | 29 +++++-- .../android/en-US/changelogs/8.3.4,txt | 5 ++ 7 files changed, 84 insertions(+), 48 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/8.3.4,txt diff --git a/app/build.gradle b/app/build.gradle index 27b6113d..16016487 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId = 'com.tutpro.baresip' minSdkVersion 21 targetSdkVersion 28 - versionCode = 70 - versionName = '8.3.3' + versionCode = 71 + versionName = '8.3.4' externalNativeBuild { cmake { cFlags '-DHAVE_INTTYPES_H' diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 33550b04..8eea8ad5 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -53,9 +53,6 @@ class BaresipService: Service() { filesPath = filesDir.absolutePath am = getSystemService(Context.AUDIO_SERVICE) as AudioManager - // Setting this when call is established, causes on some devices 3-4 sec delay - // to hearing of audio - am.mode = AudioManager.MODE_IN_COMMUNICATION val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext, RingtoneManager.TYPE_RINGTONE) @@ -75,10 +72,12 @@ class BaresipService: Service() { Log.d(LOG_TAG, "Network '$network' is available") // This is followed by onLinkPropertiesChanged } + override fun onLost(network: Network) { super.onLost(network) Log.d(LOG_TAG, "Network '$network' is lost") } + override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { super.onLinkPropertiesChanged(network, linkProperties) Log.d(LOG_TAG, "Network $network link properties changed") @@ -154,7 +153,7 @@ class BaresipService: Service() { } } - ContactsActivity.restoreContacts(applicationContext.filesDir) + ContactsActivity.restoreContacts(applicationContext.filesDir, "contacts") Thread(Runnable { baresipStart(filesPath) }).start() isServiceRunning = true @@ -162,9 +161,6 @@ class BaresipService: Service() { if (Config.variable("dyn_dns")[0] == "yes") Config.remove("dns_server") - - Log.d(LOG_TAG, "AudioManager mode is ${am.mode}") - } "Call Show", "Call Answer" -> { @@ -236,8 +232,8 @@ class BaresipService: Service() { Log.w(LOG_TAG, "onStartCommand did not find UA $uap") else ChatsActivity.saveUaMessage(ua.account.aor, - intent.getStringExtra("time").toLong(), - applicationContext.filesDir.absolutePath) + intent.getStringExtra("time").toLong(), + applicationContext.filesDir.absolutePath) nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID) } @@ -345,7 +341,11 @@ class BaresipService: Service() { status[account_index] = R.drawable.dot_yellow updateStatusNotification() } - "call ringing" -> { + "call progress", "call ringing" -> { + if (!isAudioFocused()) { + requestAudioFocus(AudioManager.STREAM_VOICE_CALL) + setCallVolume() + } } "call incoming" -> { val peerUri = Api.call_peeruri(callp) @@ -356,7 +356,7 @@ class BaresipService: Service() { CallHistory.save(filesPath) ua.account.missedCalls = true if (!Utils.isVisible()) - return + return newEvent = "call rejected" } else { Log.d(LOG_TAG, "Incoming call $uap/$callp/$peerUri") @@ -416,15 +416,13 @@ class BaresipService: Service() { CallHistory.add(CallHistory(aor, call.peerURI, call.dir, true)) CallHistory.save(filesPath) call.hasHistory = true - if (call.dir == "in") stopRinging() - if (!isAudioFocused()) requestAudioFocus(AudioManager.STREAM_VOICE_CALL) - if (callVolume != 0) { - origCallVolume = am.getStreamVolume(am.mode) - am.setStreamVolume(am.mode, - (callVolume * 0.1 * am.getStreamMaxVolume(am.mode)).roundToInt(), - 0) - Log.d(LOG_TAG, "Original/new call volume of stream ${am.mode} is " + - "$origCallVolume/${am.getStreamVolume(am.mode)}") + if (call.dir == "in") { + stopRinging() + am.mode = AudioManager.MODE_IN_COMMUNICATION + } + if (!isAudioFocused()) { + requestAudioFocus(AudioManager.STREAM_VOICE_CALL) + setCallVolume() } } "call verified", "call secure" -> { @@ -450,8 +448,8 @@ class BaresipService: Service() { val intent = Intent(this, BaresipService::class.java) intent.action = "Transfer Show" intent.putExtra("uap", uap) - .putExtra("callp", callp) - .putExtra("uri", ev[1]) + .putExtra("callp", callp) + .putExtra("uri", ev[1]) val pi = PendingIntent.getService(this, TRANSFER_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) @@ -472,8 +470,8 @@ class BaresipService: Service() { val acceptIntent = Intent(this, BaresipService::class.java) acceptIntent.action = "Transfer Accept" acceptIntent.putExtra("uap", uap) - .putExtra("callp", callp) - .putExtra("uri", ev[1]) + .putExtra("callp", callp) + .putExtra("uri", ev[1]) val acceptPendingIntent = PendingIntent.getService(this, ACCEPT_REQ_CODE, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT) val denyIntent = Intent(this, BaresipService::class.java) @@ -506,11 +504,8 @@ class BaresipService: Service() { } if (Call.calls().size == 0) { abandonAudioFocus() - if (origCallVolume != -1) { - am.setStreamVolume(am.mode, origCallVolume, 0) - origCallVolume = -1 - } - Log.d(LOG_TAG, "Call volume of stream ${am.mode} is ${am.getStreamVolume(am.mode)}") + resetCallVolume() + am.mode = AudioManager.MODE_NORMAL if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false speakerPhone = false } @@ -711,7 +706,6 @@ class BaresipService: Service() { } private fun abandonAudioFocus() { - Log.d(LOG_TAG, "Abandonin audio focus") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (audioFocusRequest != null) { am.abandonAudioFocusRequest(audioFocusRequest!!) @@ -723,6 +717,8 @@ class BaresipService: Service() { audioFocused = false } } + if (isAudioFocused()) + Log.w(LOG_TAG, "Failed to abandon audio focus") } private fun startRinging() { @@ -755,7 +751,25 @@ class BaresipService: Service() { } } abandonAudioFocus() - am.mode = AudioManager.MODE_IN_COMMUNICATION + } + + private fun setCallVolume() { + if (callVolume != 0) { + origCallVolume = am.getStreamVolume(am.mode) + am.setStreamVolume(am.mode, + (callVolume * 0.1 * am.getStreamMaxVolume(am.mode)).roundToInt(), + 0) + Log.d(LOG_TAG, "Original/new call volume of stream ${am.mode} is " + + "$origCallVolume/${am.getStreamVolume(am.mode)}") + } + } + + private fun resetCallVolume() { + if (origCallVolume != -1) { + am.setStreamVolume(am.mode, origCallVolume, 0) + origCallVolume = -1 + } + Log.d(LOG_TAG, "Call volume of stream ${am.mode} is ${am.getStreamVolume(am.mode)}") } private fun cleanService() { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt index ac77495e..7579bba4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt @@ -98,7 +98,7 @@ class ContactActivity : AppCompatActivity() { } Contact.contacts().sortBy { Contact -> Contact.name } - ContactsActivity.saveContacts(applicationContext.filesDir) + ContactsActivity.saveContacts(applicationContext.filesDir, "contacts") i.putExtra("name", newName) setResult(Activity.RESULT_OK, i) diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt index bfd38fcd..6383e9ff 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt @@ -66,7 +66,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList { Contact.contacts().removeAt(pos) - ContactsActivity.saveContacts(cxt.applicationContext.filesDir) + ContactsActivity.saveContacts(cxt.applicationContext.filesDir, "contacts") this.notifyDataSetChanged() } DialogInterface.BUTTON_NEGATIVE -> { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt index b56164ee..0273a847 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactsActivity.kt @@ -57,7 +57,7 @@ class ContactsActivity : AppCompatActivity() { val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) when (item.itemId) { R.id.export_contacts -> { - if (saveContacts(dir)) + if (saveContacts(dir, "contacts.bs")) Utils.alertView(this, "", getString(R.string.exported_contacts)) else @@ -65,11 +65,11 @@ class ContactsActivity : AppCompatActivity() { getString(R.string.export_error)) } R.id.import_contacts -> { - if (restoreContacts(dir)) { + if (restoreContacts(dir, "contacts.bs")) { Utils.alertView(this, "", getString(R.string.imported_contacts)) clAdapter.notifyDataSetChanged() - saveContacts(applicationContext.filesDir) + saveContacts(applicationContext.filesDir, "contacts") } else Utils.alertView(this,getString(R.string.error), getString(R.string.import_error)) @@ -93,15 +93,15 @@ class ContactsActivity : AppCompatActivity() { companion object { - fun saveContacts(path: File): Boolean { + fun saveContacts(path: File, file: String): Boolean { var contents = "" for (c in Contact.contacts()) contents += "\"${c.name}\" ${c.uri}\n" - return Utils.putFileContents(File(path, "contacts.bs"), contents) + return Utils.putFileContents(File(path, file), contents) } - fun restoreContacts(path: File): Boolean { - val content = Utils.getFileContents(File(path, "contacts.bs")) + fun restoreContacts(path: File, file: String): Boolean { + val content = Utils.getFileContents(File(path, file)) if (content == "Failed") return false Api.contacts_remove() Contact.contacts().clear() diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index c0e80d53..2a4d7053 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -13,6 +13,7 @@ import android.content.pm.PackageManager import android.media.AudioManager import android.os.Build import android.os.CountDownTimer +import android.os.Handler import android.support.v4.content.LocalBroadcastManager import android.view.inputmethod.InputMethodManager import android.text.InputType @@ -257,11 +258,25 @@ class MainActivity : AppCompatActivity() { uri = "$uri@$host" } } - if (!Utils.checkSipUri(uri)) + if (!Utils.checkSipUri(uri)) { Utils.alertView(this, getString(R.string.notice), "${getString(R.string.invalid_sip_uri)} '$uri'") - else - call(ua, uri, "outgoing") + } else { + // Set audio mode to MODE_IN_COMMUNICATION and wait 2.5 sec before + // placing to call in order to avoid missing audio from callee due to + // a bug in many Android devices. + val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager + am.mode = AudioManager.MODE_IN_COMMUNICATION + callButton.visibility = View.INVISIBLE + hangupButton.visibility = View.VISIBLE + Handler().postDelayed({ + if (!call(ua, uri, "outgoing")) { + am.mode = AudioManager.MODE_NORMAL + callButton.visibility = View.VISIBLE + hangupButton.visibility = View.INVISIBLE + } + }, 2500) + } } else { val latest = CallHistory.aorLatestHistory(aor) if (latest != null) @@ -976,12 +991,12 @@ class MainActivity : AppCompatActivity() { } } - private fun call(ua: UserAgent, uri: String, status: String) { + private fun call(ua: UserAgent, uri: String, status: String): Boolean { if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) { Toast.makeText(applicationContext, getString(R.string.no_microphone_permission), Toast.LENGTH_SHORT).show() - return + return false } if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition]) spinToAor(ua.account.aor) @@ -990,9 +1005,10 @@ class MainActivity : AppCompatActivity() { Log.d("Baresip", "Adding outgoing call ${ua.uap}/$callp/$uri") Call.calls().add(Call(callp, ua, uri, "out", status, Utils.dtmfWatcher(callp))) showCall(ua) + return true } else { Log.e("Baresip", "ua_connect ${ua.uap}/$uri failed") - callButton.visibility = View.VISIBLE + return false } } @@ -1040,6 +1056,7 @@ class MainActivity : AppCompatActivity() { private fun showCall(ua: UserAgent) { if (Call.uaCalls(ua, "").size == 0) { callTitle.text = getString(R.string.outgoing_call_to_dots) + callUri.text.clear() callUri.hint = getString(R.string.callee) callUri.isFocusable = true callUri.isFocusableInTouchMode = true diff --git a/fastlane/metadata/android/en-US/changelogs/8.3.4,txt b/fastlane/metadata/android/en-US/changelogs/8.3.4,txt new file mode 100644 index 00000000..d1b476c1 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/8.3.4,txt @@ -0,0 +1,5 @@ +- Use communication mode only when call is (being) established. +- Introduced 2.5 sec delay to placing of a call in order to avoid loss of + audio at the beginning of call. +- Fixed initializing default contacts when baresip is started the first time. +- Clear call URI when call is closed.