- Upgraded target Android API level to 28 (Android 9)

- Moved some non-UI functionality from main activity to baresip service
- Simplified implementation of call transfer
- Modified baresip launcher and status bar images
This commit is contained in:
Juha Heinanen
2019-04-08 18:47:59 +03:00
parent eb4cfbcece
commit cf5680b52b
19 changed files with 409 additions and 298 deletions
+8 -9
View File
@@ -1,14 +1,15 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android { android {
compileSdkVersion = 27 compileSdkVersion = 28
defaultConfig { defaultConfig {
applicationId = 'com.tutpro.baresip' applicationId = 'com.tutpro.baresip'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 27 targetSdkVersion 28
versionCode = 49 versionCode = 50
versionName = '6.1.0' versionName = '6.2.0'
externalNativeBuild { externalNativeBuild {
cmake { cmake {
cFlags '-DHAVE_INTTYPES_H' cFlags '-DHAVE_INTTYPES_H'
@@ -27,7 +28,7 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro' 'proguard-rules.pro'
} }
} }
@@ -43,14 +44,12 @@ android {
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:design:28.0.0'
} }
repositories { repositories {
mavenCentral() mavenCentral()
} }
apply plugin: 'kotlin-android-extensions'
+3 -1
View File
@@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tutpro.baresip"> package="com.tutpro.baresip">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
@@ -95,6 +96,7 @@
<service <service
android:name=".BaresipService" android:name=".BaresipService"
android:permission="android.permission.FOREGROUND_SERVICE"
android:enabled="true" > android:enabled="true" >
</service> </service>
@@ -102,7 +104,7 @@
android:name=".RunOnStartup" android:name=".RunOnStartup"
android:enabled="true" android:enabled="true"
android:exported="true" android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.tutpro.baresip.Restart" /> <action android:name="com.tutpro.baresip.Restart" />
-1
View File
@@ -977,7 +977,6 @@ Java_com_tutpro_baresip_Api_uag_1current_1set(JNIEnv *env, jobject thiz, jstring
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua); (*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
LOGD("running uag_current_set on %s\n", native_ua); LOGD("running uag_current_set on %s\n", native_ua);
uag_current_set(ua); uag_current_set(ua);
return;
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
@@ -41,8 +41,9 @@ class AccountListAdapter(private val cxt: Context, private val rows: ArrayList<A
val deleteDialog = AlertDialog.Builder(cxt) val deleteDialog = AlertDialog.Builder(cxt)
deleteDialog.setMessage("Do you want to delete account ${ua.account.aor}?") deleteDialog.setMessage("Do you want to delete account ${ua.account.aor}?")
deleteDialog.setPositiveButton("Delete") { dialog, _ -> deleteDialog.setPositiveButton("Delete") { dialog, _ ->
if (Api.ua_isregistered(ua.uap)) Api.ua_unregister(ua.uap) if (Api.ua_isregistered(ua.uap))
Api.ua_destroy(ua.uap) Api.ua_unregister(ua.uap)
// Api.ua_destroy(ua.uap)
UserAgent.remove(ua) UserAgent.remove(ua)
AccountsActivity.generateAccounts() AccountsActivity.generateAccounts()
AccountsActivity.saveAccounts() AccountsActivity.saveAccounts()
@@ -101,7 +101,8 @@ class BaresipService: Service() {
action = "Start" action = "Start"
Log.d(LOG_TAG, "Received onStartCommand with null intent") Log.d(LOG_TAG, "Received onStartCommand with null intent")
} else { } else {
action = intent.getAction() // Utils.dumpIntent(intent)
action = intent.action!!
Log.d(LOG_TAG, "Received onStartCommand action $action") Log.d(LOG_TAG, "Received onStartCommand action $action")
} }
@@ -162,6 +163,92 @@ class BaresipService: Service() {
showStatusNotification() showStatusNotification()
} }
"Call Show", "Call Answer" -> {
val newIntent = Intent(this, MainActivity::class.java)
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
newIntent.putExtra("action", action.toLowerCase())
newIntent.putExtra("callp", intent!!.getStringExtra("callp"))
startActivity(newIntent)
}
"Call Reject" -> {
val callp = intent!!.getStringExtra("callp")
val call = Call.find(callp)
if (call == null) {
Log.w(LOG_TAG, "onStartCommand did not find call $callp")
} else {
val peerUri = call.peerURI
val aor = call.ua.account.aor
Log.i(LOG_TAG, "Aor $aor rejected incoming call $callp from $peerUri")
Api.ua_hangup(call.ua.uap, callp, 486, "Rejected")
CallHistory.add(CallHistory(aor, peerUri, "in", false))
CallHistory.save(filesPath)
}
}
"Transfer Show", "Transfer Accept" -> {
val uap = intent!!.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.w(LOG_TAG, "onStartCommand did not find ua $uap")
} else {
val newIntent = Intent(this, MainActivity::class.java)
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
newIntent.putExtra("action", action.toLowerCase())
newIntent.putExtra("callp", intent.getStringExtra("callp"))
newIntent.putExtra("uri", intent.getStringExtra("uri"))
startActivity(newIntent)
nm.cancel(BaresipService.TRANSFER_NOTIFICATION_ID)
}
}
"Transfer Deny" -> {
val callp = intent!!.getStringExtra("callp")
val call = Call.find(callp)
if (call == null)
Log.w(LOG_TAG, "onStartCommand did not find call $callp")
else
Api.call_notify_sipfrag(callp, 603, "Decline")
nm.cancel(BaresipService.TRANSFER_NOTIFICATION_ID)
}
"Message Show", "Message Reply" -> {
val newIntent = Intent(this, MainActivity::class.java)
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
newIntent.putExtra("action", action.toLowerCase())
newIntent.putExtra("uap", intent!!.getStringExtra("uap"))
newIntent.putExtra("time", intent.getStringExtra("time"))
startActivity(newIntent)
nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID)
}
"Message Save" -> {
val uap = intent!!.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null)
Log.w(LOG_TAG, "onStartCommand did not find UA $uap")
else
ChatsActivity.saveUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong(),
applicationContext.filesDir.absolutePath)
nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID)
}
"Message Delete" -> {
val uap = intent!!.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null)
Log.w(LOG_TAG, "onStartCommand did not find UA $uap")
else
ChatsActivity.deleteUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong(),
applicationContext.filesDir.absolutePath)
nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID)
}
"UpdateNotification" -> { "UpdateNotification" -> {
updateStatusNotification() updateStatusNotification()
} }
@@ -243,14 +330,20 @@ class BaresipService: Service() {
else else
status[account_index] = R.drawable.dot_green status[account_index] = R.drawable.dot_green
updateStatusNotification() updateStatusNotification()
if (!Utils.isVisible())
return
} }
"registering failed" -> { "registering failed" -> {
status[account_index] = R.drawable.dot_red status[account_index] = R.drawable.dot_red
updateStatusNotification() updateStatusNotification()
if (!Utils.isVisible())
return
} }
"unregistering" -> { "unregistering" -> {
status[account_index] = R.drawable.dot_yellow status[account_index] = R.drawable.dot_yellow
updateStatusNotification() updateStatusNotification()
if (!Utils.isVisible())
return
} }
"call incoming" -> { "call incoming" -> {
val peerUri = Api.call_peeruri(callp) val peerUri = Api.call_peeruri(callp)
@@ -260,6 +353,8 @@ class BaresipService: Service() {
CallHistory.add(CallHistory(aor, peerUri, "in", false)) CallHistory.add(CallHistory(aor, peerUri, "in", false))
CallHistory.save(filesPath) CallHistory.save(filesPath)
ua.account.missedCalls = true ua.account.missedCalls = true
if (!Utils.isVisible())
return
newEvent = "call rejected" newEvent = "call rejected"
} else { } else {
Log.d(LOG_TAG, "Incoming call $uap/$callp/$peerUri") Log.d(LOG_TAG, "Incoming call $uap/$callp/$peerUri")
@@ -267,44 +362,41 @@ class BaresipService: Service() {
Utils.dtmfWatcher(callp))) Utils.dtmfWatcher(callp)))
startRinging() startRinging()
} }
if ((newEvent == null) && !Utils.isVisible()) { if (!Utils.isVisible()) {
val intent = Intent(this, MainActivity::class.java) val intent = Intent(this, BaresipService::class.java)
.setAction(Intent.ACTION_MAIN) intent.action = "Call Show"
.addCategory(Intent.CATEGORY_LAUNCHER) intent.putExtra("callp", callp)
val pi = PendingIntent.getActivity(this, CALL_REQ_CODE, intent, val pi = PendingIntent.getService(this, CALL_REQ_CODE, intent,
0) PendingIntent.FLAG_UPDATE_CURRENT)
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
val caller = Utils.friendlyUri(ContactsActivity.contactName(peerUri), val caller = Utils.friendlyUri(ContactsActivity.contactName(peerUri),
Utils.aorDomain(aor)) Utils.aorDomain(aor))
val title = "Incoming call from $caller"
nb.setSmallIcon(R.drawable.ic_stat) nb.setSmallIcon(R.drawable.ic_stat)
.setColor(ContextCompat.getColor(this, .setColor(ContextCompat.getColor(this,
R.color.colorBaresip)) R.color.colorBaresip))
.setContentIntent(pi) .setContentIntent(pi)
.setAutoCancel(true) .setAutoCancel(true)
.setContentTitle(title) .setContentTitle("Incoming call from")
.setContentText(caller)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
nb.setVibrate(LongArray(0)) nb.setVibrate(LongArray(0))
.setVisibility(VISIBILITY_PRIVATE) .setVisibility(VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH) .setPriority(Notification.PRIORITY_HIGH)
} }
val answerIntent = Intent(this, MainActivity::class.java) val answerIntent = Intent(this, BaresipService::class.java)
answerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or answerIntent.action = "Call Answer"
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
answerIntent.putExtra("action", "answer")
answerIntent.putExtra("callp", callp) answerIntent.putExtra("callp", callp)
val answerPendingIntent = PendingIntent.getActivity(this, val answerPendingIntent = PendingIntent.getService(this,
ANSWER_REQ_CODE, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT) ANSWER_REQ_CODE, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val rejectIntent = Intent(this, MainActivity::class.java) val rejectIntent = Intent(this, BaresipService::class.java)
rejectIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or rejectIntent.action = "Call Reject"
Intent.FLAG_ACTIVITY_SINGLE_TOP)
rejectIntent.putExtra("action", "reject")
rejectIntent.putExtra("callp", callp) rejectIntent.putExtra("callp", callp)
val rejectPendingIntent = PendingIntent.getActivity(this, val rejectPendingIntent = PendingIntent.getService(this,
REJECT_REQ_CODE, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT) REJECT_REQ_CODE, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT)
nb.addAction(R.drawable.ic_stat, "Answer", answerPendingIntent) nb.addAction(R.drawable.ic_stat, "Answer", answerPendingIntent)
nb.addAction(R.drawable.ic_stat, "Reject", rejectPendingIntent) nb.addAction(R.drawable.ic_stat, "Reject", rejectPendingIntent)
nm.notify(CALL_NOTIFICATION_ID, nb.build()) nm.notify(CALL_NOTIFICATION_ID, nb.build())
return
} }
} }
"call established" -> { "call established" -> {
@@ -324,54 +416,68 @@ class BaresipService: Service() {
am.mode = AudioManager.MODE_IN_COMMUNICATION am.mode = AudioManager.MODE_IN_COMMUNICATION
requestAudioFocus(AudioManager.STREAM_VOICE_CALL) requestAudioFocus(AudioManager.STREAM_VOICE_CALL)
am.isSpeakerphoneOn = false am.isSpeakerphoneOn = false
if (!Utils.isVisible())
return
}
"call verified", "call secure" -> {
val call = Call.find(callp)
if (call == null) {
Log.e("Baresip", "Call $callp that is verified is not found")
return
}
if (ev[0] == "call secure") {
call.security = R.drawable.box_yellow
} else {
call.security = R.drawable.box_green
call.zid = ev[1]
}
if (!Utils.isVisible())
return
} }
"call transfer" -> { "call transfer" -> {
val call = Call.find(callp) val call = Call.find(callp)
if (call == null) { if (call == null) {
Log.d(LOG_TAG, "AoR $aor call $callp to be transferred is not found") Log.w(LOG_TAG, "Call $callp to be transferred is not found")
return return
} }
if (!Utils.isVisible()) { if (!Utils.isVisible()) {
val intent = Intent(this, MainActivity::class.java) val intent = Intent(this, BaresipService::class.java)
.setAction(Intent.ACTION_MAIN) intent.action = "Transfer Show"
.addCategory(Intent.CATEGORY_LAUNCHER) intent.putExtra("uap", uap)
val pi = PendingIntent.getActivity(this, TRANSFER_REQ_CODE, .putExtra("callp", callp)
intent, 0) .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) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]), val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
Utils.aorDomain(aor)) Utils.aorDomain(aor))
val title = "Call transfer request to $target"
nb.setSmallIcon(R.drawable.ic_stat) nb.setSmallIcon(R.drawable.ic_stat)
.setColor(ContextCompat.getColor(this, .setColor(ContextCompat.getColor(this, R.color.colorBaresip))
R.color.colorBaresip))
.setContentIntent(pi) .setContentIntent(pi)
.setDefaults(Notification.DEFAULT_SOUND) .setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true) .setAutoCancel(true)
.setContentTitle(title) .setContentTitle("Call transfer request to")
.setContentText(target)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
nb.setVibrate(LongArray(0)) nb.setVibrate(LongArray(0))
.setVisibility(VISIBILITY_PRIVATE) .setVisibility(VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH) .setPriority(Notification.PRIORITY_HIGH)
} }
val acceptIntent = Intent(this, MainActivity::class.java) val acceptIntent = Intent(this, BaresipService::class.java)
acceptIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or acceptIntent.action = "Transfer Accept"
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
acceptIntent.putExtra("action", "transfer")
acceptIntent.putExtra("uap", uap) acceptIntent.putExtra("uap", uap)
acceptIntent.putExtra("callp", callp) .putExtra("callp", callp)
acceptIntent.putExtra("uri", ev[1]) .putExtra("uri", ev[1])
val acceptPendingIntent = PendingIntent.getActivity(this, val acceptPendingIntent = PendingIntent.getService(this,
ACCEPT_REQ_CODE, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT) ACCEPT_REQ_CODE, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val denyIntent = Intent(this, MainActivity::class.java) val denyIntent = Intent(this, BaresipService::class.java)
denyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or denyIntent.action = "Transfer Deny"
Intent.FLAG_ACTIVITY_SINGLE_TOP)
denyIntent.putExtra("action", "deny")
denyIntent.putExtra("callp", callp) denyIntent.putExtra("callp", callp)
val denyPendingIntent = PendingIntent.getActivity(this, val denyPendingIntent = PendingIntent.getService(this,
DENY_REQ_CODE, denyIntent, PendingIntent.FLAG_UPDATE_CURRENT) DENY_REQ_CODE, denyIntent, PendingIntent.FLAG_UPDATE_CURRENT)
nb.addAction(R.drawable.ic_stat, "Accept", acceptPendingIntent) nb.addAction(R.drawable.ic_stat, "Accept", acceptPendingIntent)
nb.addAction(R.drawable.ic_stat, "Deny", denyPendingIntent) nb.addAction(R.drawable.ic_stat, "Deny", denyPendingIntent)
nm.notify(CALL_NOTIFICATION_ID, nb.build()) nm.notify(TRANSFER_NOTIFICATION_ID, nb.build())
return return
} }
} }
@@ -395,6 +501,12 @@ class BaresipService: Service() {
if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false
if (audioFocused) abandonAudioFocus() if (audioFocused) abandonAudioFocus()
} }
if (speakerPhone) {
am.isSpeakerphoneOn = !am.isSpeakerphoneOn
speakerPhone = am.isSpeakerphoneOn
}
if (!Utils.isVisible())
return
} }
"transfer failed" -> { "transfer failed" -> {
Log.d(LOG_TAG, "AoR $aor hanging up call $callp with ${ev[1]}") Log.d(LOG_TAG, "AoR $aor hanging up call $callp with ${ev[1]}")
@@ -406,6 +518,8 @@ class BaresipService: Service() {
} }
if (newEvent == null) newEvent = event if (newEvent == null) newEvent = event
val intent = Intent("service event") val intent = Intent("service event")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("event", newEvent) intent.putExtra("event", newEvent)
intent.putExtra("params", arrayListOf(uap, callp)) intent.putExtra("params", arrayListOf(uap, callp))
LocalBroadcastManager.getInstance(this).sendBroadcast(intent) LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
@@ -413,9 +527,9 @@ class BaresipService: Service() {
@Keep @Keep
fun messageEvent(uap: String, peer: String, msg: ByteArray) { fun messageEvent(uap: String, peer: String, msg: ByteArray) {
var s = "Decoding of message failed!" var text = "Decoding of message failed!"
try { try {
s = String(msg, StandardCharsets.UTF_8) text = String(msg, StandardCharsets.UTF_8)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(LOG_TAG, "UTF-8 decode failed") Log.e(LOG_TAG, "UTF-8 decode failed")
} }
@@ -426,14 +540,15 @@ class BaresipService: Service() {
return return
} }
val timeStamp = System.currentTimeMillis().toString() val timeStamp = System.currentTimeMillis().toString()
Message.add(Message(ua.account.aor, peer, text, timeStamp.toLong(),
R.drawable.arrow_down_green, 0, "", true))
if (!Utils.isVisible()) { if (!Utils.isVisible()) {
val intent = Intent(this, MainActivity::class.java) val intent = Intent(this, BaresipService::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or intent.action = "Message Show"
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) intent.putExtra("uap", uap)
.putExtra("action", "show") .putExtra("time", timeStamp)
.putExtra("uap", uap) val pi = PendingIntent.getService(this, MESSAGE_REQ_CODE, intent,
.putExtra("peer", peer) PendingIntent.FLAG_UPDATE_CURRENT)
val pi = PendingIntent.getActivity(this, MESSAGE_REQ_CODE, intent, 0)
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
val sender = Utils.friendlyUri(ContactsActivity.contactName(peer), val sender = Utils.friendlyUri(ContactsActivity.contactName(peer),
Utils.aorDomain(ua.account.aor)) Utils.aorDomain(ua.account.aor))
@@ -443,44 +558,41 @@ class BaresipService: Service() {
.setDefaults(Notification.DEFAULT_SOUND) .setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true) .setAutoCancel(true)
.setContentTitle("Message from $sender") .setContentTitle("Message from $sender")
.setContentText(s) .setContentText(text)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
nb.setVibrate(LongArray(0)) nb.setVibrate(LongArray(0))
.setVisibility(VISIBILITY_PRIVATE) .setVisibility(VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH) .setPriority(Notification.PRIORITY_HIGH)
} }
val replyIntent = Intent(this, MainActivity::class.java) val replyIntent = Intent(this, BaresipService::class.java)
replyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or replyIntent.action = "Message Reply"
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
replyIntent.putExtra("action", "reply")
replyIntent.putExtra("uap", uap) replyIntent.putExtra("uap", uap)
replyIntent.putExtra("peer", peer) .putExtra("time", timeStamp)
val replyPendingIntent = PendingIntent.getActivity(this, val replyPendingIntent = PendingIntent.getService(this,
REPLY_REQ_CODE, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) REPLY_REQ_CODE, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val saveIntent = Intent(this, MainActivity::class.java) val saveIntent = Intent(this, BaresipService::class.java)
saveIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or saveIntent.action = "Message Save"
Intent.FLAG_ACTIVITY_SINGLE_TOP)
saveIntent.putExtra("action", "save")
saveIntent.putExtra("uap", uap) saveIntent.putExtra("uap", uap)
saveIntent.putExtra("time", timeStamp) .putExtra("time", timeStamp)
val savePendingIntent = PendingIntent.getActivity(this, val savePendingIntent = PendingIntent.getService(this,
SAVE_REQ_CODE, saveIntent, PendingIntent.FLAG_UPDATE_CURRENT) SAVE_REQ_CODE, saveIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val deleteIntent = Intent(this, MainActivity::class.java) val deleteIntent = Intent(this, BaresipService::class.java)
deleteIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or deleteIntent.action = "Message Delete"
Intent.FLAG_ACTIVITY_SINGLE_TOP)
deleteIntent.putExtra("action", "delete")
deleteIntent.putExtra("uap", uap) deleteIntent.putExtra("uap", uap)
deleteIntent.putExtra("time", timeStamp) .putExtra("time", timeStamp)
val deletePendingIntent = PendingIntent.getActivity(this, val deletePendingIntent = PendingIntent.getService(this,
DELETE_REQ_CODE, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT) DELETE_REQ_CODE, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
nb.addAction(R.drawable.ic_stat, "Reply", replyPendingIntent) nb.addAction(R.drawable.ic_stat, "Reply", replyPendingIntent)
nb.addAction(R.drawable.ic_stat, "Save", savePendingIntent) nb.addAction(R.drawable.ic_stat, "Save", savePendingIntent)
nb.addAction(R.drawable.ic_stat, "Delete", deletePendingIntent) nb.addAction(R.drawable.ic_stat, "Delete", deletePendingIntent)
nm.notify(MESSAGE_NOTIFICATION_ID, nb.build()) nm.notify(MESSAGE_NOTIFICATION_ID, nb.build())
return
} }
val intent = Intent("service event") val intent = Intent("service event")
intent.putExtra("event", "message") intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
intent.putExtra("params", arrayListOf(uap, peer, s, timeStamp)) Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("event", "message show")
intent.putExtra("params", arrayListOf(uap, timeStamp))
LocalBroadcastManager.getInstance(this).sendBroadcast(intent) LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
} }
@@ -645,7 +757,8 @@ class BaresipService: Service() {
val STATUS_NOTIFICATION_ID = 101 val STATUS_NOTIFICATION_ID = 101
val CALL_NOTIFICATION_ID = 102 val CALL_NOTIFICATION_ID = 102
val MESSAGE_NOTIFICATION_ID = 103 val TRANSFER_NOTIFICATION_ID = 103
val MESSAGE_NOTIFICATION_ID = 104
val STATUS_REQ_CODE = 1 val STATUS_REQ_CODE = 1
val CALL_REQ_CODE = 2 val CALL_REQ_CODE = 2
@@ -1,6 +1,7 @@
package com.tutpro.baresip package com.tutpro.baresip
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import java.util.ArrayList import java.util.ArrayList
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,
@@ -49,6 +50,5 @@ class Call(val callp: String, val ua: UserAgent, val peerURI: String, val dir: S
if (c.callp == callp) return c if (c.callp == callp) return c
return null return null
} }
} }
} }
@@ -219,12 +219,6 @@ class ChatActivity : AppCompatActivity() {
return true 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> { private fun uaPeerMessages(aor: String, peerUri: String): ArrayList<Message> {
val res = ArrayList<Message>() val res = ArrayList<Message>()
for (m in Message.messages()) for (m in Message.messages())
@@ -65,10 +65,8 @@ class ChatListAdapter(private val cxt: Context, private var rows: ArrayList<Mess
} }
val textView = chatView.findViewById(R.id.text) as TextView val textView = chatView.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 chatView return chatView
} }
@@ -39,7 +39,7 @@ class ChatsActivity: AppCompatActivity() {
listView = findViewById(R.id.chats) 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")!!
val headerView = findViewById(R.id.account) as TextView val headerView = findViewById(R.id.account) as TextView
val headerText = "Account ${aor.substringAfter(":")}" val headerText = "Account ${aor.substringAfter(":")}"
@@ -207,6 +207,14 @@ class ChatsActivity: AppCompatActivity() {
var filesPath = "" var filesPath = ""
fun findUaMessage(aor: String, timeStamp: Long): Message? {
for (i in Message.messages().indices.reversed())
if ((Message.messages()[i].aor == aor) &&
(Message.messages()[i].timeStamp == timeStamp))
return Message.messages()[i]
return null
}
fun saveUaMessage(aor: String, time: Long, path: String) { fun saveUaMessage(aor: String, time: Long, path: String) {
for (i in Message.messages().indices.reversed()) for (i in Message.messages().indices.reversed())
if ((Message.messages()[i].aor == aor) && if ((Message.messages()[i].aor == aor) &&
@@ -240,7 +240,7 @@ class MainActivity : AppCompatActivity() {
if (!Utils.checkSipUri(uri)) if (!Utils.checkSipUri(uri))
Utils.alertView(this,"Notice","Invalid SIP URI '$uri'") Utils.alertView(this,"Notice","Invalid SIP URI '$uri'")
else else
call(ua, uri) call(ua, uri, "outgoing")
} else { } else {
val latest = CallHistory.aorLatestHistory(aor) val latest = CallHistory.aorLatestHistory(aor)
if (latest != null) if (latest != null)
@@ -409,18 +409,126 @@ class MainActivity : AppCompatActivity() {
if (intent.hasExtra("onStartup")) if (intent.hasExtra("onStartup"))
moveTaskToBack(true) moveTaskToBack(true)
if (intent.hasExtra("action")) { if (intent.hasExtra("action"))
// MainActivity was not visible when call, message, or transfer request came in // MainActivity was not visible when call, message, or transfer request came in
handleIntent(intent) handleIntent(intent)
} }
override fun onNewIntent(intent: Intent) {
// Called when MainActivity already exists at the top of current task
super.onNewIntent(intent)
val action = intent.getStringExtra("action")
Log.d("Baresip", "onNewIntent action '$action'")
if (action != null) handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
val action = intent.getStringExtra("action")
Log.d("Baresip", "Handling intent '$action'")
when (action) {
"call" -> {
if (!Call.calls().isEmpty()) {
Toast.makeText(applicationContext, "You already have an active call!",
Toast.LENGTH_SHORT).show()
return
}
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.e("Baresip", "handleIntent 'call' did not find ua $uap")
return
}
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(ua.account.aor)
resumeAction = action
resumeUri = intent.getStringExtra("peer")
}
"call show", "call answer" -> {
val callp = intent.getStringExtra("callp")
val call = Call.find(callp)
if (call == null) {
Log.e("Baresip", "handleIntent '$action' did not find call $callp")
return
}
val ua = call.ua
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(ua.account.aor)
resumeAction = action
resumeCall = call
}
"transfer show", "transfer accept" -> {
val callp = intent.getStringExtra("callp")
val call = Call.find(callp)
if (call == null) {
Log.e("Baresip", "handleIntent '$action' did not find call $callp")
moveTaskToBack(true)
return
}
resumeAction = action
resumeCall = call
resumeUri = intent.getStringExtra("uri")
}
"message show", "message reply" -> {
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.e("Baresip", "onNewIntent did not find ua $uap")
return
}
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(ua.account.aor)
resumeAction = action
resumeUap = uap
resumeTime = intent.getStringExtra("time")
}
}
}
override fun onResume() {
super.onResume()
Log.d("Baresip", "Main resumed with action '$resumeAction'")
// imm.hideSoftInputFromWindow(callUri.windowToken, 0)
visible = true
when (resumeAction) {
"call show" ->
handleServiceEvent("call incoming",
arrayListOf(resumeCall!!.ua.uap, resumeCall!!.callp))
"call answer" ->
answerButton.performClick()
"call reject" ->
rejectButton.performClick()
"call" ->
callButton.performClick()
"transfer show", "transfer accept" ->
handleServiceEvent("$resumeAction,$resumeUri",
arrayListOf(resumeCall!!.ua.uap, resumeCall!!.callp))
"message show", "message reply" ->
handleServiceEvent(resumeAction, arrayListOf(resumeUap, resumeTime))
else -> {
uaAdapter.notifyDataSetChanged()
if (aorSpinner.selectedItemPosition != -1)
showCall(UserAgent.uas()[aorSpinner.selectedItemPosition])
}
}
resumeAction = ""
}
override fun onPause() {
super.onPause()
// Log.d("Baresip", "Main paused")
visible = false
} }
private fun handleServiceEvent(event: String, params: ArrayList<String>) { private fun handleServiceEvent(event: String, params: ArrayList<String>) {
if (taskId == -1) {
Log.d("Baresip", "Omit service event '$event' for task -1")
return
}
if (event == "stopped") { if (event == "stopped") {
Log.d("Baresip", "Handling service event 'stopped'") Log.d("Baresip", "Handling service event 'stopped'")
quitTimer.cancel() quitTimer.cancel()
finishAndRemoveTask() finishAndRemoveTask()
System.exit(0) // System.exit(0)
return return
} }
val uap = params[0] val uap = params[0]
@@ -491,8 +599,7 @@ class MainActivity : AppCompatActivity() {
dtmf.visibility = View.INVISIBLE dtmf.visibility = View.INVISIBLE
infoButton.visibility = View.INVISIBLE infoButton.visibility = View.INVISIBLE
} }
if (Utils.isVisible()) { if (!visible) {
Log.d("Baresip", "Baresip is visible")
val i = Intent(applicationContext, MainActivity::class.java) val i = Intent(applicationContext, MainActivity::class.java)
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
startActivity(i) startActivity(i)
@@ -528,10 +635,10 @@ class MainActivity : AppCompatActivity() {
dtmf.hint = "DTMF" dtmf.hint = "DTMF"
dtmf.visibility = View.VISIBLE dtmf.visibility = View.VISIBLE
dtmf.requestFocus() dtmf.requestFocus()
infoButton.visibility = View.VISIBLE
}
(dtmf.tag as ArrayList<TextWatcher>).add(call.dtmfWatcher!!) (dtmf.tag as ArrayList<TextWatcher>).add(call.dtmfWatcher!!)
dtmf.addTextChangedListener(call.dtmfWatcher) dtmf.addTextChangedListener(call.dtmfWatcher)
infoButton.visibility = View.VISIBLE
}
} }
"call verify" -> { "call verify" -> {
val callp = params[1] val callp = params[1]
@@ -570,7 +677,7 @@ class MainActivity : AppCompatActivity() {
} }
dialog.dismiss() dialog.dismiss()
} }
verifyDialog.create().show() if (!isFinishing()) verifyDialog.create().show()
} }
"call verified", "call secure" -> { "call verified", "call secure" -> {
val callp = params[1] val callp = params[1]
@@ -580,20 +687,16 @@ class MainActivity : AppCompatActivity() {
return return
} }
val tag: String val tag: String
if (ev[0] == "call secure") { if (call.security == R.drawable.box_yellow)
call.security = R.drawable.box_yellow
tag = "yellow" tag = "yellow"
} else { else
call.security = R.drawable.box_green
tag = "green" tag = "green"
call.zid = ev[1]
}
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) { if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
securityButton.setImageResource(call.security) securityButton.setImageResource(call.security)
securityButton.tag = tag securityButton.tag = tag
} }
} }
"call transfer" -> { "call transfer", "transfer show" -> {
val callp = params[1] val callp = params[1]
val call = Call.find(callp) val call = Call.find(callp)
if (call == null) { if (call == null) {
@@ -606,9 +709,9 @@ class MainActivity : AppCompatActivity() {
transferDialog.setMessage("Do you accept to transfer call to $target?") transferDialog.setMessage("Do you accept to transfer call to $target?")
transferDialog.setPositiveButton("Yes") { dialog, _ -> transferDialog.setPositiveButton("Yes") { dialog, _ ->
if (call in Call.calls()) if (call in Call.calls())
transfer(ua, call, ev[1]) Api.ua_hangup(uap, callp, 0, "")
else call(ua, ev[1], "transferring")
call(ua, ev[1]) showCall(ua)
dialog.dismiss() dialog.dismiss()
} }
transferDialog.setNegativeButton("No") { dialog, _ -> transferDialog.setNegativeButton("No") { dialog, _ ->
@@ -618,6 +721,18 @@ class MainActivity : AppCompatActivity() {
} }
transferDialog.create().show() transferDialog.create().show()
} }
"transfer accept" -> {
val callp = params[1]
val call = Call.find(callp)
if (call == null) {
Log.e("Baresip", "Call $callp to be transferred is not found")
return
}
if (call in Call.calls())
Api.ua_hangup(uap, callp, 0, "")
call(ua, ev[1], "transferring")
showCall(ua)
}
"call closed" -> { "call closed" -> {
val watchers = dtmf.tag as ArrayList<TextWatcher> val watchers = dtmf.tag as ArrayList<TextWatcher>
if (watchers.size > 0) { if (watchers.size > 0) {
@@ -630,10 +745,6 @@ class MainActivity : AppCompatActivity() {
callsButton.setImageResource(R.drawable.calls_missed) callsButton.setImageResource(R.drawable.calls_missed)
} }
speakerIcon.setIcon(R.drawable.speaker_off) speakerIcon.setIcon(R.drawable.speaker_off)
if (BaresipService.speakerPhone) {
baresipService.setAction("ToggleSpeaker")
startService(baresipService)
}
val param = ev[1].trim() val param = ev[1].trim()
if ((param != "") && (Call.uaCalls(ua, "").size == 0)) { if ((param != "") && (Call.uaCalls(ua, "").size == 0)) {
if (param.get(0).isDigit()) if (param.get(0).isDigit())
@@ -644,28 +755,26 @@ class MainActivity : AppCompatActivity() {
Toast.LENGTH_LONG).show() Toast.LENGTH_LONG).show()
} }
} }
"message" -> { "message show", "message reply" -> {
val peerUri = params[1] val timeStamp = params[1].toLong()
val msgText = params[2] val msg = ChatsActivity.findUaMessage(ua.account.aor, timeStamp)
val time = params[3] if (msg == null) {
Log.d("Baresip", "Incoming message $aor/$peerUri/$msgText") Log.e("Baresip", "Message $aor/$timeStamp is not found")
Message.add(Message(aor, peerUri, msgText, time.toLong(), return
R.drawable.arrow_down_green, 0, "", }
true)) Log.d("Baresip", "Message for $aor from ${msg.peerUri}")
if (Utils.isVisible()) {
if ((aorSpinner.selectedItemPosition == -1) || if ((aorSpinner.selectedItemPosition == -1) ||
(ua != UserAgent.uas()[aorSpinner.selectedItemPosition])) (ua != UserAgent.uas()[aorSpinner.selectedItemPosition]))
aorSpinner.setSelection(account_index) aorSpinner.setSelection(account_index)
val i = Intent(applicationContext, ChatsActivity::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", aor)
b.putString("peer", peerUri) b.putString("peer", msg.peerUri)
b.putBoolean("focus", false) b.putBoolean("focus", ev[0] == "message reply")
i.putExtras(b) i.putExtras(b)
startActivity(i) startActivity(i)
} }
}
"mwi notify" -> { "mwi notify" -> {
val lines = ev[1].split("\n") val lines = ev[1].split("\n")
for (line in lines) { for (line in lines) {
@@ -691,143 +800,11 @@ class MainActivity : AppCompatActivity() {
} }
} }
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
val action = intent.getStringExtra("action")
Log.d("Baresip", "onNewIntent action '$action'")
if (action != null) handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
val action = intent.getStringExtra("action")
Log.d("Baresip", "Handling intent '$action'")
when (action) {
"call" -> {
if (!Call.calls().isEmpty()) {
Toast.makeText(applicationContext, "You already have an active call!",
Toast.LENGTH_SHORT).show()
return
}
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.e("Baresip", "handleIntent 'call' did not find ua $uap")
return
}
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(ua.account.aor)
makeCall = intent.getStringExtra("peer")
}
"answer" -> {
answerCall = intent.getStringExtra("callp")
}
"reject" -> {
rejectCall = intent.getStringExtra("callp")
moveTaskToBack(true)
}
"transfer" -> {
val callp = intent.getStringExtra("callp")
val call = Call.find(callp)
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.e("Baresip", "Ua $uap of call transfer target does not exist")
moveTaskToBack(true)
return
}
if (call == null)
call(ua, intent.getStringExtra("uri"))
else
transfer(ua, call, intent.getStringExtra("uri"))
}
"deny" -> {
val callp = intent.getStringExtra("callp")
val call = Call.find(callp)
if (call == null)
Log.d("Baresip", "Call $callp denied transfer does not exist anymore")
else
Api.call_notify_sipfrag(callp, 603, "Decline")
moveTaskToBack(true)
}
"show", "reply", "save", "delete" -> {
val uap = intent.getStringExtra("uap")
val ua = UserAgent.find(uap)
if (ua == null) {
Log.e("Baresip", "onNewIntent did not find ua $uap")
return
}
val aor = ua.account.aor
when (action) {
"show", "reply" -> {
val i = Intent(this@MainActivity, ChatsActivity::class.java)
val b = Bundle()
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
spinToAor(aor)
b.putString("aor", aor)
b.putString("peer", intent.getStringExtra("peer"))
b.putBoolean("focus", action == "reply")
i.putExtras(b)
startActivityForResult(i, MESSAGES_CODE)
}
"save" -> {
ChatsActivity.saveUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong(),
applicationContext.filesDir.absolutePath)
moveTaskToBack(true)
}
"delete" -> {
ChatsActivity.deleteUaMessage(ua.account.aor,
intent.getStringExtra("time").toLong(),
applicationContext.filesDir.absolutePath)
moveTaskToBack(true)
}
}
nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID)
}
"message" -> {
val ua = UserAgent.find(intent.getStringExtra("uap"))!!
val i = Intent(applicationContext, ChatsActivity::class.java)
val b = Bundle()
b.putString("aor", ua.account.aor)
b.putString("peer", intent.getStringExtra("peer"))
b.putBoolean("focus", true)
i.putExtras(b)
startActivity(i)
}
}
}
override fun onPause() {
super.onPause()
// Log.d("Baresip", "Main paused")
visible = false
}
/*override fun onStop() { /*override fun onStop() {
super.onStop() super.onStop()
Log.d("Baresip", "Main stopped") Log.d("Baresip", "Main stopped")
}*/ }*/
override fun onResume() {
super.onResume()
Log.d("Baresip", "Main resumed")
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
visible = true
if (answerCall != "") {
answerCall = ""
answerButton.performClick()
}
if (rejectCall != "") {
rejectCall = ""
rejectButton.performClick()
}
if (makeCall != "") {
callUri.setText(makeCall)
makeCall = ""
callButton.performClick()
}
}
override fun onBackPressed() { override fun onBackPressed() {
moveTaskToBack(true) moveTaskToBack(true)
} }
@@ -976,7 +953,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
private fun call(ua: UserAgent, uri: String) { private fun call(ua: UserAgent, uri: String, status: String) {
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,
@@ -991,8 +968,7 @@ class MainActivity : AppCompatActivity() {
val callp = Api.ua_connect(ua.uap, uri) val callp = Api.ua_connect(ua.uap, uri)
if (callp != "") { if (callp != "") {
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", "outgoing", Call.calls().add(Call(callp, ua, uri, "out", status, Utils.dtmfWatcher(callp)))
Utils.dtmfWatcher(callp)))
imm.hideSoftInputFromWindow(callUri.windowToken, 0) imm.hideSoftInputFromWindow(callUri.windowToken, 0)
securityButton.visibility = View.INVISIBLE securityButton.visibility = View.INVISIBLE
callButton.visibility = View.INVISIBLE callButton.visibility = View.INVISIBLE
@@ -1010,6 +986,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
// Currently transfer is implemented by first closing existing call and the making the new one
private fun transfer(ua: UserAgent, call: Call, uri: String) { private fun transfer(ua: UserAgent, call: Call, uri: String) {
val newCallp = Api.ua_call_alloc(ua.uap, call.callp) val newCallp = Api.ua_call_alloc(ua.uap, call.callp)
if (newCallp != "") { if (newCallp != "") {
@@ -1017,7 +994,8 @@ class MainActivity : AppCompatActivity() {
val newCall = Call(newCallp, ua, uri, "out", "transferring", val newCall = Call(newCallp, ua, uri, "out", "transferring",
Utils.dtmfWatcher(newCallp)) Utils.dtmfWatcher(newCallp))
Call.calls().add(newCall) Call.calls().add(newCall)
Api.call_stop_audio(call.callp) Api.ua_hangup(ua.uap, call.callp, 0, "")
// Api.call_stop_audio(call.callp)
val err = Api.call_connect(newCallp, uri) val err = Api.call_connect(newCallp, uri)
if (err == 0) { if (err == 0) {
Api.call_start_audio(newCallp) Api.call_start_audio(newCallp)
@@ -1103,15 +1081,6 @@ class MainActivity : AppCompatActivity() {
holdButton.visibility = View.INVISIBLE holdButton.visibility = View.INVISIBLE
dtmf.visibility = View.INVISIBLE dtmf.visibility = View.INVISIBLE
infoButton.visibility = View.INVISIBLE infoButton.visibility = View.INVISIBLE
if (answerCall == call.callp) {
answerCall = ""
answerButton.performClick()
}
if (rejectCall == call.callp) {
rejectCall = ""
rejectButton.performClick()
moveTaskToBack(true)
}
} }
"connected" -> { "connected" -> {
securityButton.setImageResource(call.security) securityButton.setImageResource(call.security)
@@ -1141,10 +1110,13 @@ class MainActivity : AppCompatActivity() {
companion object { companion object {
var visible = true var visible = false
var makeCall = ""
var answerCall = "" var resumeAction = ""
var rejectCall = "" var resumeUap = ""
var resumeCall: Call? = null
var resumeUri = ""
var resumeTime = ""
const val ACCOUNTS_CODE = 1 const val ACCOUNTS_CODE = 1
const val CONTACTS_CODE = 2 const val CONTACTS_CODE = 2
@@ -63,7 +63,10 @@ class MessageListAdapter(private val cxt: Context, private val rows: ArrayList<M
} }
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) textView.setTypeface(null, Typeface.BOLD) if (message.new) {
textView.setTypeface(null, Typeface.BOLD)
message.new = false
}
return messageView return messageView
} }
@@ -6,6 +6,8 @@ import android.support.v7.app.AlertDialog
import android.util.Log import android.util.Log
import android.os.PowerManager import android.os.PowerManager
import android.app.KeyguardManager import android.app.KeyguardManager
import android.content.Intent
import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@@ -115,10 +117,13 @@ object Utils {
} }
fun friendlyUri(uri: String, domain: String): String { fun friendlyUri(uri: String, domain: String): String {
if (uri.contains("@") && !uri.substring(4).contains(":") && var u = uri
!uri.contains(";")) { if (uri.startsWith("<") && (uri.endsWith(">")))
val user = uriUserPart(uri) u = uri.substring(1).substringBeforeLast(">")
val host = uriHostPart(uri) if (u.contains("@") && !u.substring(4).contains(":") &&
!u.contains(";")) {
val user = uriUserPart(u)
val host = uriHostPart(u)
if (host == domain) return user else return "$user@$host" if (host == domain) return user else return "$user@$host"
} else { } else {
return uri return uri
@@ -281,4 +286,22 @@ object Utils {
} }
} }
fun dumpIntent(intent: Intent) {
val bundle: Bundle = intent.extras ?: return
val keys = bundle.keySet()
val it = keys.iterator()
Log.d("Baresip", "Dumping intent start")
while (it.hasNext()) {
val key = it.next()
Log.d("Baresip","[" + key + "=" + bundle.get(key)+"]");
}
Log.d("Baresip", "Dumping intent finish")
}
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 738 B

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

+1 -2
View File
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.0' ext.kotlin_version = '1.3.21'
repositories { repositories {
google() google()
jcenter() jcenter()
@@ -9,7 +9,6 @@ buildscript {
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.android.tools.build:gradle:3.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }