- all user interface unrelated data is now kept in baresip service
allowing proper recovery in case Android kills other activities - many other improvements and bug fixes
This commit is contained in:
@ -7,8 +7,8 @@ android {
|
||||
applicationId = 'com.tutpro.baresip'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode = 33
|
||||
versionName = '4.0.0'
|
||||
versionCode = 34
|
||||
versionName = '4.1.0'
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cFlags '-DHAVE_INTTYPES_H'
|
||||
|
||||
@ -700,7 +700,7 @@ Java_com_tutpro_baresip_AccountKt_account_1sipnat(JNIEnv *env, jobject thiz, jst
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_AccountKt_account_1set_1sipnat(JNIEnv *env, jobject thiz,
|
||||
jstring javaAcc, jstring javaSipNat) {
|
||||
jstring javaAcc, jstring javaSipNat) {
|
||||
const char *native_acc = (*env)->GetStringUTFChars(env, javaAcc, 0);
|
||||
struct account *acc = (struct account *)strtoul(native_acc, NULL, 10);
|
||||
(*env)->ReleaseStringUTFChars(env, javaAcc, native_acc);
|
||||
@ -716,7 +716,7 @@ Java_com_tutpro_baresip_AccountKt_account_1set_1sipnat(JNIEnv *env, jobject thiz
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_AccountKt_account_1set_1mwi(JNIEnv *env, jobject thiz,
|
||||
jstring javaAcc, jstring javaValue) {
|
||||
jstring javaAcc, jstring javaValue) {
|
||||
const char *native_acc = (*env)->GetStringUTFChars(env, javaAcc, 0);
|
||||
struct account *acc = (struct account *) strtoul(native_acc, NULL, 10);
|
||||
(*env)->ReleaseStringUTFChars(env, javaAcc, native_acc);
|
||||
@ -748,8 +748,7 @@ Java_com_tutpro_baresip_AccountKt_account_1vm_1uri(JNIEnv *env, jobject thiz, js
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1alloc(JNIEnv *env, jobject thiz,
|
||||
jstring javaUri) {
|
||||
Java_com_tutpro_baresip_Api_ua_1alloc(JNIEnv *env, jobject thiz, jstring javaUri) {
|
||||
const char *uri = (*env)->GetStringUTFChars(env, javaUri, 0);
|
||||
struct ua *ua;
|
||||
LOGD("allocating UA '%s'\n", uri);
|
||||
@ -762,8 +761,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1alloc(JNIEnv *env, jobject
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1register(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1register(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -772,8 +770,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1register(JNIEnv *env, jobje
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1unregister(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1unregister(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -782,8 +779,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1unregister(JNIEnv *env, job
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1isregistered(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1isregistered(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -792,8 +788,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1isregistered(JNIEnv *env, j
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1update_1account(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1update_1account(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -802,8 +797,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1update_1account(JNIEnv *env
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1destroy(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1destroy(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -812,7 +806,7 @@ Java_com_tutpro_baresip_UserAgent_00024Companion_ua_1destroy(JNIEnv *env, jobjec
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_tutpro_baresip_UserAgentKt_ua_1account(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_ua_1account(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -828,8 +822,7 @@ Java_com_tutpro_baresip_UserAgentKt_ua_1account(JNIEnv *env, jobject thiz, jstri
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_uag_1current_1set(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA)
|
||||
Java_com_tutpro_baresip_Api_uag_1current_1set(JNIEnv *env, jobject thiz, jstring javaUA)
|
||||
{
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
@ -849,9 +842,47 @@ Java_com_tutpro_baresip_Api_call_1peeruri(JNIEnv *env, jobject thiz, jstring jav
|
||||
return (*env)->NewStringUTF(env, call_peeruri(call));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_Api_call_1send_1digit(JNIEnv *env, jobject thiz, jstring javaCall,
|
||||
jchar digit) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
const uint16_t native_digit = digit;
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
LOGD("sending DTMF digit '%c' to call %s\n", (char)native_digit, native_call);
|
||||
re_thread_enter();
|
||||
int res = call_send_digit(call, (char)native_digit);
|
||||
if (!res) res = call_send_digit(call, KEYCODE_REL);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_Api_ua_1hangup(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA, jstring javaCall, jint code,
|
||||
jstring reason) {
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
const uint16_t native_code = code;
|
||||
const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0);
|
||||
LOGD("hanging up call %s/%s\n", native_ua, native_call);
|
||||
re_thread_enter();
|
||||
if (strlen(native_reason) == 0)
|
||||
ua_hangup(ua, call, native_code, NULL);
|
||||
else
|
||||
ua_hangup(ua, call, native_code, native_reason);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_ua_1connect(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA, jstring javaURI) {
|
||||
Java_com_tutpro_baresip_Api_ua_1connect(JNIEnv *env, jobject thiz, jstring javaUA,
|
||||
jstring javaURI) {
|
||||
struct call *call;
|
||||
struct ua *ua;
|
||||
int err;
|
||||
@ -875,8 +906,8 @@ Java_com_tutpro_baresip_MainActivity_ua_1connect(JNIEnv *env, jobject thiz,
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_ua_1call_1alloc(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA, jstring javaXCall) {
|
||||
Java_com_tutpro_baresip_Api_ua_1call_1alloc(JNIEnv *env, jobject thiz, jstring javaUA,
|
||||
jstring javaXCall) {
|
||||
struct call *xcall, *call = NULL;
|
||||
struct ua *ua;
|
||||
int err;
|
||||
@ -901,8 +932,8 @@ Java_com_tutpro_baresip_MainActivity_ua_1call_1alloc(JNIEnv *env, jobject thiz,
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA, jstring javaCall) {
|
||||
Java_com_tutpro_baresip_Api_ua_1answer(JNIEnv *env, jobject thiz, jstring javaUA,
|
||||
jstring javaCall) {
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
LOGD("answering call %s/%s\n", native_ua, native_call);
|
||||
@ -918,8 +949,8 @@ Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1connect(JNIEnv *env, jobject thiz, jstring javaCall,
|
||||
jstring javaPeer) {
|
||||
Java_com_tutpro_baresip_Api_call_1connect(JNIEnv *env, jobject thiz, jstring javaCall,
|
||||
jstring javaPeer) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
const char *native_peer = (*env)->GetStringUTFChars(env, javaPeer, 0);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
@ -936,7 +967,23 @@ Java_com_tutpro_baresip_MainActivity_call_1connect(JNIEnv *env, jobject thiz, js
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1start_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
Java_com_tutpro_baresip_Api_call_1notify_1sipfrag(JNIEnv *env, jobject thiz, jstring javaCall,
|
||||
jint code, jstring reason) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
const uint16_t native_code = code;
|
||||
const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0);
|
||||
LOGD("notifying call %s/%s\n", native_call, native_reason);
|
||||
re_thread_enter();
|
||||
(void)call_notify_sipfrag(call, native_code, native_reason);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_Api_call_1start_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
LOGD("starting audio of call %s\n", native_call);
|
||||
@ -949,7 +996,7 @@ Java_com_tutpro_baresip_MainActivity_call_1start_1audio(JNIEnv *env, jobject thi
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1stop_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
Java_com_tutpro_baresip_Api_call_1stop_1audio(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
LOGD("stopping audio of call %s\n", native_call);
|
||||
@ -962,8 +1009,7 @@ Java_com_tutpro_baresip_MainActivity_call_1stop_1audio(JNIEnv *env, jobject thiz
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1hold(JNIEnv *env, jobject thiz,
|
||||
jstring javaCall) {
|
||||
Java_com_tutpro_baresip_Api_call_1hold(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
||||
int ret;
|
||||
@ -979,7 +1025,7 @@ Java_com_tutpro_baresip_MainActivity_call_1hold(JNIEnv *env, jobject thiz,
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1unhold(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
Java_com_tutpro_baresip_Api_call_1unhold(JNIEnv *env, jobject thiz, jstring javaCall) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
||||
int ret;
|
||||
@ -994,48 +1040,9 @@ Java_com_tutpro_baresip_MainActivity_call_1unhold(JNIEnv *env, jobject thiz, jst
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_ua_1hangup(JNIEnv *env, jobject thiz,
|
||||
jstring javaUA, jstring javaCall, jint code,
|
||||
jstring reason) {
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
const uint16_t native_code = code;
|
||||
const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0);
|
||||
LOGD("hanging up call %s/%s\n", native_ua, native_call);
|
||||
re_thread_enter();
|
||||
if (strlen(native_reason) == 0)
|
||||
ua_hangup(ua, call, native_code, NULL);
|
||||
else
|
||||
ua_hangup(ua, call, native_code, native_reason);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1send_1digit(JNIEnv *env, jobject thiz,
|
||||
jstring javaCall, jchar digit) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
const uint16_t native_digit = digit;
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
LOGD("sending DTMF digit '%c' to call %s\n", (char)native_digit, native_call);
|
||||
re_thread_enter();
|
||||
int res = call_send_digit(call, (char)native_digit);
|
||||
if (!res) res = call_send_digit(call, KEYCODE_REL);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_ChatActivity_message_1send(JNIEnv *env, jobject thiz, jstring javaUA,
|
||||
jstring javaPeer, jstring javaMsg,
|
||||
jstring javaTime) {
|
||||
Java_com_tutpro_baresip_Api_message_1send(JNIEnv *env, jobject thiz, jstring javaUA,
|
||||
jstring javaPeer, jstring javaMsg, jstring javaTime) {
|
||||
struct ua *ua;
|
||||
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||
const char *native_peer = (*env)->GetStringUTFChars(env, javaPeer, 0);
|
||||
@ -1055,24 +1062,8 @@ Java_com_tutpro_baresip_ChatActivity_message_1send(JNIEnv *env, jobject thiz, js
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_call_1notify_1sipfrag(JNIEnv *env, jobject thiz,
|
||||
jstring javaCall, jint code, jstring reason) {
|
||||
const char *native_call = (*env)->GetStringUTFChars(env, javaCall, 0);
|
||||
struct call *call = (struct call *)strtoul(native_call, NULL, 10);
|
||||
const uint16_t native_code = code;
|
||||
const char *native_reason = (*env)->GetStringUTFChars(env, reason, 0);
|
||||
LOGD("notifying call %s/%s\n", native_call, native_reason);
|
||||
re_thread_enter();
|
||||
(void)call_notify_sipfrag(call, native_code, native_reason);
|
||||
re_thread_leave();
|
||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||
(*env)->ReleaseStringUTFChars(env, reason, native_reason);
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_tutpro_baresip_MainActivity_reload_1config(JNIEnv *env, jobject thiz) {
|
||||
Java_com_tutpro_baresip_Api_reload_1config(JNIEnv *env, jobject thiz) {
|
||||
int err;
|
||||
err = conf_configure();
|
||||
if (err) {
|
||||
|
||||
@ -116,28 +116,28 @@ class Account(val accp: String) {
|
||||
|
||||
fun accounts(): ArrayList<Account> {
|
||||
val res = ArrayList<Account>()
|
||||
for (ua in MainActivity.uas) {
|
||||
for (ua in UserAgent.uas()) {
|
||||
res.add(ua.account)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun find(uas: ArrayList<UserAgent>, accp: String): Account? {
|
||||
for (ua in uas) {
|
||||
fun find(accp: String): Account? {
|
||||
for (ua in UserAgent.uas()) {
|
||||
if (ua.account.accp == accp) return ua.account
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun findUa(aor: String): UserAgent? {
|
||||
for (ua in MainActivity.uas) {
|
||||
for (ua in UserAgent.uas()) {
|
||||
if (ua.account.aor == aor) return ua
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun exists(uas: ArrayList<UserAgent>, aor: String): Boolean {
|
||||
for (ua in uas) {
|
||||
fun exists(aor: String): Boolean {
|
||||
for (ua in UserAgent.uas()) {
|
||||
if (ua.account.aor == aor) return true
|
||||
}
|
||||
return false
|
||||
@ -155,7 +155,6 @@ external fun account_auth_pass(acc: String): String
|
||||
external fun account_set_auth_pass(acc: String, pass: String): Int
|
||||
external fun account_outbound(acc: String, ix: Int): String
|
||||
external fun account_set_outbound(acc: String, ob: String, ix: Int): Int
|
||||
external fun account_sipnat(acc: String): String
|
||||
external fun account_set_sipnat(acc: String, sipnat: String): Int
|
||||
external fun account_audio_codec(acc: String, ix: Int): String
|
||||
external fun account_regint(acc: String): Int
|
||||
|
||||
@ -32,9 +32,9 @@ class AccountActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_account)
|
||||
|
||||
acc = Account.find(MainActivity.uas, intent.extras.getString("accp"))!!
|
||||
acc = Account.find(intent.extras.getString("accp"))!!
|
||||
aor = acc.aor
|
||||
uaIndex = UserAgent.findAorIndex(MainActivity.uas, aor)!!
|
||||
uaIndex = UserAgent.findAorIndex(UserAgent.uas(), aor)!!
|
||||
|
||||
setTitle(aor.replace("sip:", ""))
|
||||
|
||||
@ -220,7 +220,7 @@ class AccountActivity : AppCompatActivity() {
|
||||
if (acc.regint != 3600) newRegint = 3600
|
||||
} else {
|
||||
if (acc.regint != 0) {
|
||||
UserAgent.ua_unregister(MainActivity.uas[uaIndex].uap)
|
||||
Api.ua_unregister(UserAgent.uas()[uaIndex].uap)
|
||||
newRegint = 0
|
||||
}
|
||||
}
|
||||
@ -285,20 +285,18 @@ class AccountActivity : AppCompatActivity() {
|
||||
|
||||
if (save) {
|
||||
AccountsActivity.saveAccounts()
|
||||
if (UserAgent.ua_update_account(MainActivity.uas[uaIndex].uap) != 0)
|
||||
if (Api.ua_update_account(UserAgent.uas()[uaIndex].uap) != 0)
|
||||
Log.e("Baresip", "Failed to update UA with AoR $aor")
|
||||
}
|
||||
|
||||
if (regCheck.isChecked) UserAgent.ua_register(MainActivity.uas[uaIndex].uap)
|
||||
if (regCheck.isChecked) Api.ua_register(UserAgent.uas()[uaIndex].uap)
|
||||
|
||||
setResult(RESULT_OK, intent)
|
||||
finish()
|
||||
return true
|
||||
|
||||
} else if (item.itemId == android.R.id.home) {
|
||||
|
||||
Log.d("Baresip", "Back array was pressed at Account")
|
||||
setResult(RESULT_CANCELED, intent)
|
||||
finish()
|
||||
return true
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@ -28,22 +29,21 @@ class AccountListAdapter(private val cxt: Context, private val rows: ArrayList<A
|
||||
aorView.setOnClickListener { _ ->
|
||||
val i = Intent(cxt, AccountActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("accp", MainActivity.uas[position].account.accp)
|
||||
b.putString("accp", UserAgent.uas()[position].account.accp)
|
||||
i.putExtras(b)
|
||||
cxt.startActivity(i)
|
||||
(cxt as Activity).startActivity(i)
|
||||
}
|
||||
val ua = UserAgent.uas()[position]
|
||||
val actionView = rowView.findViewById(R.id.action) as ImageButton
|
||||
actionView.setImageResource(row.action)
|
||||
actionView.setOnClickListener { _ ->
|
||||
Log.d("Baresip", "Delete button clicked")
|
||||
val deleteDialog = AlertDialog.Builder(cxt)
|
||||
deleteDialog.setMessage("Do you want to delete account ${MainActivity.uas[position].account.aor}?")
|
||||
deleteDialog.setMessage("Do you want to delete account ${ua.account.aor}?")
|
||||
deleteDialog.setPositiveButton("Delete") { dialog, _ ->
|
||||
MainActivity.uas[position].destroy()
|
||||
MainActivity.uas.remove(MainActivity.uas[position])
|
||||
MainActivity.images.removeAt(position)
|
||||
AccountsActivity.saveAccounts()
|
||||
UserAgent.remove(ua)
|
||||
AccountsActivity.generateAccounts()
|
||||
AccountsActivity.saveAccounts()
|
||||
this.notifyDataSetChanged()
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
@ -13,17 +13,20 @@ import java.util.ArrayList
|
||||
|
||||
class AccountsActivity : AppCompatActivity() {
|
||||
|
||||
internal var aor: String = ""
|
||||
internal lateinit var alAdapter: AccountListAdapter
|
||||
|
||||
internal var aor = ""
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_accounts)
|
||||
|
||||
val listview = findViewById(R.id.accounts) as ListView
|
||||
filesPath = applicationContext.filesDir.absolutePath
|
||||
|
||||
val listView = findViewById(R.id.accounts) as ListView
|
||||
generateAccounts()
|
||||
alAdapter = AccountListAdapter(this, accounts)
|
||||
listview.adapter = alAdapter
|
||||
listView.adapter = alAdapter
|
||||
|
||||
val addAccountButton = findViewById(R.id.addAccount) as ImageButton
|
||||
val newAorView = findViewById(R.id.newAor) as EditText
|
||||
@ -34,7 +37,7 @@ class AccountsActivity : AppCompatActivity() {
|
||||
Log.e("Baresip", "Invalid SIP Address of Record $aor")
|
||||
Utils.alertView(this, "Notice",
|
||||
"Invalid SIP Address of Record: $aor")
|
||||
} else if (Account.exists(MainActivity.uas, aor)) {
|
||||
} else if (Account.exists(aor)) {
|
||||
Log.e("Baresip", "Account $aor already exists")
|
||||
} else {
|
||||
val ua = UserAgent.uaAlloc("<$aor>;regq=0.5;pubint=0;regint=0")
|
||||
@ -46,8 +49,7 @@ class AccountsActivity : AppCompatActivity() {
|
||||
newAorView.setText("")
|
||||
newAorView.hint = "SIP URI user@domain"
|
||||
newAorView.clearFocus()
|
||||
MainActivity.uas.add(ua)
|
||||
MainActivity.images.add(R.drawable.dot_yellow)
|
||||
UserAgent.add(ua, R.drawable.dot_yellow)
|
||||
generateAccounts()
|
||||
alAdapter.notifyDataSetChanged()
|
||||
saveAccounts()
|
||||
@ -56,10 +58,18 @@ class AccountsActivity : AppCompatActivity() {
|
||||
b.putString("accp", ua.account.accp)
|
||||
i.putExtras(b)
|
||||
startActivity(i)
|
||||
// recreate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val accp = intent.extras.getString("accp")
|
||||
if (accp != "") {
|
||||
val i = Intent(this, AccountActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("accp", accp)
|
||||
i.putExtras(b)
|
||||
startActivity(i)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
@ -76,11 +86,13 @@ class AccountsActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
|
||||
internal var filesPath = ""
|
||||
|
||||
var accounts = ArrayList<AccountRow>()
|
||||
|
||||
fun generateAccounts() {
|
||||
accounts.clear()
|
||||
for (ua in MainActivity.uas)
|
||||
for (ua in UserAgent.uas())
|
||||
accounts.add(AccountRow(ua.account.aor.replace("sip:", ""),
|
||||
R.drawable.action_remove))
|
||||
}
|
||||
@ -88,9 +100,8 @@ class AccountsActivity : AppCompatActivity() {
|
||||
fun saveAccounts() {
|
||||
var accounts = ""
|
||||
for (a in Account.accounts()) accounts = accounts + a.print() + "\n"
|
||||
val path = MainActivity.filesPath + "/accounts"
|
||||
Utils.putFileContents(File(path), accounts)
|
||||
// Log.d("Baresip", "Saved accounts '${accounts}' to '$path")
|
||||
Utils.putFileContents(File(filesPath + "/accounts"), accounts)
|
||||
// Log.d("Baresip", "Saved accounts '${accounts}' to '${filesPath}/accounts")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,28 @@ package com.tutpro.baresip
|
||||
object Api {
|
||||
|
||||
external fun audio_codecs(): String
|
||||
external fun uag_current_set(uap: String)
|
||||
external fun ua_account(ua: String): String
|
||||
external fun ua_alloc(uri: String): String
|
||||
external fun ua_update_account(ua: String): Int
|
||||
external fun ua_destroy(ua: String)
|
||||
external fun ua_register(ua: String): Int
|
||||
external fun ua_isregistered(ua: String): Boolean
|
||||
external fun ua_unregister(ua: String)
|
||||
external fun ua_connect(uap: String, peer_uri: String): String
|
||||
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
|
||||
external fun ua_call_alloc(uap: String, xcallp: String): String
|
||||
external fun ua_answer(uap: String, callp: String)
|
||||
external fun call_hold(callp: String): Int
|
||||
external fun call_unhold(callp: String): Int
|
||||
external fun call_connect(callp: String, peer_uri: String): Int
|
||||
external fun call_peeruri(callp: String): String
|
||||
external fun call_send_digit(callp: String, digit: Char): Int
|
||||
external fun call_notify_sipfrag(callp: String, code: Int, reason: String)
|
||||
external fun call_start_audio(callp: String)
|
||||
external fun call_stop_audio(callp: String)
|
||||
external fun message_send(uap: String, peer_uri: String, message: String, time: String): Int
|
||||
external fun reload_config(): Int
|
||||
external fun cmd_exec(cmd: String): Int
|
||||
external fun contact_add(contact: String)
|
||||
external fun contacts_remove()
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.*
|
||||
import android.app.Notification.VISIBILITY_PUBLIC
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.*
|
||||
import android.media.*
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkInfo
|
||||
import android.net.wifi.WifiManager
|
||||
@ -22,11 +21,14 @@ import android.os.Build
|
||||
import android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
|
||||
class BaresipService: Service() {
|
||||
|
||||
private val LOG_TAG = "Baresip Service"
|
||||
internal lateinit var intent: Intent
|
||||
internal lateinit var am: AudioManager
|
||||
internal lateinit var rt: Ringtone
|
||||
internal lateinit var nm: NotificationManager
|
||||
internal lateinit var snb: NotificationCompat.Builder
|
||||
internal lateinit var npi: PendingIntent
|
||||
@ -34,6 +36,10 @@ class BaresipService: Service() {
|
||||
internal lateinit var wl: PowerManager.WakeLock
|
||||
internal lateinit var fl: WifiManager.WifiLock
|
||||
|
||||
internal var rtTimer: Timer? = null
|
||||
internal var filesPath = ""
|
||||
internal var restarting = false
|
||||
|
||||
override fun onCreate() {
|
||||
|
||||
Log.d(LOG_TAG, "At onCreate")
|
||||
@ -41,6 +47,13 @@ class BaresipService: Service() {
|
||||
intent = Intent("com.tutpro.baresip.EVENT")
|
||||
intent.setPackage("com.tutpro.baresip")
|
||||
|
||||
filesPath = applicationContext.filesDir.absolutePath
|
||||
|
||||
am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext,
|
||||
RingtoneManager.TYPE_RINGTONE)
|
||||
rt = RingtoneManager.getRingtone(applicationContext, rtUri)
|
||||
|
||||
nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
createNotificationChannels()
|
||||
snb = NotificationCompat.Builder(this, DEFAULT_CHANNEL_ID)
|
||||
@ -59,7 +72,7 @@ class BaresipService: Service() {
|
||||
if (isConnected) {
|
||||
Log.d(LOG_TAG, "Network is connected/connecting")
|
||||
if (disconnected) {
|
||||
UserAgent.register(MainActivity.uas)
|
||||
UserAgent.register(uas)
|
||||
disconnected = false
|
||||
}
|
||||
} else {
|
||||
@ -103,22 +116,21 @@ class BaresipService: Service() {
|
||||
|
||||
val assets = arrayOf("accounts", "contacts", "config", "busy.wav", "callwaiting.wav",
|
||||
"error.wav", "notfound.wav", "ring.wav", "ringback.wav")
|
||||
val path = applicationContext.filesDir.path
|
||||
var file = File(path)
|
||||
var file = File(filesPath)
|
||||
if (!file.exists()) {
|
||||
Log.d(LOG_TAG, "Creating baresip directory")
|
||||
try {
|
||||
File(path).mkdirs()
|
||||
File(filesPath).mkdirs()
|
||||
} catch (e: Error) {
|
||||
Log.e(LOG_TAG, "Failed to create directory: " + e.toString())
|
||||
}
|
||||
|
||||
}
|
||||
for (a in assets) {
|
||||
file = File("$path/$a")
|
||||
file = File("${filesPath}/$a")
|
||||
if (!file.exists()) {
|
||||
Log.d(LOG_TAG, "Copying asset $a")
|
||||
Utils.copyAssetToFile(applicationContext, a, "$path/$a")
|
||||
Utils.copyAssetToFile(applicationContext, a, "$filesPath/$a")
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Asset $a already copied")
|
||||
if (a == "config") {
|
||||
@ -144,8 +156,8 @@ class BaresipService: Service() {
|
||||
}
|
||||
|
||||
wl.acquire()
|
||||
Thread(Runnable { baresipStart(path) }).start()
|
||||
BaresipService.IS_SERVICE_RUNNING = true
|
||||
Thread(Runnable { baresipStart(filesPath) }).start()
|
||||
BaresipService.isServiceRunning = true
|
||||
registerReceiver(nr, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))
|
||||
showStatusNotification()
|
||||
}
|
||||
@ -159,7 +171,7 @@ class BaresipService: Service() {
|
||||
}
|
||||
|
||||
"Kill" -> {
|
||||
RESTARTING = true
|
||||
restarting = true
|
||||
stop()
|
||||
}
|
||||
}
|
||||
@ -175,7 +187,7 @@ class BaresipService: Service() {
|
||||
Log.d(LOG_TAG, "In onDestroy")
|
||||
super.onDestroy()
|
||||
Log.i(LOG_TAG, "Restart baresip killed by Android")
|
||||
RESTARTING = true
|
||||
restarting = true
|
||||
stop()
|
||||
}
|
||||
|
||||
@ -208,14 +220,13 @@ class BaresipService: Service() {
|
||||
fun uaAdd(uap: String) {
|
||||
Log.d(LOG_TAG, "addUA at BaresipService")
|
||||
val ua = UserAgent(uap)
|
||||
MainActivity.uas.add(ua)
|
||||
if (UserAgent.ua_isregistered(uap)) {
|
||||
uas.add(ua)
|
||||
if (Api.ua_isregistered(uap)) {
|
||||
Log.d(LOG_TAG, "Ua ${ua.account.aor} is registered")
|
||||
MainActivity.images.add(R.drawable.dot_green)
|
||||
status.add(R.drawable.dot_green)
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Ua ${ua.account.aor} is NOT registered")
|
||||
MainActivity.images.add(R.drawable.dot_yellow)
|
||||
// ua.register()
|
||||
status.add(R.drawable.dot_yellow)
|
||||
}
|
||||
val intent = Intent("service event")
|
||||
intent.putExtra("event", "ua added")
|
||||
@ -226,54 +237,69 @@ class BaresipService: Service() {
|
||||
|
||||
@Keep
|
||||
fun uaEvent(event: String, uap: String, callp: String) {
|
||||
Log.d(LOG_TAG, "updateStatus got event $event/$uap/$callp")
|
||||
if (!IS_SERVICE_RUNNING) return
|
||||
Log.d(LOG_TAG, "uaEvent got event $event/$uap/$callp")
|
||||
if (!isServiceRunning) return
|
||||
if (event == "exit")
|
||||
return
|
||||
val ua = UserAgent.find(MainActivity.uas, uap)
|
||||
val ua = UserAgent.find(uap)
|
||||
if (ua == null) {
|
||||
Log.w(LOG_TAG, "updateStatus did not find ua $uap")
|
||||
Log.w(LOG_TAG, "uaEvent did not find ua $uap")
|
||||
return
|
||||
}
|
||||
val aor = ua.account.aor
|
||||
for (account_index in MainActivity.uas.indices) {
|
||||
if (MainActivity.uas[account_index].account.aor == aor) {
|
||||
when (event) {
|
||||
var newEvent: String? = null
|
||||
val ev = event.split(",")
|
||||
for (account_index in uas.indices) {
|
||||
if (uas[account_index].account.aor == aor) {
|
||||
when (ev[0]) {
|
||||
"registering" -> {
|
||||
return
|
||||
}
|
||||
"registered" -> {
|
||||
if (ua.account.regint == 0)
|
||||
MainActivity.images[account_index] = R.drawable.dot_yellow
|
||||
status[account_index] = R.drawable.dot_yellow
|
||||
else
|
||||
MainActivity.images[account_index] = R.drawable.dot_green
|
||||
status[account_index] = R.drawable.dot_green
|
||||
updateStatusNotification()
|
||||
}
|
||||
"registering failed" -> {
|
||||
MainActivity.images[account_index] = R.drawable.dot_red
|
||||
status[account_index] = R.drawable.dot_red
|
||||
updateStatusNotification()
|
||||
}
|
||||
"unregistering" -> {
|
||||
MainActivity.images[account_index] = R.drawable.dot_yellow
|
||||
status[account_index] = R.drawable.dot_yellow
|
||||
updateStatusNotification()
|
||||
}
|
||||
"call incoming" -> {
|
||||
if (!Utils.isVisible()) {
|
||||
val peerUri = Api.call_peeruri(callp)
|
||||
if (Call.calls().size > 0) {
|
||||
Log.i(LOG_TAG, "Auto-rejecting incoming call $uap/$callp/$peerUri")
|
||||
Api.ua_hangup(uap, callp, 486, "Busy Here")
|
||||
CallHistory.add(CallHistory(aor, peerUri, "in", false))
|
||||
CallHistory.save(filesPath)
|
||||
ua.account.missedCalls = true
|
||||
newEvent = "call rejected"
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Incoming call $uap/$callp/$peerUri")
|
||||
calls.add(Call(callp, ua, peerUri, "in", "incoming",
|
||||
Utils.dtmfWatcher(callp)))
|
||||
startRinging()
|
||||
}
|
||||
if ((newEvent == null) && !Utils.isVisible()) {
|
||||
val cnb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val caller = Utils.friendlyUri(ContactsActivity.contactName(peerUri),
|
||||
Utils.aorDomain(aor))
|
||||
val title = "Incoming call from $caller"
|
||||
cnb.setSmallIcon(R.drawable.ic_stat)
|
||||
.setColor(0x0ca1fd)
|
||||
.setContentIntent(npi)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle("Call from ${ContactsActivity.contactName(
|
||||
Api.call_peeruri(callp))}")
|
||||
.setContentTitle(title)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
cnb.setVibrate(LongArray(0))
|
||||
.setVisibility(VISIBILITY_PRIVATE)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
}
|
||||
/* val view = RemoteViews(getPackageName(), R.layout.call_notification)
|
||||
view.setTextViewText(R.id.callFrom, "Call from ${Api.call_peeruri(callp)}")
|
||||
cnb.setContent(view) */
|
||||
val answerIntent = Intent(this, MainActivity::class.java)
|
||||
answerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
@ -288,22 +314,114 @@ class BaresipService: Service() {
|
||||
rejectIntent.putExtra("callp", callp)
|
||||
val rejectPendingIntent = PendingIntent.getActivity(this,
|
||||
1, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
/* view.setOnClickPendingIntent(R.id.answerButton, answerPendingIntent)
|
||||
view.setOnClickPendingIntent(R.id.rejectButton, rejectPendingIntent)
|
||||
cnb.setCustomBigContentView(view) */
|
||||
cnb.addAction(R.drawable.ic_stat, "Answer", answerPendingIntent)
|
||||
cnb.addAction(R.drawable.ic_stat, "Reject", rejectPendingIntent)
|
||||
nm.notify(CALL_NOTIFICATION_ID, cnb.build())
|
||||
}
|
||||
}
|
||||
"call established", "call closed" -> {
|
||||
"call established" -> {
|
||||
nm.cancel(CALL_NOTIFICATION_ID)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.w(LOG_TAG, "Established AoR $aor call $callp is not found")
|
||||
return
|
||||
}
|
||||
Log.d("Baresip", "AoR $aor call $callp established")
|
||||
call.status = "connected"
|
||||
call.onhold = false
|
||||
call.security = R.drawable.box_red
|
||||
CallHistory.add(CallHistory(aor, call.peerURI, call.dir, true))
|
||||
CallHistory.save(filesPath)
|
||||
call.hasHistory = true
|
||||
if (rtTimer != null) {
|
||||
rtTimer!!.cancel()
|
||||
rtTimer = null
|
||||
if (rt.isPlaying) rt.stop()
|
||||
}
|
||||
am.mode = AudioManager.MODE_IN_COMMUNICATION
|
||||
requestAudioFocus( AudioManager.STREAM_VOICE_CALL)
|
||||
am.isSpeakerphoneOn = false
|
||||
}
|
||||
"call transfer" -> {
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.d("Baresip","AoR $aor call $callp to be transferred is not found")
|
||||
return
|
||||
}
|
||||
if (!Utils.isVisible()) {
|
||||
val cnb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
|
||||
Utils.aorDomain(aor))
|
||||
val title = "Call transfer request to $target"
|
||||
cnb.setSmallIcon(R.drawable.ic_stat)
|
||||
.setColor(0x0ca1fd)
|
||||
.setContentIntent(npi)
|
||||
.setDefaults(Notification.DEFAULT_SOUND)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle(title)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
cnb.setVibrate(LongArray(0))
|
||||
.setVisibility(VISIBILITY_PRIVATE)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
}
|
||||
val acceptIntent = Intent(this, MainActivity::class.java)
|
||||
acceptIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
acceptIntent.putExtra("action", "transfer")
|
||||
acceptIntent.putExtra("uap", uap)
|
||||
acceptIntent.putExtra("callp", callp)
|
||||
acceptIntent.putExtra("uri", ev[1])
|
||||
val acceptPendingIntent = PendingIntent.getActivity(this,
|
||||
0, acceptIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val rejectIntent = Intent(this, MainActivity::class.java)
|
||||
rejectIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
rejectIntent.putExtra("action", "deny")
|
||||
rejectIntent.putExtra("callp", callp)
|
||||
val rejectPendingIntent = PendingIntent.getActivity(this,
|
||||
1, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
cnb.addAction(R.drawable.ic_stat, "Accept", acceptPendingIntent)
|
||||
cnb.addAction(R.drawable.ic_stat, "Deny", rejectPendingIntent)
|
||||
nm.notify(CALL_NOTIFICATION_ID, cnb.build())
|
||||
return
|
||||
}
|
||||
}
|
||||
"call closed" -> {
|
||||
nm.cancel(CALL_NOTIFICATION_ID)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.d("Baresip","AoR $aor call $callp that is closed is not found")
|
||||
return
|
||||
}
|
||||
Log.d("Baresip", "AoR $aor call $callp is closed")
|
||||
stopRinging()
|
||||
calls.remove(call)
|
||||
if (!call.hasHistory) {
|
||||
CallHistory.add(CallHistory(aor, call.peerURI, call.dir, false))
|
||||
CallHistory.save(filesPath)
|
||||
if (call.dir == "in") ua.account.missedCalls = true
|
||||
}
|
||||
if (Call.calls().size == 0) {
|
||||
am.mode = AudioManager.MODE_NORMAL
|
||||
} else {
|
||||
val uaCalls = Call.uaCalls(ua, "")
|
||||
if (uaCalls.size > 0)
|
||||
Api.call_start_audio(uaCalls[uaCalls.size - 1].callp)
|
||||
}
|
||||
if (am.isSpeakerphoneOn) am.isSpeakerphoneOn = false
|
||||
if (audioFocused) abandonAudioFocus()
|
||||
}
|
||||
"transfer failed" -> {
|
||||
Log.d(LOG_TAG, "AoR $aor hanging up call $callp with ${ev[1]}")
|
||||
Api.ua_hangup(uap, callp, 0, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newEvent == null) newEvent = event
|
||||
val intent = Intent("service event")
|
||||
intent.putExtra("event", event)
|
||||
intent.putExtra("event", newEvent)
|
||||
intent.putExtra("params", arrayListOf(uap, callp))
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
}
|
||||
@ -316,25 +434,29 @@ class BaresipService: Service() {
|
||||
} catch (e: Exception) {
|
||||
Log.e(LOG_TAG, "UTF-8 decode failed")
|
||||
}
|
||||
Log.d(LOG_TAG, "Message event $uap/$peer/$s")
|
||||
Log.d(LOG_TAG, "Message event for $uap from $peer")
|
||||
val ua = UserAgent.find(uap)
|
||||
if (ua == null) {
|
||||
Log.w(LOG_TAG, "messageEvent did not find ua $uap")
|
||||
return
|
||||
}
|
||||
val timeStamp = System.currentTimeMillis().toString()
|
||||
if (!Utils.isVisible()) {
|
||||
val cnb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val sender = Utils.friendlyUri(ContactsActivity.contactName(peer),
|
||||
Utils.aorDomain(ua.account.aor))
|
||||
cnb.setSmallIcon(R.drawable.ic_stat)
|
||||
.setColor(0x0ca1fd)
|
||||
.setContentIntent(npi)
|
||||
.setDefaults(Notification.DEFAULT_SOUND)
|
||||
.setAutoCancel(true)
|
||||
.setContentTitle("Message from ${ContactsActivity.contactName(peer)}")
|
||||
.setContentTitle("Message from $sender")
|
||||
.setContentText(s)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
cnb.setVibrate(LongArray(0))
|
||||
.setVisibility(VISIBILITY_PRIVATE)
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
}
|
||||
/* val view = RemoteViews(getPackageName(), R.layout.call_notification)
|
||||
view.setTextViewText(R.id.callFrom, "Call from ${Api.call_peeruri(callp)}")
|
||||
cnb.setContent(view) */
|
||||
val replyIntent = Intent(this, MainActivity::class.java)
|
||||
replyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
@ -359,9 +481,6 @@ class BaresipService: Service() {
|
||||
deleteIntent.putExtra("time", timeStamp)
|
||||
val deletePendingIntent = PendingIntent.getActivity(this,
|
||||
2, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
/* view.setOnClickPendingIntent(R.id.answerButton, answerPendingIntent)
|
||||
view.setOnClickPendingIntent(R.id.rejectButton, rejectPendingIntent)
|
||||
cnb.setCustomBigContentView(view) */
|
||||
cnb.addAction(R.drawable.ic_stat, "Reply", replyPendingIntent)
|
||||
cnb.addAction(R.drawable.ic_stat, "Save", savePendingIntent)
|
||||
cnb.addAction(R.drawable.ic_stat, "Delete", deletePendingIntent)
|
||||
@ -385,28 +504,28 @@ class BaresipService: Service() {
|
||||
@Keep
|
||||
fun stopped() {
|
||||
Log.d(LOG_TAG, "got event 'stopped'")
|
||||
IS_SERVICE_RUNNING = false
|
||||
isServiceRunning = false
|
||||
val intent = Intent("service event")
|
||||
intent.putExtra("event", "stopped")
|
||||
intent.putExtra("params", arrayListOf<String>())
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
stopForeground(true)
|
||||
stopSelf()
|
||||
if (RESTARTING) restart()
|
||||
if (restarting) restart()
|
||||
}
|
||||
|
||||
private fun updateStatusNotification() {
|
||||
val contentView = RemoteViews(getPackageName(), R.layout.status_notification)
|
||||
for (i: Int in 0 .. 5) {
|
||||
val resID = resources.getIdentifier("status$i", "id", packageName)
|
||||
if (i < MainActivity.images.size) {
|
||||
contentView.setImageViewResource(resID, MainActivity.images[i])
|
||||
if (i < status.size) {
|
||||
contentView.setImageViewResource(resID, status[i])
|
||||
contentView.setViewVisibility(resID, View.VISIBLE)
|
||||
} else {
|
||||
contentView.setViewVisibility(resID, View.INVISIBLE)
|
||||
}
|
||||
}
|
||||
if (MainActivity.images.size > 4)
|
||||
if (status.size > 4)
|
||||
contentView.setViewVisibility(R.id.etc, View.VISIBLE)
|
||||
else
|
||||
contentView.setViewVisibility(R.id.etc, View.INVISIBLE)
|
||||
@ -414,11 +533,78 @@ class BaresipService: Service() {
|
||||
nm.notify(STATUS_NOTIFICATION_ID, snb.build())
|
||||
}
|
||||
|
||||
private fun requestAudioFocus(streamType: Int) {
|
||||
val res: Int
|
||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) && (audioFocusRequest == null)) {
|
||||
val playbackAttributes = AudioAttributes.Builder()
|
||||
.setLegacyStreamType(streamType)
|
||||
.build()
|
||||
@TargetApi(26)
|
||||
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||
.setAudioAttributes(playbackAttributes)
|
||||
.build()
|
||||
@TargetApi(26)
|
||||
res = am.requestAudioFocus(audioFocusRequest)
|
||||
if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d("Baresip", "Audio focus granted")
|
||||
} else {
|
||||
Log.d("Baresip", "Audio focus denied")
|
||||
audioFocusRequest = null
|
||||
}
|
||||
} else {
|
||||
res = am.requestAudioFocus(null, streamType,
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||
if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d("Baresip", "Audio focus granted")
|
||||
audioFocused = true
|
||||
} else {
|
||||
Log.d("Baresip", "Audio focus denied")
|
||||
audioFocused = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun abandonAudioFocus() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (audioFocusRequest != null) {
|
||||
am.abandonAudioFocusRequest(audioFocusRequest)
|
||||
audioFocusRequest = null
|
||||
}
|
||||
} else {
|
||||
if (audioFocused) {
|
||||
am.abandonAudioFocus(null)
|
||||
audioFocused = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startRinging() {
|
||||
am.mode = AudioManager.MODE_RINGTONE
|
||||
requestAudioFocus(AudioManager.STREAM_RING)
|
||||
rt.play()
|
||||
rtTimer = Timer()
|
||||
rtTimer!!.scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
if (!rt.isPlaying()) {
|
||||
rt.play()
|
||||
}
|
||||
}
|
||||
}, 1000 * 1, 1000 * 1)
|
||||
}
|
||||
|
||||
private fun stopRinging() {
|
||||
if (rtTimer != null) {
|
||||
rtTimer!!.cancel()
|
||||
rtTimer = null
|
||||
if (rt.isPlaying) rt.stop()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
MainActivity.uas.clear()
|
||||
MainActivity.images.clear()
|
||||
MainActivity.history.clear()
|
||||
MainActivity.messages.clear()
|
||||
uas.clear()
|
||||
status.clear()
|
||||
history.clear()
|
||||
messages.clear()
|
||||
try {
|
||||
unregisterReceiver(nr)
|
||||
} catch (e: Exception) {
|
||||
@ -427,15 +613,15 @@ class BaresipService: Service() {
|
||||
if (this::nm.isInitialized) nm.cancelAll()
|
||||
if (this::wl.isInitialized && wl.isHeld) wl.release()
|
||||
if (this::fl.isInitialized && fl.isHeld) fl.release()
|
||||
if (IS_SERVICE_RUNNING) {
|
||||
if (isServiceRunning) {
|
||||
baresipStop(forceStop)
|
||||
if (!forceStop) forceStop = true
|
||||
} else if (RESTARTING)
|
||||
} else if (restarting)
|
||||
restart()
|
||||
}
|
||||
|
||||
private fun restart() {
|
||||
RESTARTING = false
|
||||
restarting = false
|
||||
val broadcastIntent = Intent("com.tutpro.baresip.Restart")
|
||||
sendBroadcast(broadcastIntent)
|
||||
}
|
||||
@ -445,16 +631,27 @@ class BaresipService: Service() {
|
||||
|
||||
companion object {
|
||||
|
||||
var IS_SERVICE_RUNNING = false
|
||||
var RESTARTING = false
|
||||
val STATUS_NOTIFICATION_ID = 101
|
||||
val CALL_NOTIFICATION_ID = 102
|
||||
val MESSAGE_NOTIFICATION_ID = 103
|
||||
|
||||
val DEFAULT_CHANNEL_ID = "com.tutpro.baresip.default"
|
||||
val HIGH_CHANNEL_ID = "com.tutpro.baresip.high"
|
||||
|
||||
var isServiceRunning = false
|
||||
var disconnected = false
|
||||
var forceStop = false
|
||||
|
||||
var uas = ArrayList<UserAgent>()
|
||||
var status = ArrayList<Int>()
|
||||
var calls = ArrayList<Call>()
|
||||
var history = ArrayList<CallHistory>()
|
||||
var messages = ArrayList<Message>()
|
||||
var contacts = ArrayList<Contact>()
|
||||
|
||||
var audioFocused = false
|
||||
var audioFocusRequest: AudioFocusRequest? = null
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@ -13,6 +13,10 @@ class Call(val callp: String, val ua: UserAgent, val peerURI: String, val dir: S
|
||||
|
||||
companion object {
|
||||
|
||||
fun calls(): ArrayList<Call> {
|
||||
return BaresipService.calls
|
||||
}
|
||||
|
||||
fun calls(calls: ArrayList<Call>, dir: String): ArrayList<Call> {
|
||||
val result = ArrayList<Call>()
|
||||
for (i in calls.indices) {
|
||||
@ -21,17 +25,24 @@ class Call(val callp: String, val ua: UserAgent, val peerURI: String, val dir: S
|
||||
return result
|
||||
}
|
||||
|
||||
fun uaCalls(calls: ArrayList<Call>, ua: UserAgent, dir: String): ArrayList<Call> {
|
||||
fun calls(dir: String): ArrayList<Call> {
|
||||
val result = ArrayList<Call>()
|
||||
for (i in calls.indices)
|
||||
if ((calls[i].ua == ua) && ((dir == "") || calls[i].dir == dir)) result.add(calls[i])
|
||||
for (c in BaresipService.calls) {
|
||||
if (c.dir == dir) result.add(c)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun find(calls: ArrayList<Call>, callp: String): Call? {
|
||||
for (c in calls) {
|
||||
fun uaCalls(ua: UserAgent, dir: String): ArrayList<Call> {
|
||||
val result = ArrayList<Call>()
|
||||
for (c in BaresipService.calls)
|
||||
if ((c.ua == ua) && ((dir == "") || c.dir == dir)) result.add(c)
|
||||
return result
|
||||
}
|
||||
|
||||
fun find(callp: String): Call? {
|
||||
for (c in BaresipService.calls)
|
||||
if (c.callp == callp) return c
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import java.io.Serializable
|
||||
import android.util.Log
|
||||
import java.io.*
|
||||
import java.util.ArrayList
|
||||
import java.util.GregorianCalendar
|
||||
|
||||
class CallHistory(val aor: String, val peerURI: String, val direction: String,
|
||||
@ -10,29 +12,72 @@ class CallHistory(val aor: String, val peerURI: String, val direction: String,
|
||||
|
||||
companion object {
|
||||
|
||||
fun aorHistory(history: ArrayList<CallHistory>, aor: String): Int {
|
||||
const val CALL_HISTORY_SIZE = 100
|
||||
|
||||
fun history(): ArrayList<CallHistory> {
|
||||
return BaresipService.history
|
||||
}
|
||||
|
||||
fun historySet(history: ArrayList<CallHistory>) {
|
||||
BaresipService.history = history
|
||||
}
|
||||
|
||||
fun add(history: CallHistory) {
|
||||
BaresipService.history.add(history)
|
||||
if (aorHistorySize(history.aor) > CALL_HISTORY_SIZE) {
|
||||
var i = 0
|
||||
for (h in BaresipService.history)
|
||||
if (h.aor == history.aor)
|
||||
break
|
||||
else
|
||||
i++
|
||||
BaresipService.history.removeAt(i)
|
||||
}
|
||||
}
|
||||
|
||||
fun aorHistorySize(aor: String): Int {
|
||||
var size = 0;
|
||||
for (h in history) {
|
||||
for (h in BaresipService.history) {
|
||||
if (h.aor == aor) size++
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
fun aorRemoveHistory(history: ArrayList<CallHistory>, aor: String) {
|
||||
for (h in history) {
|
||||
if (h.aor == aor) {
|
||||
history.remove(h)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun aorLatestHistory(history: ArrayList<CallHistory>, aor: String): CallHistory? {
|
||||
for (h in history.reversed())
|
||||
fun aorLatestHistory(aor: String): CallHistory? {
|
||||
for (h in BaresipService.history.reversed())
|
||||
if (h.aor == aor) return h
|
||||
return null
|
||||
}
|
||||
|
||||
fun save(path: String) {
|
||||
val file = File(path, "history")
|
||||
try {
|
||||
val fos = FileOutputStream(file)
|
||||
val oos = ObjectOutputStream(fos)
|
||||
oos.writeObject(history())
|
||||
oos.close()
|
||||
fos.close()
|
||||
} catch (e: IOException) {
|
||||
Log.w("Baresip", "OutputStream exception: " + e.toString())
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun restore(path: String) {
|
||||
val file = File(path + "/history")
|
||||
if (file.exists()) {
|
||||
try {
|
||||
val fis = FileInputStream(file)
|
||||
val ois = ObjectInputStream(fis)
|
||||
historySet(ois.readObject() as ArrayList<CallHistory>)
|
||||
ois.close()
|
||||
fis.close()
|
||||
} catch (e: Exception) {
|
||||
Log.w("Baresip", "InputStream exception: - " + e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,12 +11,6 @@ import android.view.MenuItem
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.ArrayList
|
||||
@ -120,7 +114,12 @@ class CallsActivity : AppCompatActivity() {
|
||||
true
|
||||
}
|
||||
|
||||
ua!!.account.missedCalls = false
|
||||
ua.account.missedCalls = false
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
CallHistory.save(applicationContext.filesDir.absolutePath)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
@ -137,8 +136,8 @@ class CallsActivity : AppCompatActivity() {
|
||||
|
||||
private fun aorGenerateHistory(aor: String) {
|
||||
uaHistory.clear()
|
||||
for (i in MainActivity.history.indices.reversed()) {
|
||||
val h = MainActivity.history[i]
|
||||
for (i in CallHistory.history().indices.reversed()) {
|
||||
val h = CallHistory.history()[i]
|
||||
if (h.aor == aor) {
|
||||
var direction: Int
|
||||
if (h.direction == "in")
|
||||
@ -171,7 +170,7 @@ class CallsActivity : AppCompatActivity() {
|
||||
|
||||
private fun removeUaHistoryAt(i: Int) {
|
||||
for (index in uaHistory[i].indexes)
|
||||
MainActivity.history.removeAt(index)
|
||||
CallHistory.history().removeAt(index)
|
||||
uaHistory.removeAt(i)
|
||||
}
|
||||
|
||||
@ -182,38 +181,4 @@ class CallsActivity : AppCompatActivity() {
|
||||
now.get(Calendar.DAY_OF_MONTH) == time.get(Calendar.DAY_OF_MONTH)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun saveHistory() {
|
||||
val file = File(MainActivity.filesPath, "history")
|
||||
try {
|
||||
val fos = FileOutputStream(file)
|
||||
val oos = ObjectOutputStream(fos)
|
||||
oos.writeObject(MainActivity.history)
|
||||
oos.close()
|
||||
fos.close()
|
||||
} catch (e: IOException) {
|
||||
Log.w("Baresip", "OutputStream exception: " + e.toString())
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun restoreHistory(path: String) {
|
||||
val file = File(path + "/history")
|
||||
if (file.exists()) {
|
||||
try {
|
||||
val fis = FileInputStream(file)
|
||||
val ois = ObjectInputStream(fis)
|
||||
@SuppressWarnings("unchecked")
|
||||
MainActivity.history = ois.readObject() as ArrayList<CallHistory>
|
||||
Log.d("Baresip", "Restored History of ${MainActivity.history.size} entries")
|
||||
ois.close()
|
||||
fis.close()
|
||||
} catch (e: Exception) {
|
||||
Log.w("Baresip", "InputStream exception: - " + e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
startActivityForResult(i, MainActivity.CONTACT_CODE)
|
||||
}
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
MainActivity.messages.remove(chatMessages[pos])
|
||||
Message.messages().remove(chatMessages[pos])
|
||||
chatMessages.removeAt(pos)
|
||||
mlAdapter.notifyDataSetChanged()
|
||||
if (chatMessages.size == 0) {
|
||||
@ -118,10 +118,10 @@ class ChatActivity : AppCompatActivity() {
|
||||
imm.hideSoftInputFromWindow(newMessage.windowToken, 0)
|
||||
val time = System.currentTimeMillis()
|
||||
val msg = Message(aor, peerUri, R.drawable.arrow_up_yellow, msgText, time,true)
|
||||
MainActivity.messages.add(msg)
|
||||
Message.add(msg)
|
||||
chatMessages.add(msg)
|
||||
mlAdapter.notifyDataSetChanged()
|
||||
if (message_send(ua!!.uap, peerUri, msgText, time.toString()) != 0)
|
||||
if (Api.message_send(ua.uap, peerUri, msgText, time.toString()) != 0)
|
||||
Toast.makeText(getApplicationContext(), "Sending of message failed!",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
else
|
||||
@ -146,7 +146,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
ChatsActivity.saveMessages()
|
||||
ChatsActivity.saveMessages(applicationContext.filesDir.absolutePath)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
intent.putExtra("action", "call")
|
||||
intent.putExtra("uap", ua.uap)
|
||||
intent.putExtra("peer", ContactsActivity.contactName(peerUri))
|
||||
intent.putExtra("peer", peerUri)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
|
||||
private fun uaPeerMessages(aor: String, peerUri: String): ArrayList<Message> {
|
||||
val res = ArrayList<Message>()
|
||||
for (m in MainActivity.messages)
|
||||
for (m in Message.messages())
|
||||
if ((m.aor == aor) && (m.peerUri == peerUri)) res.add(m)
|
||||
return res
|
||||
}
|
||||
@ -203,6 +203,4 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
external fun message_send(uap: String, peer_uri: String, message: String, time: String): Int
|
||||
|
||||
}
|
||||
|
||||
@ -30,6 +30,8 @@ class ChatsActivity: AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_chats)
|
||||
|
||||
filesPath = applicationContext.filesDir.absolutePath
|
||||
|
||||
listView = findViewById(R.id.chats) as ListView
|
||||
plusButton = findViewById(R.id.plusButton) as ImageButton
|
||||
|
||||
@ -67,13 +69,13 @@ class ChatsActivity: AppCompatActivity() {
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
val peerUri = uaMessages[pos].peerUri
|
||||
val msgs = ArrayList<Message>()
|
||||
for (m in MainActivity.messages)
|
||||
for (m in Message.messages())
|
||||
if ((m.aor != aor) || (m.peerUri != peerUri))
|
||||
msgs.add(m)
|
||||
else
|
||||
clAdapter.remove(m)
|
||||
clAdapter.notifyDataSetChanged()
|
||||
MainActivity.messages = msgs
|
||||
Message.messages(msgs)
|
||||
uaMessages = uaMessages(aor)
|
||||
}
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
@ -84,8 +86,8 @@ class ChatsActivity: AppCompatActivity() {
|
||||
val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat)
|
||||
val peer = ContactsActivity.contactName(uaMessages[pos].peerUri)
|
||||
if (peer.startsWith("sip:"))
|
||||
builder.setMessage("Do you want to delete chat with peer '" +
|
||||
"${Utils.friendlyUri(peer, Utils.aorDomain(aor))}' or add peer to contacts?")
|
||||
builder.setMessage("Do you want to delete chat with peer " +
|
||||
"${Utils.friendlyUri(peer, Utils.aorDomain(aor))} or add peer to contacts?")
|
||||
.setPositiveButton("Cancel", dialogClickListener)
|
||||
.setNegativeButton("Delete Chat", dialogClickListener)
|
||||
.setNeutralButton("Add Contact", dialogClickListener)
|
||||
@ -101,7 +103,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
peerUri = findViewById(R.id.peerUri) as AutoCompleteTextView
|
||||
peerUri.threshold = 2
|
||||
peerUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
ContactsActivity.contacts.map{Contact -> Contact.name}))
|
||||
Contact.contacts().map{Contact -> Contact.name}))
|
||||
|
||||
plusButton.setOnClickListener {
|
||||
val uriText = peerUri.text.toString().trim()
|
||||
@ -143,7 +145,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
saveMessages()
|
||||
saveMessages(applicationContext.filesDir.absolutePath)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
@ -171,7 +173,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
|
||||
private fun uaMessages(aor: String) : ArrayList<Message> {
|
||||
val res = ArrayList<Message>()
|
||||
for (m in MainActivity.messages.reversed()) {
|
||||
for (m in Message.messages().reversed()) {
|
||||
if (m.aor != aor) continue
|
||||
var found = false
|
||||
for (r in res)
|
||||
@ -186,32 +188,34 @@ class ChatsActivity: AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
|
||||
fun saveUaMessage(aor: String, time: Long) {
|
||||
for (i in MainActivity.messages.indices.reversed())
|
||||
if ((MainActivity.messages[i].aor == aor) &&
|
||||
(MainActivity.messages[i].timeStamp == time)) {
|
||||
MainActivity.messages[i].new = false
|
||||
saveMessages()
|
||||
var filesPath = ""
|
||||
|
||||
fun saveUaMessage(aor: String, time: Long, path: String) {
|
||||
for (i in Message.messages().indices.reversed())
|
||||
if ((Message.messages()[i].aor == aor) &&
|
||||
(Message.messages()[i].timeStamp == time)) {
|
||||
Message.messages()[i].new = false
|
||||
saveMessages(path)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteUaMessage(aor: String, time: Long) {
|
||||
for (i in MainActivity.messages.indices.reversed())
|
||||
if ((MainActivity.messages[i].aor == aor) &&
|
||||
(MainActivity.messages[i].timeStamp == time)) {
|
||||
MainActivity.messages.removeAt(i)
|
||||
saveMessages()
|
||||
fun deleteUaMessage(aor: String, time: Long, path: String) {
|
||||
for (i in Message.messages().indices.reversed())
|
||||
if ((Message.messages()[i].aor == aor) &&
|
||||
(Message.messages()[i].timeStamp == time)) {
|
||||
Message.messages().removeAt(i)
|
||||
saveMessages(path)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fun saveMessages() {
|
||||
val file = File(MainActivity.filesPath, "messages")
|
||||
fun saveMessages(path: String = filesPath) {
|
||||
val file = File(path, "messages")
|
||||
try {
|
||||
val fos = FileOutputStream(file)
|
||||
val oos = ObjectOutputStream(fos)
|
||||
oos.writeObject(MainActivity.messages)
|
||||
oos.writeObject(Message.messages())
|
||||
oos.close()
|
||||
fos.close()
|
||||
} catch (e: IOException) {
|
||||
@ -220,15 +224,13 @@ class ChatsActivity: AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
fun restoreMessages(path: String) {
|
||||
fun restoreMessages(path: String = filesPath) {
|
||||
val file = File(path, "messages")
|
||||
if (file.exists()) {
|
||||
try {
|
||||
val fis = FileInputStream(file)
|
||||
val ois = ObjectInputStream(fis)
|
||||
@SuppressWarnings("unchecked")
|
||||
MainActivity.messages = ois.readObject() as ArrayList<Message>
|
||||
Log.d("Baresip", "Restored ${MainActivity.messages.size} messages")
|
||||
Message.messages(ois.readObject() as ArrayList<Message>)
|
||||
ois.close()
|
||||
fis.close()
|
||||
} catch (e: Exception) {
|
||||
@ -236,5 +238,6 @@ class ChatsActivity: AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,16 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
class Contact(var name: String, var uri: String)
|
||||
import java.util.ArrayList
|
||||
|
||||
class Contact(var name: String, var uri: String) {
|
||||
|
||||
companion object {
|
||||
|
||||
const val CONTACTS_SIZE = 100
|
||||
|
||||
fun contacts(): ArrayList<Contact> {
|
||||
return BaresipService.contacts
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -37,10 +37,10 @@ class ContactActivity : AppCompatActivity() {
|
||||
}
|
||||
} else {
|
||||
index = intent.extras.getInt("index")
|
||||
val name = ContactsActivity.contacts[index].name
|
||||
val name = Contact.contacts()[index].name
|
||||
setTitle(name)
|
||||
nameView.setText(name)
|
||||
uriView.setText(ContactsActivity.contacts[index].uri)
|
||||
uriView.setText(Contact.contacts()[index].uri)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class ContactActivity : AppCompatActivity() {
|
||||
"Invalid contact name: $newName")
|
||||
return false
|
||||
}
|
||||
if ((new || (ContactsActivity.contacts[index].name != newName)) &&
|
||||
if ((new || (Contact.contacts()[index].name != newName)) &&
|
||||
ContactsActivity.nameExists(newName)) {
|
||||
Utils.alertView(this, "Notice",
|
||||
"Contact $newName already exists")
|
||||
@ -73,20 +73,27 @@ class ContactActivity : AppCompatActivity() {
|
||||
var newUri = uriView.text.toString().trim()
|
||||
if (!newUri.startsWith("<")) {
|
||||
if (!newUri.startsWith("sip:")) newUri = "sip:$newUri"
|
||||
if (!Utils.checkSipUri(newUri)) {
|
||||
if (!Utils.checkAorUri(newUri)) {
|
||||
Utils.alertView(this, "Notice","Invalid contact URI: $newUri")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (new) {
|
||||
ContactsActivity.contacts.add(Contact(newName, newUri))
|
||||
if (Contact.contacts().size >= Contact.CONTACTS_SIZE) {
|
||||
Utils.alertView(this,
|
||||
"Notice", "Maximum number of contacts exceeded")
|
||||
return true
|
||||
} else {
|
||||
Contact.contacts().add(Contact(newName, newUri))
|
||||
}
|
||||
} else {
|
||||
ContactsActivity.contacts[index].uri = newUri
|
||||
ContactsActivity.contacts[index].name = newName
|
||||
Contact.contacts()[index].uri = newUri
|
||||
Contact.contacts()[index].name = newName
|
||||
}
|
||||
ContactsActivity.contacts.sortBy { Contact -> Contact.name }
|
||||
ContactsActivity.saveContacts()
|
||||
|
||||
Contact.contacts().sortBy { Contact -> Contact.name }
|
||||
ContactsActivity.saveContacts(applicationContext.filesDir.absolutePath)
|
||||
|
||||
i.putExtra("name", newName)
|
||||
setResult(Activity.RESULT_OK, i)
|
||||
@ -104,8 +111,10 @@ class ContactActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal var index = 0
|
||||
internal var new = false
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
|
||||
Log.e("Baresip", "onClickListener did not find AoR $aor")
|
||||
} else {
|
||||
i.putExtra("uap", ua.uap)
|
||||
i.putExtra("peer", ContactsActivity.contacts[pos].uri)
|
||||
i.putExtra("peer", Contact.contacts()[pos].uri)
|
||||
(cxt as Activity).startActivity(i)
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
|
||||
}
|
||||
val builder = AlertDialog.Builder(cxt, R.style.Theme_AppCompat)
|
||||
builder.setMessage("Do you want to call or send message to '" +
|
||||
"${ContactsActivity.contacts[pos].name}'?")
|
||||
"${Contact.contacts()[pos].name}'?")
|
||||
.setNeutralButton("Call", dialogClickListener)
|
||||
.setNegativeButton("Send Message", dialogClickListener)
|
||||
.setPositiveButton("Cancel", dialogClickListener)
|
||||
@ -66,7 +66,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
ContactsActivity.contacts.removeAt(pos)
|
||||
Contact.contacts().removeAt(pos)
|
||||
ContactsActivity.saveContacts()
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
@ -76,7 +76,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList<C
|
||||
}
|
||||
val builder = AlertDialog.Builder(cxt, R.style.Theme_AppCompat)
|
||||
builder.setMessage("Do you want to delete contact '" +
|
||||
"${ContactsActivity.contacts[pos].name}'?")
|
||||
"${Contact.contacts()[pos].name}'?")
|
||||
.setPositiveButton("Cancel", dialogClickListener)
|
||||
.setNegativeButton("Delete Contact", dialogClickListener)
|
||||
.show()
|
||||
|
||||
@ -10,7 +10,6 @@ import android.widget.ImageButton
|
||||
import android.widget.ListView
|
||||
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
|
||||
class ContactsActivity : AppCompatActivity() {
|
||||
|
||||
@ -20,22 +19,29 @@ class ContactsActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_contacts)
|
||||
|
||||
filesPath = applicationContext.filesDir.absolutePath
|
||||
|
||||
val listView = findViewById(R.id.contacts) as ListView
|
||||
|
||||
Log.d("Baresip", "Got ${contacts.size} contacts")
|
||||
val aor = intent.extras.getString("aor")
|
||||
clAdapter = ContactListAdapter(this, contacts, aor)
|
||||
clAdapter = ContactListAdapter(this, Contact.contacts(), aor)
|
||||
listView.adapter = clAdapter
|
||||
listView.isLongClickable = true
|
||||
|
||||
val plusButton = findViewById(R.id.plusButton) as ImageButton
|
||||
plusButton.setOnClickListener {
|
||||
val i = Intent(this, ContactActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putBoolean("new", true)
|
||||
b.putString("uri", "")
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, MainActivity.CONTACT_CODE)
|
||||
if (Contact.contacts().size >= Contact.CONTACTS_SIZE) {
|
||||
Utils.alertView(this, "Notice",
|
||||
"Your maximum number of contacts " +
|
||||
"(${Contact.CONTACTS_SIZE}) has been exceeded.")
|
||||
} else {
|
||||
val i = Intent(this, ContactActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putBoolean("new", true)
|
||||
b.putString("uri", "")
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, MainActivity.CONTACT_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,34 +70,32 @@ class ContactsActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
|
||||
var contacts = ArrayList<Contact>()
|
||||
internal var filesPath = ""
|
||||
|
||||
fun saveContacts() {
|
||||
fun saveContacts(path: String = filesPath) {
|
||||
var contents = ""
|
||||
for (c in contacts)
|
||||
for (c in Contact.contacts())
|
||||
contents += "\"${c.name}\" ${c.uri}\n"
|
||||
val path = MainActivity.filesPath + "/contacts"
|
||||
Utils.putFileContents(File(path), contents)
|
||||
Log.d("Baresip", "Saved contacts '${contents}' to '$path")
|
||||
Utils.putFileContents(File(path + "/contacts"), contents)
|
||||
}
|
||||
|
||||
fun restoreContacts(path: String) {
|
||||
fun restoreContacts(path: String = filesPath) {
|
||||
val content = Utils.getFileContents(File(path + "/contacts"))
|
||||
Api.contacts_remove()
|
||||
contacts.clear()
|
||||
Contact.contacts().clear()
|
||||
content.lines().forEach {
|
||||
val parts = it.split("\"")
|
||||
if (parts.size == 3) {
|
||||
val name = parts[1]
|
||||
val uri = parts[2].trim()
|
||||
Api.contact_add("\"$name\" $uri")
|
||||
contacts.add(Contact(name, uri))
|
||||
Contact.contacts().add(Contact(name, uri))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun findContactURI(name: String): String {
|
||||
for (c in contacts)
|
||||
for (c in Contact.contacts())
|
||||
if (c.name == name)
|
||||
return c.uri.removePrefix("<")
|
||||
.replaceAfter(">", "")
|
||||
@ -100,13 +104,13 @@ class ContactsActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun nameExists(name: String): Boolean {
|
||||
for (c in contacts)
|
||||
for (c in Contact.contacts())
|
||||
if (c.name.equals(name, ignoreCase = true)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun contactName(uri: String): String {
|
||||
for (c in contacts)
|
||||
for (c in Contact.contacts())
|
||||
if ((Utils.uriUserPart(c.uri) == Utils.uriUserPart(uri)) &&
|
||||
(Utils.uriHostPart(c.uri) == Utils.uriHostPart(uri)))
|
||||
return c.name
|
||||
|
||||
@ -7,10 +7,10 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
@ -27,8 +27,7 @@ class EditConfigActivity : AppCompatActivity() {
|
||||
setContentView(R.layout.activity_edit_config)
|
||||
|
||||
editText = findViewById(R.id.editConfig) as EditText
|
||||
path = applicationContext.filesDir.absolutePath + "/config"
|
||||
// path = "/sdcard/baresip/config";
|
||||
path = "${applicationContext.filesDir.absolutePath}/config"
|
||||
file = File(path!!)
|
||||
var content: String
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.app.NotificationManager
|
||||
import android.content.*
|
||||
import android.support.v4.app.ActivityCompat
|
||||
@ -15,22 +14,18 @@ import android.view.MenuItem
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.media.*
|
||||
import android.os.Build
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.support.v7.view.menu.ActionMenuItemView
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.*
|
||||
import android.view.*
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
lateinit var appContext: Context
|
||||
internal lateinit var layout: RelativeLayout
|
||||
internal lateinit var baresipService: Intent
|
||||
internal lateinit var callTitle: TextView
|
||||
@ -51,7 +46,6 @@ class MainActivity : AppCompatActivity() {
|
||||
internal lateinit var aorSpinner: Spinner
|
||||
internal lateinit var am: AudioManager
|
||||
internal lateinit var rt: Ringtone
|
||||
internal var rtTimer: Timer? = null
|
||||
internal lateinit var imm: InputMethodManager
|
||||
internal lateinit var nm: NotificationManager
|
||||
internal lateinit var serviceEventReceiver: BroadcastReceiver
|
||||
@ -69,9 +63,15 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
filesPath = applicationContext.filesDir.absolutePath
|
||||
if (ContextCompat.checkSelfPermission(applicationContext,
|
||||
Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) {
|
||||
Toast.makeText(applicationContext,"You have not granted microphone permission.",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
finishAndRemoveTask()
|
||||
System.exit(0)
|
||||
return
|
||||
}
|
||||
|
||||
appContext = applicationContext
|
||||
layout = findViewById(R.id.mainActivityLayout) as RelativeLayout
|
||||
callTitle = findViewById(R.id.callTitle) as TextView
|
||||
callUri = findViewById(R.id.callUri) as AutoCompleteTextView
|
||||
@ -112,16 +112,16 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
aorSpinner = findViewById(R.id.AoRList)
|
||||
uaAdapter = UaSpinnerAdapter(applicationContext, uas, images)
|
||||
uaAdapter = UaSpinnerAdapter(applicationContext, UserAgent.uas(), UserAgent.status())
|
||||
aorSpinner.adapter = uaAdapter
|
||||
aorSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||
Log.d("Baresip", "aorSpinner selecting $position")
|
||||
val acc = uas[position].account
|
||||
val acc = UserAgent.uas()[position].account
|
||||
val aor = acc.aor
|
||||
val ua = uas[position]
|
||||
val ua = UserAgent.uas()[position]
|
||||
Log.d("Baresip", "Setting $aor current")
|
||||
uag_current_set(uas[position].uap)
|
||||
Api.uag_current_set(UserAgent.uas()[position].uap)
|
||||
showCall(ua)
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
@ -151,11 +151,12 @@ class MainActivity : AppCompatActivity() {
|
||||
true
|
||||
} else {
|
||||
if ((event.x - view.left) < 100) {
|
||||
val i = Intent(this, AccountActivity::class.java)
|
||||
val i = Intent(this, AccountsActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("accp", uas[aorSpinner.selectedItemPosition].account.accp)
|
||||
b.putString("accp",
|
||||
UserAgent.uas()[aorSpinner.selectedItemPosition].account.accp)
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, ACCOUNT_CODE)
|
||||
startActivityForResult(i, ACCOUNTS_CODE)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -165,11 +166,12 @@ class MainActivity : AppCompatActivity() {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
callUri.threshold = 2
|
||||
ContactsActivity.restoreContacts(applicationContext.filesDir.path)
|
||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
ContactsActivity.contacts.map{Contact -> Contact.name}))
|
||||
Contact.contacts().map{Contact -> Contact.name}))
|
||||
callUri.threshold = 2
|
||||
ContactsActivity.restoreContacts(applicationContext.filesDir.absolutePath)
|
||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
Contact.contacts().map{Contact -> Contact.name}))
|
||||
|
||||
securityButton.setOnClickListener {
|
||||
when (securityButton.tag) {
|
||||
@ -186,7 +188,8 @@ class MainActivity : AppCompatActivity() {
|
||||
unverifyDialog.setMessage("This call is SECURE and peer is VERIFIED! " +
|
||||
"Do you want to unverify the peer?")
|
||||
unverifyDialog.setPositiveButton("Unverify") { dialog, _ ->
|
||||
val calls = Call.uaCalls(calls, uas[aorSpinner.selectedItemPosition], "")
|
||||
val calls = Call.uaCalls(UserAgent.uas()[aorSpinner.selectedItemPosition],
|
||||
"")
|
||||
if (calls.size > 0) {
|
||||
if (Api.cmd_exec("zrtp_unverify " + calls[0].zid) != 0) {
|
||||
Log.w("Baresip",
|
||||
@ -207,9 +210,10 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
callButton.setOnClickListener {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
callUri.setAdapter(null)
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
if (!ONE_CALL_ONLY || calls.isEmpty()) {
|
||||
if (Call.calls().isEmpty()) {
|
||||
val uriText = callUri.text.toString().trim()
|
||||
if (uriText.length > 0) {
|
||||
var uri = ContactsActivity.findContactURI(uriText)
|
||||
@ -225,66 +229,66 @@ class MainActivity : AppCompatActivity() {
|
||||
else
|
||||
call(ua, uri)
|
||||
} else {
|
||||
val latest = CallHistory.aorLatestHistory(history, aor)
|
||||
val latest = CallHistory.aorLatestHistory(aor)
|
||||
if (latest != null)
|
||||
if (Utils.uriHostPart(latest.peerURI) == Utils.uriHostPart(aor))
|
||||
callUri.setText(Utils.uriUserPart(latest.peerURI))
|
||||
else
|
||||
callUri.setText(latest.peerURI)
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(latest.peerURI),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hangupButton.setOnClickListener {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val uaCalls = Call.uaCalls(calls, ua, "")
|
||||
val uaCalls = Call.uaCalls(ua, "")
|
||||
if (uaCalls.size > 0) {
|
||||
val callp = uaCalls[uaCalls.size - 1].callp
|
||||
Log.d("Baresip", "AoR $aor hanging up call $callp with ${callUri.text}")
|
||||
hangupButton.isEnabled = false
|
||||
ua_hangup(ua.uap, callp, 0, "")
|
||||
Api.ua_hangup(ua.uap, callp, 0, "")
|
||||
}
|
||||
}
|
||||
|
||||
answerButton.setOnClickListener {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val callp = Call.uaCalls(calls, ua,"in")[0].callp
|
||||
val callp = Call.uaCalls(ua,"in")[0].callp
|
||||
Log.d("Baresip", "AoR $aor answering call $callp from ${callUri.text}")
|
||||
answerButton.isEnabled = false
|
||||
ua_answer(ua.uap, callp)
|
||||
Api.ua_answer(ua.uap, callp)
|
||||
}
|
||||
|
||||
rejectButton.setOnClickListener {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val callp = Call.uaCalls(calls, ua,"in")[0].callp
|
||||
val callp = Call.uaCalls(ua,"in")[0].callp
|
||||
Log.d("Baresip", "AoR $aor rejecting call $callp from ${callUri.text}")
|
||||
rejectButton.isEnabled = false
|
||||
ua_hangup(ua.uap, callp, 486, "Rejected")
|
||||
Api.ua_hangup(ua.uap, callp, 486, "Rejected")
|
||||
}
|
||||
|
||||
holdButton.setOnClickListener {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
val call = Call.uaCalls(calls, ua,"")[0]
|
||||
val call = Call.uaCalls(ua,"")[0]
|
||||
if (call.onhold) {
|
||||
Log.d("Baresip", "AoR $aor resuming call ${call.callp} with ${callUri.text}")
|
||||
call_unhold(call.callp)
|
||||
Api.call_unhold(call.callp)
|
||||
call.onhold = false
|
||||
holdButton.setImageResource(R.drawable.pause)
|
||||
} else {
|
||||
Log.d("Baresip", "AoR $aor holding call ${call.callp} with ${callUri.text}")
|
||||
call_hold(call.callp)
|
||||
Api.call_hold(call.callp)
|
||||
call.onhold = true
|
||||
holdButton.setImageResource(R.drawable.play)
|
||||
}
|
||||
}
|
||||
|
||||
dtmf.tag = ArrayList<TextWatcher>()
|
||||
|
||||
voicemailButton.setOnClickListener {
|
||||
if (aorSpinner.selectedItemPosition >= 0) {
|
||||
val ua = uas[aorSpinner.selectedItemPosition]
|
||||
val ua = UserAgent.uas()[aorSpinner.selectedItemPosition]
|
||||
val acc = ua.account
|
||||
if (acc.vmUri != "") {
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
@ -317,19 +321,19 @@ class MainActivity : AppCompatActivity() {
|
||||
val i = Intent(this@MainActivity, ContactsActivity::class.java)
|
||||
val b = Bundle()
|
||||
if (aorSpinner.selectedItemPosition >= 0)
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
b.putString("aor", UserAgent.uas()[aorSpinner.selectedItemPosition].account.aor)
|
||||
else
|
||||
b.putString("aor", "")
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, CONTACTS_CODE)
|
||||
}
|
||||
|
||||
ChatsActivity.restoreMessages(applicationContext.filesDir.path)
|
||||
ChatsActivity.restoreMessages(applicationContext.filesDir.absolutePath)
|
||||
messagesButton.setOnClickListener {
|
||||
if (aorSpinner.selectedItemPosition >= 0) {
|
||||
val i = Intent(this@MainActivity, ChatsActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
b.putString("aor", UserAgent.uas()[aorSpinner.selectedItemPosition].account.aor)
|
||||
b.putString("peer", "")
|
||||
b.putBoolean("focus", false)
|
||||
i.putExtras(b)
|
||||
@ -337,12 +341,12 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
CallsActivity.restoreHistory(applicationContext.filesDir.path)
|
||||
CallHistory.restore(applicationContext.filesDir.absolutePath)
|
||||
callsButton.setOnClickListener {
|
||||
if (aorSpinner.selectedItemPosition >= 0) {
|
||||
val i = Intent(this@MainActivity, CallsActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor)
|
||||
b.putString("aor", UserAgent.uas()[aorSpinner.selectedItemPosition].account.aor)
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, CALLS_CODE)
|
||||
}
|
||||
@ -363,7 +367,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
baresipService = Intent(this@MainActivity, BaresipService::class.java)
|
||||
if (!BaresipService.IS_SERVICE_RUNNING) {
|
||||
if (!BaresipService.isServiceRunning) {
|
||||
baresipService.setAction("Start")
|
||||
startService(baresipService)
|
||||
}
|
||||
@ -372,7 +376,7 @@ class MainActivity : AppCompatActivity() {
|
||||
moveTaskToBack(true)
|
||||
|
||||
if (intent.hasExtra("action")) {
|
||||
// MainActivity was not running when call or message came in
|
||||
// MainActivity was not visible when call, message, or transfer request came in
|
||||
handleIntent(intent)
|
||||
}
|
||||
}
|
||||
@ -385,7 +389,7 @@ class MainActivity : AppCompatActivity() {
|
||||
return
|
||||
}
|
||||
val uap = params[0]
|
||||
val ua = UserAgent.find(uas, uap)
|
||||
val ua = UserAgent.find(uap)
|
||||
if (ua == null) {
|
||||
Log.w("Baresip", "handleServiceEvent '$event' did not find ua $uap")
|
||||
return
|
||||
@ -394,8 +398,8 @@ class MainActivity : AppCompatActivity() {
|
||||
Log.d("Baresip", "Handling service event '${ev[0]}' for $uap")
|
||||
val aor = ua.account.aor
|
||||
val acc = ua.account
|
||||
for (account_index in uas.indices) {
|
||||
if (uas[account_index].account.aor == aor) {
|
||||
for (account_index in UserAgent.uas().indices) {
|
||||
if (UserAgent.uas()[account_index].account.aor == aor) {
|
||||
when (ev[0]) {
|
||||
"ua added" -> {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
@ -406,70 +410,49 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
"call ringing" -> {
|
||||
}
|
||||
"call rejected" -> {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
}
|
||||
"call incoming" -> {
|
||||
val callp = params[1]
|
||||
if (ContextCompat.checkSelfPermission(applicationContext,
|
||||
Manifest.permission.RECORD_AUDIO) ==
|
||||
PackageManager.PERMISSION_DENIED) {
|
||||
Toast.makeText(applicationContext,
|
||||
"You have not granted microphone permission.",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
ua_hangup(uap, callp, 486, "Busy Here")
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.e("Baresip", "Incoming call $callp not found")
|
||||
return
|
||||
}
|
||||
val peer_uri = Api.call_peeruri(callp)
|
||||
val new_call = Call(callp, ua, peer_uri, "in", "incoming",
|
||||
dtmfWatcher(callp))
|
||||
if (ONE_CALL_ONLY && (calls.size > 0)) {
|
||||
Log.d("Baresip", "Auto-rejecting incoming call $uap/$callp/$peer_uri")
|
||||
ua_hangup(uap, callp, 486, "Busy Here")
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, peer_uri, "in", false))
|
||||
CallsActivity.saveHistory()
|
||||
acc.missedCalls = true
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
aorSpinner.setSelection(account_index)
|
||||
} else {
|
||||
Log.d("Baresip", "Incoming call $uap/$callp/$peer_uri")
|
||||
calls.add(new_call)
|
||||
if (ua != uas[aorSpinner.selectedItemPosition]) {
|
||||
aorSpinner.setSelection(account_index)
|
||||
} else {
|
||||
callTitle.text = "Incoming call from ..."
|
||||
callUri.setText(new_call.peerURI)
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
callButton.visibility = View.INVISIBLE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
answerButton.visibility = View.VISIBLE
|
||||
answerButton.isEnabled = true
|
||||
rejectButton.visibility = View.VISIBLE
|
||||
rejectButton.isEnabled = true
|
||||
holdButton.visibility = View.INVISIBLE
|
||||
dtmf.visibility = View.INVISIBLE
|
||||
}
|
||||
startRinging()
|
||||
if (Utils.isVisible()) {
|
||||
callTitle.text = "Incoming call from ..."
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerURI),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
callButton.visibility = View.INVISIBLE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
answerButton.visibility = View.VISIBLE
|
||||
answerButton.isEnabled = true
|
||||
rejectButton.visibility = View.VISIBLE
|
||||
rejectButton.isEnabled = true
|
||||
holdButton.visibility = View.INVISIBLE
|
||||
dtmf.visibility = View.INVISIBLE
|
||||
}
|
||||
if (Utils.isVisible()) {
|
||||
Log.d("Baresip", "Baresip is visible")
|
||||
val i = Intent(applicationContext, MainActivity::class.java)
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
||||
startActivity(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
"call established" -> {
|
||||
val callp = params[1]
|
||||
val call = Call.find(calls, callp)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.e("Baresip", "Established call $callp not found")
|
||||
return
|
||||
}
|
||||
Log.d("Baresip", "AoR $aor call $callp established")
|
||||
call.status = "connected"
|
||||
call.onhold = false
|
||||
call.security = R.drawable.box_red
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
if (call.dir == "in")
|
||||
callTitle.text = "Incoming call from ..."
|
||||
else
|
||||
@ -492,28 +475,13 @@ class MainActivity : AppCompatActivity() {
|
||||
dtmf.hint = "DTMF"
|
||||
dtmf.visibility = View.VISIBLE
|
||||
dtmf.requestFocus()
|
||||
dtmf.addTextChangedListener(call.dtmfWatcher)
|
||||
}
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, call.peerURI, call.dir, true))
|
||||
CallsActivity.saveHistory()
|
||||
call.hasHistory = true
|
||||
if (rtTimer != null) {
|
||||
rtTimer!!.cancel()
|
||||
rtTimer = null
|
||||
if (rt.isPlaying) rt.stop()
|
||||
}
|
||||
am.mode = AudioManager.MODE_IN_COMMUNICATION
|
||||
requestAudioFocus( AudioManager.STREAM_VOICE_CALL)
|
||||
am.isSpeakerphoneOn = false
|
||||
// am.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
|
||||
// (am.getStreamMaxVolume(STREAM_VOICE_CALL) / 2) + 1,
|
||||
// AudioManager.STREAM_VOICE_CALL)
|
||||
(dtmf.tag as ArrayList<TextWatcher>).add(call.dtmfWatcher!!)
|
||||
dtmf.addTextChangedListener(call.dtmfWatcher)
|
||||
}
|
||||
"call verify" -> {
|
||||
val callp = params[1]
|
||||
val call = Call.find(calls, callp)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.e("Baresip", "Call $callp to be verified is not found")
|
||||
return
|
||||
@ -531,7 +499,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
call.security = security
|
||||
call.zid = ev[3]
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
securityButton.setImageResource(security)
|
||||
setSecurityButtonTag(securityButton, security)
|
||||
securityButton.visibility = View.VISIBLE
|
||||
@ -541,7 +509,7 @@ class MainActivity : AppCompatActivity() {
|
||||
verifyDialog.setNegativeButton("No") { dialog, _ ->
|
||||
call.security = R.drawable.box_yellow
|
||||
call.zid = ev[3]
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
securityButton.setImageResource(R.drawable.box_yellow)
|
||||
securityButton.tag = "yellow"
|
||||
securityButton.visibility = View.VISIBLE
|
||||
@ -552,7 +520,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
"call verified", "call secure" -> {
|
||||
val callp = params[1]
|
||||
val call = Call.find(calls, callp)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.e("Baresip", "Call $callp that is verified is not found")
|
||||
return
|
||||
@ -566,7 +534,7 @@ class MainActivity : AppCompatActivity() {
|
||||
tag = "green"
|
||||
call.zid = ev[1]
|
||||
}
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
securityButton.setImageResource(call.security)
|
||||
securityButton.tag = tag
|
||||
securityButton.visibility = View.VISIBLE
|
||||
@ -574,86 +542,53 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
"call transfer" -> {
|
||||
val callp = params[1]
|
||||
val call = Call.find(calls, callp)
|
||||
val call = Call.find(callp)
|
||||
if (call == null) {
|
||||
Log.e("Baresip", "Call $callp to be transfered is not found")
|
||||
Log.e("Baresip", "Call $callp to be transferred is not found")
|
||||
return
|
||||
}
|
||||
val transferDialog = AlertDialog.Builder(this)
|
||||
transferDialog.setMessage("Do you want to transfer this call to ${ev[1]}?")
|
||||
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
|
||||
Utils.aorDomain(aor))
|
||||
transferDialog.setMessage("Do you accept to transfer call to $target?")
|
||||
transferDialog.setPositiveButton("Yes") { dialog, _ ->
|
||||
if (call in calls)
|
||||
if (call in Call.calls())
|
||||
transfer(ua, call, ev[1])
|
||||
else
|
||||
call(ua, ev[1])
|
||||
dialog.dismiss()
|
||||
}
|
||||
transferDialog.setNegativeButton("No") { dialog, _ ->
|
||||
if (call in calls)
|
||||
call_notify_sipfrag(callp, 603, "Decline")
|
||||
if (call in Call.calls())
|
||||
Api.call_notify_sipfrag(callp, 603, "Decline")
|
||||
dialog.dismiss()
|
||||
}
|
||||
transferDialog.create().show()
|
||||
}
|
||||
"transfer failed" -> {
|
||||
val callp = params[1]
|
||||
Log.d("Baresip", "AoR $aor hanging up call $callp with ${ev[1]}")
|
||||
ua_hangup(ua.uap, callp, 0, "")
|
||||
}
|
||||
"call closed" -> {
|
||||
val callp = params[1]
|
||||
val call = Call.find(calls, callp)
|
||||
if (call == null) {
|
||||
Log.d("Baresip", "Call $callp that is closed is not found")
|
||||
return
|
||||
val watchers = dtmf.tag as ArrayList<TextWatcher>
|
||||
if (watchers.size > 0) {
|
||||
dtmf.removeTextChangedListener(watchers[0])
|
||||
watchers.removeAt(0)
|
||||
}
|
||||
Log.d("Baresip", "Removing call ${uap}/${callp}/" + call.peerURI)
|
||||
stopRinging()
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
dtmf.removeTextChangedListener(call.dtmfWatcher)
|
||||
}
|
||||
calls.remove(call)
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) {
|
||||
if (ua == UserAgent.uas()[aorSpinner.selectedItemPosition]) {
|
||||
showCall(ua)
|
||||
if (ua.account.missedCalls)
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
if (!call.hasHistory) {
|
||||
if (CallHistory.aorHistory(history, aor) > HISTORY_SIZE)
|
||||
CallHistory.aorRemoveHistory(history, aor)
|
||||
history.add(CallHistory(aor, call.peerURI, call.dir,false))
|
||||
CallsActivity.saveHistory()
|
||||
if (call.dir == "in") {
|
||||
acc.missedCalls = true
|
||||
if (ua == uas[aorSpinner.selectedItemPosition])
|
||||
callsButton.setImageResource(R.drawable.calls_missed)
|
||||
}
|
||||
}
|
||||
if (calls.size == 0) {
|
||||
am.mode = AudioManager.MODE_NORMAL
|
||||
} else {
|
||||
val uaCalls = Call.uaCalls(calls, ua, "")
|
||||
if (uaCalls.size > 0) call_start_audio(uaCalls[uaCalls.size - 1].callp)
|
||||
}
|
||||
if (am.isSpeakerphoneOn) {
|
||||
am.isSpeakerphoneOn = false
|
||||
val speakerIcon = findViewById(R.id.speakerIcon) as ActionMenuItemView
|
||||
speakerIcon.setBackgroundColor(ContextCompat.getColor(applicationContext,
|
||||
val speakerIcon = findViewById(R.id.speakerIcon) as ActionMenuItemView
|
||||
speakerIcon.setBackgroundColor(ContextCompat.getColor(applicationContext,
|
||||
R.color.colorPrimary))
|
||||
}
|
||||
if (audioFocused) {
|
||||
abandonAudioFocus()
|
||||
}
|
||||
}
|
||||
"message" -> {
|
||||
val peerUri = params[1]
|
||||
val msgText = params[2]
|
||||
val time = params[3]
|
||||
val newMsg = Message(aor, peerUri, R.drawable.arrow_down_green, msgText,
|
||||
time.toLong(), true)
|
||||
Log.d("Baresip", "Incoming message $aor/$peerUri/$msgText")
|
||||
messages.add(newMsg)
|
||||
ChatsActivity.saveMessages()
|
||||
Message.add(Message(aor, peerUri, R.drawable.arrow_down_green, msgText,
|
||||
time.toLong(), true))
|
||||
if (Utils.isVisible()) {
|
||||
if (ua != uas[aorSpinner.selectedItemPosition])
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
|
||||
aorSpinner.setSelection(account_index)
|
||||
val i = Intent(applicationContext, ChatsActivity::class.java)
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
@ -676,7 +611,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
if ((aorSpinner.selectedItemPosition >= 0) &&
|
||||
(ua == uas[aorSpinner.selectedItemPosition]))
|
||||
(ua == UserAgent.uas()[aorSpinner.selectedItemPosition]))
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
else
|
||||
@ -702,26 +637,19 @@ class MainActivity : AppCompatActivity() {
|
||||
Log.d("Baresip", "Handling intent '$action'")
|
||||
when (action) {
|
||||
"call" -> {
|
||||
if (!calls.isEmpty()) {
|
||||
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(MainActivity.uas, uap)
|
||||
val ua = UserAgent.find(uap)
|
||||
if (ua == null) {
|
||||
Log.e("Baresip", "onNewIntent did not find ua $uap")
|
||||
Log.e("Baresip", "handleIntent 'call' did not find ua $uap")
|
||||
return
|
||||
}
|
||||
val aor = ua.account.aor
|
||||
if (ua != uas[aorSpinner.selectedItemPosition]) {
|
||||
for (account_index in uas.indices) {
|
||||
if (uas[account_index].account.aor == aor) {
|
||||
aorSpinner.setSelection(account_index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
|
||||
spinToAor(ua.account.aor)
|
||||
makeCall = intent.getStringExtra("peer")
|
||||
}
|
||||
"answer" -> {
|
||||
@ -731,9 +659,33 @@ class MainActivity : AppCompatActivity() {
|
||||
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)
|
||||
}
|
||||
"reply", "save", "delete" -> {
|
||||
val uap = intent.getStringExtra("uap")
|
||||
val ua = UserAgent.find(MainActivity.uas, uap)
|
||||
val ua = UserAgent.find(uap)
|
||||
if (ua == null) {
|
||||
Log.e("Baresip", "onNewIntent did not find ua $uap")
|
||||
return
|
||||
@ -743,14 +695,8 @@ class MainActivity : AppCompatActivity() {
|
||||
"reply" -> {
|
||||
val i = Intent(this@MainActivity, ChatsActivity::class.java)
|
||||
val b = Bundle()
|
||||
if (ua != uas[aorSpinner.selectedItemPosition]) {
|
||||
for (account_index in uas.indices) {
|
||||
if (uas[account_index].account.aor == aor) {
|
||||
aorSpinner.setSelection(account_index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
|
||||
spinToAor(aor)
|
||||
b.putString("aor", aor)
|
||||
b.putString("peer", intent.getStringExtra("peer"))
|
||||
b.putBoolean("focus", true)
|
||||
@ -759,19 +705,21 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
"save" -> {
|
||||
ChatsActivity.saveUaMessage(ua.account.aor,
|
||||
intent.getStringExtra("time").toLong())
|
||||
intent.getStringExtra("time").toLong(),
|
||||
applicationContext.filesDir.absolutePath)
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
"delete" -> {
|
||||
ChatsActivity.deleteUaMessage(ua.account.aor,
|
||||
intent.getStringExtra("time").toLong())
|
||||
intent.getStringExtra("time").toLong(),
|
||||
applicationContext.filesDir.absolutePath)
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
||||
nm.cancel(BaresipService.MESSAGE_NOTIFICATION_ID)
|
||||
}
|
||||
"message" -> {
|
||||
val ua = UserAgent.find(MainActivity.uas, intent.getStringExtra("uap"))!!
|
||||
val ua = UserAgent.find(intent.getStringExtra("uap"))!!
|
||||
val i = Intent(applicationContext, ChatsActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("aor", ua.account.aor)
|
||||
@ -816,7 +764,7 @@ class MainActivity : AppCompatActivity() {
|
||||
override fun onDestroy() {
|
||||
Log.d("Baresip", "Destroyed")
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(serviceEventReceiver)
|
||||
if (BaresipService.IS_SERVICE_RUNNING) {
|
||||
if (BaresipService.isServiceRunning) {
|
||||
baresipService.setAction("Kill")
|
||||
startService(baresipService)
|
||||
}
|
||||
@ -844,6 +792,9 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
R.id.accounts -> {
|
||||
i = Intent(this, AccountsActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("accp", "")
|
||||
i.putExtras(b)
|
||||
startActivityForResult(i, ACCOUNTS_CODE)
|
||||
return true
|
||||
}
|
||||
@ -860,7 +811,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
R.id.quit -> {
|
||||
Log.d("Baresip", "Quiting")
|
||||
if (BaresipService.IS_SERVICE_RUNNING) {
|
||||
if (BaresipService.isServiceRunning) {
|
||||
baresipService.setAction("Stop");
|
||||
startService(baresipService)
|
||||
}
|
||||
@ -876,11 +827,11 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
ACCOUNTS_CODE -> {
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
if (uas.size > 0) {
|
||||
if (UserAgent.uas().size > 0) {
|
||||
if ((aorSpinner.selectedItemPosition == -1) ||
|
||||
(aorSpinner.selectedItemPosition >= uas.size))
|
||||
(aorSpinner.selectedItemPosition >= UserAgent.uas().size))
|
||||
aorSpinner.setSelection(0)
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
val acc = UserAgent.uas()[aorSpinner.selectedItemPosition].account
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
@ -898,7 +849,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
ACCOUNT_CODE -> {
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
val acc = UserAgent.uas()[aorSpinner.selectedItemPosition].account
|
||||
if (acc.vmUri != "") {
|
||||
if (acc.vmNew > 0)
|
||||
voicemailButton.setImageResource(R.drawable.voicemail_new)
|
||||
@ -912,14 +863,14 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
CONTACTS_CODE -> {
|
||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
ContactsActivity.contacts.map{Contact -> Contact.name}))
|
||||
Contact.contacts().map{Contact -> Contact.name}))
|
||||
}
|
||||
|
||||
EDIT_CONFIG_CODE -> {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Utils.alertView(this, "Notice",
|
||||
"You need to restart baresip in order to activate saved config!")
|
||||
reload_config()
|
||||
Api.reload_config()
|
||||
}
|
||||
if (resultCode == RESULT_CANCELED) {
|
||||
Log.d("Baresip", "Edit config canceled")
|
||||
@ -927,14 +878,17 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
CALLS_CODE -> {
|
||||
val acc = uas[aorSpinner.selectedItemPosition].account
|
||||
val acc = UserAgent.uas()[aorSpinner.selectedItemPosition].account
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (data != null)
|
||||
callUri.setText(data.getStringExtra("peer_uri"))
|
||||
if (data != null) {
|
||||
val peerUri = data.getStringExtra("peer_uri")
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(peerUri),
|
||||
Utils.aorDomain(Utils.aorDomain(acc.aor))))
|
||||
}
|
||||
}
|
||||
if (resultCode == RESULT_CANCELED) {
|
||||
Log.d("Baresip", "History canceled")
|
||||
if (CallHistory.aorHistory(history, acc.aor) == 0) {
|
||||
if (CallHistory.aorHistorySize(acc.aor) == 0) {
|
||||
holdButton.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
@ -946,6 +900,14 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun spinToAor(aor: String) {
|
||||
for (account_index in UserAgent.uas().indices)
|
||||
if (UserAgent.uas()[account_index].account.aor == aor) {
|
||||
aorSpinner.setSelection(account_index)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private fun call(ua: UserAgent, uri: String) {
|
||||
if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.RECORD_AUDIO)
|
||||
== PackageManager.PERMISSION_DENIED) {
|
||||
@ -953,12 +915,16 @@ class MainActivity : AppCompatActivity() {
|
||||
"You have not granted microphone permission.", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
callUri.setText(uri)
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
|
||||
spinToAor(ua.account.aor)
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(uri),
|
||||
Utils.aorDomain(Utils.aorDomain(ua.account.aor))))
|
||||
callButton.visibility = View.INVISIBLE
|
||||
val callp = ua_connect(ua.uap, uri)
|
||||
val callp = Api.ua_connect(ua.uap, uri)
|
||||
if (callp != "") {
|
||||
Log.d("Baresip", "Adding outgoing call ${ua.uap}/$callp/$uri")
|
||||
calls.add(Call(callp, ua, uri, "out", "outgoing", dtmfWatcher(callp)))
|
||||
Call.calls().add(Call(callp, ua, uri, "out", "outgoing",
|
||||
Utils.dtmfWatcher(callp)))
|
||||
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
callButton.visibility = View.INVISIBLE
|
||||
@ -975,44 +941,27 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun transfer(ua: UserAgent, call: Call, uri: String) {
|
||||
val newCallp = ua_call_alloc(ua.uap, call.callp)
|
||||
val newCallp = Api.ua_call_alloc(ua.uap, call.callp)
|
||||
if (newCallp != "") {
|
||||
Log.d("Baresip", "Adding outgoing call ${ua.uap}/$newCallp/$uri")
|
||||
val newCall = Call(newCallp, ua, uri, "out", "transferring",
|
||||
dtmfWatcher(newCallp))
|
||||
calls.add(newCall)
|
||||
call_stop_audio(call.callp)
|
||||
call_start_audio(newCallp)
|
||||
val err = call_connect(newCallp, uri)
|
||||
Utils.dtmfWatcher(newCallp))
|
||||
Call.calls().add(newCall)
|
||||
Api.call_stop_audio(call.callp)
|
||||
Api.call_start_audio(newCallp)
|
||||
val err = Api.call_connect(newCallp, uri)
|
||||
if (err == 0) {
|
||||
if (ua == uas[aorSpinner.selectedItemPosition]) showCall(ua)
|
||||
if (ua != UserAgent.uas()[aorSpinner.selectedItemPosition])
|
||||
spinToAor(ua.account.aor)
|
||||
showCall(ua)
|
||||
} else {
|
||||
call_start_audio(call.callp)
|
||||
Api.call_start_audio(call.callp)
|
||||
Log.w("Baresip", "call_connect $newCallp failed with error $err")
|
||||
call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||
Api.call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||
}
|
||||
} else {
|
||||
Log.w("Baresip", "ua_call_alloc ${ua.uap}/${call.callp} failed")
|
||||
call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||
}
|
||||
}
|
||||
|
||||
private fun dtmfWatcher(callp: String): TextWatcher {
|
||||
return object : TextWatcher {
|
||||
override fun beforeTextChanged(sequence: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(sequence: CharSequence, start: Int, before: Int, count: Int) {
|
||||
val text = sequence.subSequence(start, start + count).toString()
|
||||
if (text.length > 0) {
|
||||
val digit = text[0]
|
||||
Log.d("Baresip", "Got DTMF digit '$digit'")
|
||||
if (((digit >= '0') && (digit <= '9')) || (digit == '*') || (digit == '#'))
|
||||
call_send_digit(callp, digit)
|
||||
}
|
||||
}
|
||||
override fun afterTextChanged(sequence: Editable) {
|
||||
// KEYCODE_REL
|
||||
// call_send_digit(callp, 4.toChar())
|
||||
}
|
||||
Api.call_notify_sipfrag(call.callp, 500, "Call Error")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,10 +980,13 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun showCall(ua: UserAgent) {
|
||||
if (Call.uaCalls(calls, ua, "").size == 0) {
|
||||
if (Call.uaCalls(ua, "").size == 0) {
|
||||
callTitle.text = "Outgoing call to ..."
|
||||
callUri.text.clear()
|
||||
callUri.hint = "Callee"
|
||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||
Contact.contacts().map{Contact -> Contact.name}))
|
||||
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
callButton.visibility = View.VISIBLE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
@ -1043,8 +995,8 @@ class MainActivity : AppCompatActivity() {
|
||||
holdButton.visibility = View.INVISIBLE
|
||||
dtmf.visibility = View.INVISIBLE
|
||||
} else {
|
||||
val callsOut = Call.uaCalls(calls, ua, "out")
|
||||
val callsIn = Call.uaCalls(calls, ua, "in")
|
||||
val callsOut = Call.uaCalls(ua, "out")
|
||||
val callsIn = Call.uaCalls(ua, "in")
|
||||
val call: Call
|
||||
if (callsOut.size > 0) {
|
||||
call = callsOut[callsOut.size - 1]
|
||||
@ -1056,7 +1008,8 @@ class MainActivity : AppCompatActivity() {
|
||||
callTitle.text = "Incoming call from ..."
|
||||
call = callsIn[callsIn.size - 1]
|
||||
}
|
||||
callUri.setText(call.peerURI)
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerURI),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
when (call.status) {
|
||||
"outgoing", "transferring" -> {
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
@ -1112,97 +1065,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestAudioFocus(streamType: Int) {
|
||||
val res: Int
|
||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) && (audioFocusRequest == null)) {
|
||||
val playbackAttributes = AudioAttributes.Builder()
|
||||
.setLegacyStreamType(streamType)
|
||||
.build()
|
||||
@TargetApi(26)
|
||||
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||
.setAudioAttributes(playbackAttributes)
|
||||
.build()
|
||||
@TargetApi(26)
|
||||
res = am.requestAudioFocus(audioFocusRequest)
|
||||
if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d("Baresip", "Audio focus granted")
|
||||
} else {
|
||||
Log.d("Baresip", "Audio focus denied")
|
||||
audioFocusRequest = null
|
||||
}
|
||||
} else {
|
||||
res = am.requestAudioFocus(null, streamType,
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||
if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d("Baresip", "Audio focus granted")
|
||||
audioFocused = true
|
||||
} else {
|
||||
Log.d("Baresip", "Audio focus denied")
|
||||
audioFocused = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun abandonAudioFocus() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (audioFocusRequest != null) {
|
||||
am.abandonAudioFocusRequest(audioFocusRequest)
|
||||
audioFocusRequest = null
|
||||
}
|
||||
} else {
|
||||
if (audioFocused) {
|
||||
am.abandonAudioFocus(null)
|
||||
audioFocused = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startRinging() {
|
||||
am.mode = AudioManager.MODE_RINGTONE
|
||||
requestAudioFocus(AudioManager.STREAM_RING)
|
||||
rt.play()
|
||||
rtTimer = Timer()
|
||||
rtTimer!!.scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
if (!rt.isPlaying()) {
|
||||
rt.play()
|
||||
}
|
||||
}
|
||||
}, 1000 * 1, 1000 * 1)
|
||||
}
|
||||
|
||||
private fun stopRinging() {
|
||||
if (rtTimer != null) {
|
||||
rtTimer!!.cancel()
|
||||
rtTimer = null
|
||||
if (rt.isPlaying) rt.stop()
|
||||
}
|
||||
}
|
||||
|
||||
external fun uag_current_set(uap: String)
|
||||
external fun ua_connect(uap: String, peer_uri: String): String
|
||||
external fun ua_call_alloc(uap: String, xcallp: String): String
|
||||
external fun ua_answer(uap: String, callp: String)
|
||||
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
|
||||
external fun call_hold(callp: String): Int
|
||||
external fun call_unhold(callp: String): Int
|
||||
external fun call_send_digit(callp: String, digit: Char): Int
|
||||
external fun call_connect(callp: String, peer_uri: String): Int
|
||||
external fun call_notify_sipfrag(callp: String, code: Int, reason: String)
|
||||
external fun call_start_audio(callp: String)
|
||||
external fun call_stop_audio(callp: String)
|
||||
external fun reload_config(): Int
|
||||
|
||||
companion object {
|
||||
|
||||
var uas = ArrayList<UserAgent>()
|
||||
internal var images = ArrayList<Int>()
|
||||
var history: ArrayList<CallHistory> = ArrayList()
|
||||
internal var calls = ArrayList<Call>()
|
||||
internal var messages = ArrayList<Message>()
|
||||
internal var audioFocused = false
|
||||
internal var audioFocusRequest: AudioFocusRequest? = null
|
||||
var filesPath = ""
|
||||
var visible = true
|
||||
var makeCall = ""
|
||||
var answerCall = ""
|
||||
@ -1217,11 +1081,7 @@ class MainActivity : AppCompatActivity() {
|
||||
const val CONTACT_CODE = 7
|
||||
const val MESSAGES_CODE = 8
|
||||
const val MESSAGE_CODE = 9
|
||||
|
||||
const val RECORD_AUDIO_PERMISSION = 1
|
||||
const val HISTORY_SIZE = 100
|
||||
const val MESSAGE_HISTORY_SIZE = 100
|
||||
const val ONE_CALL_ONLY = true
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,38 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import java.io.Serializable
|
||||
import java.io.*
|
||||
import java.util.ArrayList
|
||||
|
||||
class Message(val aor: String, val peerUri: String, var direction: Int, val message: String,
|
||||
val timeStamp: Long, var new: Boolean): Serializable {
|
||||
|
||||
companion object {
|
||||
|
||||
val MESSAGE_HISTORY_SIZE = 100
|
||||
|
||||
fun messages(): ArrayList<Message> {
|
||||
return BaresipService.messages
|
||||
}
|
||||
|
||||
fun messages(messages: ArrayList<Message>) {
|
||||
BaresipService.messages = messages
|
||||
}
|
||||
|
||||
fun add(message: Message) {
|
||||
BaresipService.messages.add(message)
|
||||
var count = 0
|
||||
var firstIndex = -1
|
||||
for (i in BaresipService.messages.indices)
|
||||
if (BaresipService.messages[i].aor == message.aor) {
|
||||
if (count == 0) firstIndex = i
|
||||
count++
|
||||
if (count > MESSAGE_HISTORY_SIZE) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (count > MESSAGE_HISTORY_SIZE)
|
||||
BaresipService.messages.removeAt(firstIndex)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,37 +4,51 @@ import android.util.Log
|
||||
|
||||
class UserAgent (val uap: String) {
|
||||
|
||||
val account = Account(ua_account(uap))
|
||||
val account = Account(Api.ua_account(uap))
|
||||
|
||||
fun register() {
|
||||
if (account.regint > 0) {
|
||||
Log.d("Baresip", "Registering ${account.aor} UA ${uap}")
|
||||
if (ua_register(uap) != 0)
|
||||
if (Api.ua_register(uap) != 0)
|
||||
Log.e("Baresip", "Registering failed")
|
||||
}
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
ua_destroy(uap)
|
||||
Api.ua_destroy(uap)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
external fun ua_alloc(uri: String): String
|
||||
external fun ua_update_account(ua: String): Int
|
||||
external fun ua_destroy(ua: String)
|
||||
external fun ua_register(ua: String): Int
|
||||
external fun ua_isregistered(ua: String): Boolean
|
||||
external fun ua_unregister(ua: String)
|
||||
fun uas(): ArrayList<UserAgent> {
|
||||
return BaresipService.uas
|
||||
}
|
||||
|
||||
fun status(): ArrayList<Int> {
|
||||
return BaresipService.status
|
||||
}
|
||||
|
||||
fun add(ua: UserAgent, status: Int) {
|
||||
BaresipService.uas.add(ua)
|
||||
BaresipService.status.add(status)
|
||||
}
|
||||
|
||||
fun remove(ua: UserAgent) {
|
||||
val index = BaresipService.uas.indexOf(ua)
|
||||
if (index != -1) {
|
||||
BaresipService.uas[index].destroy()
|
||||
BaresipService.status.removeAt(index)
|
||||
}
|
||||
}
|
||||
|
||||
fun uaAlloc(uri: String): UserAgent? {
|
||||
val uap = ua_alloc(uri)
|
||||
val uap = Api.ua_alloc(uri)
|
||||
if (uap != "") return UserAgent(uap)
|
||||
return null
|
||||
}
|
||||
|
||||
fun find(uas: ArrayList<UserAgent>, uap: String): UserAgent? {
|
||||
for (ua in uas) {
|
||||
fun find(uap: String): UserAgent? {
|
||||
for (ua in BaresipService.uas) {
|
||||
if (ua.uap == uap) return ua
|
||||
}
|
||||
return null
|
||||
@ -50,12 +64,10 @@ class UserAgent (val uap: String) {
|
||||
fun register(uas: ArrayList<UserAgent>) {
|
||||
for (ua in uas) {
|
||||
if (ua.account.regint > 0)
|
||||
if (ua_register(ua.uap) != 0)
|
||||
if (Api.ua_register(ua.uap) != 0)
|
||||
Log.e("Baresip", "Failed to register ${ua.account.aor}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
external fun ua_account(ua: String): String
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ import android.support.v7.app.AlertDialog
|
||||
import android.util.Log
|
||||
import android.os.PowerManager
|
||||
import android.app.KeyguardManager
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
|
||||
import java.io.*
|
||||
|
||||
@ -95,9 +97,13 @@ object Utils {
|
||||
}
|
||||
|
||||
fun friendlyUri(uri: String, domain: String): String {
|
||||
val user = uriUserPart(uri)
|
||||
val host = uriHostPart(uri)
|
||||
if (host == domain) return user else return "$user@$host"
|
||||
if (uri.contains("@")) {
|
||||
val user = uriUserPart(uri)
|
||||
val host = uriHostPart(uri)
|
||||
if (host == domain) return user else return "$user@$host"
|
||||
} else {
|
||||
return uri
|
||||
}
|
||||
}
|
||||
|
||||
fun aorDomain(aor: String): String {
|
||||
@ -233,4 +239,23 @@ object Utils {
|
||||
return isLocked
|
||||
}
|
||||
|
||||
fun dtmfWatcher(callp: String): TextWatcher {
|
||||
return object : TextWatcher {
|
||||
override fun beforeTextChanged(sequence: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(sequence: CharSequence, start: Int, before: Int, count: Int) {
|
||||
val text = sequence.subSequence(start, start + count).toString()
|
||||
if (text.length > 0) {
|
||||
val digit = text[0]
|
||||
Log.d("Baresip", "Got DTMF digit '$digit'")
|
||||
if (((digit >= '0') && (digit <= '9')) || (digit == '*') || (digit == '#'))
|
||||
Api.call_send_digit(callp, digit)
|
||||
}
|
||||
}
|
||||
override fun afterTextChanged(sequence: Editable) {
|
||||
// KEYCODE_REL
|
||||
// call_send_digit(callp, 4.toChar())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
android:textAlignment="gravity"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textSize="18sp"
|
||||
android:maxLines="1"
|
||||
android:text="" />
|
||||
|
||||
Reference in New Issue
Block a user