- 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.
This commit is contained in:
Juha Heinanen
2019-06-06 11:26:13 +03:00
parent 66fce98c9c
commit c66e20a6ed
7 changed files with 84 additions and 48 deletions
+2 -2
View File
@@ -8,8 +8,8 @@ android {
applicationId = 'com.tutpro.baresip' applicationId = 'com.tutpro.baresip'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 28
versionCode = 70 versionCode = 71
versionName = '8.3.3' versionName = '8.3.4'
externalNativeBuild { externalNativeBuild {
cmake { cmake {
cFlags '-DHAVE_INTTYPES_H' cFlags '-DHAVE_INTTYPES_H'
@@ -53,9 +53,6 @@ class BaresipService: Service() {
filesPath = filesDir.absolutePath filesPath = filesDir.absolutePath
am = getSystemService(Context.AUDIO_SERVICE) as AudioManager 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, val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext,
RingtoneManager.TYPE_RINGTONE) RingtoneManager.TYPE_RINGTONE)
@@ -75,10 +72,12 @@ class BaresipService: Service() {
Log.d(LOG_TAG, "Network '$network' is available") Log.d(LOG_TAG, "Network '$network' is available")
// This is followed by onLinkPropertiesChanged // This is followed by onLinkPropertiesChanged
} }
override fun onLost(network: Network) { override fun onLost(network: Network) {
super.onLost(network) super.onLost(network)
Log.d(LOG_TAG, "Network '$network' is lost") Log.d(LOG_TAG, "Network '$network' is lost")
} }
override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
super.onLinkPropertiesChanged(network, linkProperties) super.onLinkPropertiesChanged(network, linkProperties)
Log.d(LOG_TAG, "Network $network link properties changed") 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() Thread(Runnable { baresipStart(filesPath) }).start()
isServiceRunning = true isServiceRunning = true
@@ -162,9 +161,6 @@ class BaresipService: Service() {
if (Config.variable("dyn_dns")[0] == "yes") if (Config.variable("dyn_dns")[0] == "yes")
Config.remove("dns_server") Config.remove("dns_server")
Log.d(LOG_TAG, "AudioManager mode is ${am.mode}")
} }
"Call Show", "Call Answer" -> { "Call Show", "Call Answer" -> {
@@ -345,7 +341,11 @@ class BaresipService: Service() {
status[account_index] = R.drawable.dot_yellow status[account_index] = R.drawable.dot_yellow
updateStatusNotification() updateStatusNotification()
} }
"call ringing" -> { "call progress", "call ringing" -> {
if (!isAudioFocused()) {
requestAudioFocus(AudioManager.STREAM_VOICE_CALL)
setCallVolume()
}
} }
"call incoming" -> { "call incoming" -> {
val peerUri = Api.call_peeruri(callp) val peerUri = Api.call_peeruri(callp)
@@ -416,15 +416,13 @@ class BaresipService: Service() {
CallHistory.add(CallHistory(aor, call.peerURI, call.dir, true)) CallHistory.add(CallHistory(aor, call.peerURI, call.dir, true))
CallHistory.save(filesPath) CallHistory.save(filesPath)
call.hasHistory = true call.hasHistory = true
if (call.dir == "in") stopRinging() if (call.dir == "in") {
if (!isAudioFocused()) requestAudioFocus(AudioManager.STREAM_VOICE_CALL) stopRinging()
if (callVolume != 0) { am.mode = AudioManager.MODE_IN_COMMUNICATION
origCallVolume = am.getStreamVolume(am.mode) }
am.setStreamVolume(am.mode, if (!isAudioFocused()) {
(callVolume * 0.1 * am.getStreamMaxVolume(am.mode)).roundToInt(), requestAudioFocus(AudioManager.STREAM_VOICE_CALL)
0) setCallVolume()
Log.d(LOG_TAG, "Original/new call volume of stream ${am.mode} is " +
"$origCallVolume/${am.getStreamVolume(am.mode)}")
} }
} }
"call verified", "call secure" -> { "call verified", "call secure" -> {
@@ -506,11 +504,8 @@ class BaresipService: Service() {
} }
if (Call.calls().size == 0) { if (Call.calls().size == 0) {
abandonAudioFocus() abandonAudioFocus()
if (origCallVolume != -1) { resetCallVolume()
am.setStreamVolume(am.mode, origCallVolume, 0) am.mode = AudioManager.MODE_NORMAL
origCallVolume = -1
}
Log.d(LOG_TAG, "Call volume of stream ${am.mode} is ${am.getStreamVolume(am.mode)}")
if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false
speakerPhone = false speakerPhone = false
} }
@@ -711,7 +706,6 @@ class BaresipService: Service() {
} }
private fun abandonAudioFocus() { private fun abandonAudioFocus() {
Log.d(LOG_TAG, "Abandonin audio focus")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (audioFocusRequest != null) { if (audioFocusRequest != null) {
am.abandonAudioFocusRequest(audioFocusRequest!!) am.abandonAudioFocusRequest(audioFocusRequest!!)
@@ -723,6 +717,8 @@ class BaresipService: Service() {
audioFocused = false audioFocused = false
} }
} }
if (isAudioFocused())
Log.w(LOG_TAG, "Failed to abandon audio focus")
} }
private fun startRinging() { private fun startRinging() {
@@ -755,7 +751,25 @@ class BaresipService: Service() {
} }
} }
abandonAudioFocus() 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() { private fun cleanService() {
@@ -98,7 +98,7 @@ class ContactActivity : AppCompatActivity() {
} }
Contact.contacts().sortBy { Contact -> Contact.name } Contact.contacts().sortBy { Contact -> Contact.name }
ContactsActivity.saveContacts(applicationContext.filesDir) ContactsActivity.saveContacts(applicationContext.filesDir, "contacts")
i.putExtra("name", newName) i.putExtra("name", newName)
setResult(Activity.RESULT_OK, i) setResult(Activity.RESULT_OK, i)
@@ -66,7 +66,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
when (which) { when (which) {
DialogInterface.BUTTON_POSITIVE -> { DialogInterface.BUTTON_POSITIVE -> {
Contact.contacts().removeAt(pos) Contact.contacts().removeAt(pos)
ContactsActivity.saveContacts(cxt.applicationContext.filesDir) ContactsActivity.saveContacts(cxt.applicationContext.filesDir, "contacts")
this.notifyDataSetChanged() this.notifyDataSetChanged()
} }
DialogInterface.BUTTON_NEGATIVE -> { DialogInterface.BUTTON_NEGATIVE -> {
@@ -57,7 +57,7 @@ class ContactsActivity : AppCompatActivity() {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
when (item.itemId) { when (item.itemId) {
R.id.export_contacts -> { R.id.export_contacts -> {
if (saveContacts(dir)) if (saveContacts(dir, "contacts.bs"))
Utils.alertView(this, "", Utils.alertView(this, "",
getString(R.string.exported_contacts)) getString(R.string.exported_contacts))
else else
@@ -65,11 +65,11 @@ class ContactsActivity : AppCompatActivity() {
getString(R.string.export_error)) getString(R.string.export_error))
} }
R.id.import_contacts -> { R.id.import_contacts -> {
if (restoreContacts(dir)) { if (restoreContacts(dir, "contacts.bs")) {
Utils.alertView(this, "", Utils.alertView(this, "",
getString(R.string.imported_contacts)) getString(R.string.imported_contacts))
clAdapter.notifyDataSetChanged() clAdapter.notifyDataSetChanged()
saveContacts(applicationContext.filesDir) saveContacts(applicationContext.filesDir, "contacts")
} else } else
Utils.alertView(this,getString(R.string.error), Utils.alertView(this,getString(R.string.error),
getString(R.string.import_error)) getString(R.string.import_error))
@@ -93,15 +93,15 @@ class ContactsActivity : AppCompatActivity() {
companion object { companion object {
fun saveContacts(path: File): Boolean { fun saveContacts(path: File, file: String): Boolean {
var contents = "" var contents = ""
for (c in Contact.contacts()) for (c in Contact.contacts())
contents += "\"${c.name}\" ${c.uri}\n" 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 { fun restoreContacts(path: File, file: String): Boolean {
val content = Utils.getFileContents(File(path, "contacts.bs")) val content = Utils.getFileContents(File(path, file))
if (content == "Failed") return false if (content == "Failed") return false
Api.contacts_remove() Api.contacts_remove()
Contact.contacts().clear() Contact.contacts().clear()
@@ -13,6 +13,7 @@ import android.content.pm.PackageManager
import android.media.AudioManager import android.media.AudioManager
import android.os.Build import android.os.Build
import android.os.CountDownTimer import android.os.CountDownTimer
import android.os.Handler
import android.support.v4.content.LocalBroadcastManager import android.support.v4.content.LocalBroadcastManager
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.text.InputType import android.text.InputType
@@ -257,11 +258,25 @@ class MainActivity : AppCompatActivity() {
uri = "$uri@$host" uri = "$uri@$host"
} }
} }
if (!Utils.checkSipUri(uri)) if (!Utils.checkSipUri(uri)) {
Utils.alertView(this, getString(R.string.notice), Utils.alertView(this, getString(R.string.notice),
"${getString(R.string.invalid_sip_uri)} '$uri'") "${getString(R.string.invalid_sip_uri)} '$uri'")
else } else {
call(ua, uri, "outgoing") // 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 { } else {
val latest = CallHistory.aorLatestHistory(aor) val latest = CallHistory.aorLatestHistory(aor)
if (latest != null) 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) if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_DENIED) { == PackageManager.PERMISSION_DENIED) {
Toast.makeText(applicationContext, Toast.makeText(applicationContext,
getString(R.string.no_microphone_permission), Toast.LENGTH_SHORT).show() getString(R.string.no_microphone_permission), Toast.LENGTH_SHORT).show()
return return false
} }
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition]) if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(ua.account.aor) spinToAor(ua.account.aor)
@@ -990,9 +1005,10 @@ class MainActivity : AppCompatActivity() {
Log.d("Baresip", "Adding outgoing call ${ua.uap}/$callp/$uri") Log.d("Baresip", "Adding outgoing call ${ua.uap}/$callp/$uri")
Call.calls().add(Call(callp, ua, uri, "out", status, Utils.dtmfWatcher(callp))) Call.calls().add(Call(callp, ua, uri, "out", status, Utils.dtmfWatcher(callp)))
showCall(ua) showCall(ua)
return true
} else { } else {
Log.e("Baresip", "ua_connect ${ua.uap}/$uri failed") 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) { private fun showCall(ua: UserAgent) {
if (Call.uaCalls(ua, "").size == 0) { if (Call.uaCalls(ua, "").size == 0) {
callTitle.text = getString(R.string.outgoing_call_to_dots) callTitle.text = getString(R.string.outgoing_call_to_dots)
callUri.text.clear()
callUri.hint = getString(R.string.callee) callUri.hint = getString(R.string.callee)
callUri.isFocusable = true callUri.isFocusable = true
callUri.isFocusableInTouchMode = true callUri.isFocusableInTouchMode = true
@@ -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.