use new contacts activity
renamed some baresip functions added calleeAdapter var
This commit is contained in:
+33
-22
@@ -104,6 +104,16 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev,
|
|||||||
case UA_EVENT_REGISTER_FAIL:
|
case UA_EVENT_REGISTER_FAIL:
|
||||||
re_snprintf(event_buf, sizeof event_buf, "%s", ua_event_reg_str(ev));
|
re_snprintf(event_buf, sizeof event_buf, "%s", ua_event_reg_str(ev));
|
||||||
break;
|
break;
|
||||||
|
case UA_EVENT_CALL_INCOMING:
|
||||||
|
play = mem_deref(play);
|
||||||
|
if (list_count(ua_calls(ua)) > 1) {
|
||||||
|
(void)play_file(&play, player, "callwaiting.wav", 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(void)play_file(&play, player, "ring.wav", -1);
|
||||||
|
}
|
||||||
|
re_snprintf(event_buf, sizeof event_buf, "%s", "call incoming");
|
||||||
|
break;
|
||||||
case UA_EVENT_CALL_RINGING:
|
case UA_EVENT_CALL_RINGING:
|
||||||
play = mem_deref(play);
|
play = mem_deref(play);
|
||||||
(void)play_file(&play, player, "ringback.wav", -1);
|
(void)play_file(&play, player, "ringback.wav", -1);
|
||||||
@@ -116,17 +126,6 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev,
|
|||||||
play = mem_deref(play);
|
play = mem_deref(play);
|
||||||
re_snprintf(event_buf, sizeof event_buf, "%s", "call established");
|
re_snprintf(event_buf, sizeof event_buf, "%s", "call established");
|
||||||
break;
|
break;
|
||||||
case UA_EVENT_CALL_INCOMING:
|
|
||||||
uag_current_set(ua);
|
|
||||||
play = mem_deref(play);
|
|
||||||
if (list_count(ua_calls(ua)) > 1) {
|
|
||||||
(void)play_file(&play, player, "callwaiting.wav", 3);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(void)play_file(&play, player, "ring.wav", -1);
|
|
||||||
}
|
|
||||||
re_snprintf(event_buf, sizeof event_buf, "%s", "call incoming");
|
|
||||||
break;
|
|
||||||
case UA_EVENT_CALL_MENC:
|
case UA_EVENT_CALL_MENC:
|
||||||
if (prm[0] == '1')
|
if (prm[0] == '1')
|
||||||
re_snprintf(event_buf, sizeof event_buf, "call verify,%s", prm+2);
|
re_snprintf(event_buf, sizeof event_buf, "call verify,%s", prm+2);
|
||||||
@@ -260,6 +259,8 @@ Java_com_tutpro_baresip_MainActivity_baresipStart(JNIEnv *env, jobject instance,
|
|||||||
|
|
||||||
conf_path_set(path);
|
conf_path_set(path);
|
||||||
|
|
||||||
|
// log_enable_debug(true);
|
||||||
|
|
||||||
err = conf_configure();
|
err = conf_configure();
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGW("conf_configure() failed: (%d)\n", err);
|
LOGW("conf_configure() failed: (%d)\n", err);
|
||||||
@@ -326,6 +327,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOGD("closing upon main loop exit");
|
LOGD("closing upon main loop exit");
|
||||||
|
play = mem_deref(play);
|
||||||
ua_close();
|
ua_close();
|
||||||
conf_close();
|
conf_close();
|
||||||
baresip_close();
|
baresip_close();
|
||||||
@@ -726,22 +728,22 @@ Java_com_tutpro_baresip_UserAgentKt_ua_1aor(JNIEnv *env, jobject thiz, jstring j
|
|||||||
return (*env)->NewStringUTF(env, "");
|
return (*env)->NewStringUTF(env, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL /* currently not in use */
|
JNIEXPORT void JNICALL
|
||||||
Java_com_tutpro_baresip_MainActivity_ua_1current_1set(JNIEnv *env, jobject thiz,
|
Java_com_tutpro_baresip_MainActivity_uag_1current_1set(JNIEnv *env, jobject thiz,
|
||||||
jstring javaAoR)
|
jstring javaUA)
|
||||||
{
|
{
|
||||||
struct ua *new_current_ua;
|
struct ua *new_current_ua;
|
||||||
const char *native_aor = (*env)->GetStringUTFChars(env, javaAoR, 0);
|
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
|
||||||
|
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
|
||||||
|
|
||||||
LOGD("running ua_current_set on %s\n", native_aor);
|
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
||||||
new_current_ua = uag_find_aor(native_aor);
|
LOGD("running uag_current_set on %s\n", native_ua);
|
||||||
uag_current_set(new_current_ua);
|
uag_current_set(ua);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaAoR, native_aor);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL /* currently not in use */
|
JNIEXPORT jstring JNICALL
|
||||||
Java_com_tutpro_baresip_MainActivity_ua_1current(JNIEnv *env, jobject thiz)
|
Java_com_tutpro_baresip_MainActivity_uag_1current(JNIEnv *env, jobject thiz)
|
||||||
{
|
{
|
||||||
struct ua *current_ua = uag_current();
|
struct ua *current_ua = uag_current();
|
||||||
char ua_buf[256];
|
char ua_buf[256];
|
||||||
@@ -798,10 +800,10 @@ Java_com_tutpro_baresip_MainActivity_ua_1answer(JNIEnv *env, jobject thiz,
|
|||||||
LOGD("answering call %s/%s\n", native_ua, native_call);
|
LOGD("answering call %s/%s\n", native_ua, native_call);
|
||||||
struct ua *ua = (struct ua *) strtoul(native_ua, NULL, 10);
|
struct ua *ua = (struct ua *) strtoul(native_ua, NULL, 10);
|
||||||
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
||||||
|
play = mem_deref(play);
|
||||||
ua_answer(ua, call);
|
ua_answer(ua, call);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -820,6 +822,10 @@ Java_com_tutpro_baresip_MainActivity_ua_1hold_1answer(JNIEnv *env, jobject thiz,
|
|||||||
else
|
else
|
||||||
call = NULL;
|
call = NULL;
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
|
play = mem_deref(play);
|
||||||
|
audio_set_source(call_audio(ua_call(uag_current())), NULL, NULL);
|
||||||
|
call_hold(ua_call(uag_current()), true);
|
||||||
|
ua_answer(ua, call);
|
||||||
return ua_hold_answer(ua, call);
|
return ua_hold_answer(ua, call);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,6 +837,7 @@ Java_com_tutpro_baresip_MainActivity_call_1hold(JNIEnv *env, jobject thiz,
|
|||||||
|
|
||||||
LOGD("holding call %s\n", native_call);
|
LOGD("holding call %s\n", native_call);
|
||||||
int res = call_hold(call, true);
|
int res = call_hold(call, true);
|
||||||
|
// audio_set_source(call_audio(call), NULL, NULL);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -842,6 +849,7 @@ Java_com_tutpro_baresip_MainActivity_call_1unhold(JNIEnv *env, jobject thiz,
|
|||||||
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
struct call *call = (struct call *) strtoul(native_call, NULL, 10);
|
||||||
|
|
||||||
LOGD("unholding call %s\n", native_call);
|
LOGD("unholding call %s\n", native_call);
|
||||||
|
// audio_set_source(call_audio(call), "opensles", "nil");
|
||||||
int res = call_hold(call, false);
|
int res = call_hold(call, false);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
|
||||||
return res;
|
return res;
|
||||||
@@ -923,6 +931,9 @@ JNIEXPORT jint JNICALL
|
|||||||
Java_com_tutpro_baresip_Utils_cmd_1exec(JNIEnv *env, jobject thiz, jstring javaCmd) {
|
Java_com_tutpro_baresip_Utils_cmd_1exec(JNIEnv *env, jobject thiz, jstring javaCmd) {
|
||||||
const char *native_cmd = (*env)->GetStringUTFChars(env, javaCmd, 0);
|
const char *native_cmd = (*env)->GetStringUTFChars(env, javaCmd, 0);
|
||||||
LOGD("processing command '%s'\n", native_cmd);
|
LOGD("processing command '%s'\n", native_cmd);
|
||||||
|
if (strcmp(native_cmd, "audio_debug") == 0) {
|
||||||
|
re_printf("Baresip audio debug '%H\n", audio_debug, call_audio(ua_call(uag_current())));
|
||||||
|
}
|
||||||
int res = cmd_process_long(baresip_commands(), native_cmd, strlen(native_cmd), &pf_null, NULL);
|
int res = cmd_process_long(baresip_commands(), native_cmd, strlen(native_cmd), &pf_null, NULL);
|
||||||
(*env)->ReleaseStringUTFChars(env, javaCmd, native_cmd);
|
(*env)->ReleaseStringUTFChars(env, javaCmd, native_cmd);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
internal lateinit var dtmf: EditText
|
internal lateinit var dtmf: EditText
|
||||||
internal lateinit var uaAdapter: UaSpinnerAdapter
|
internal lateinit var uaAdapter: UaSpinnerAdapter
|
||||||
internal lateinit var aorSpinner: Spinner
|
internal lateinit var aorSpinner: Spinner
|
||||||
|
internal lateinit var calleeAdapter: ArrayAdapter<String>
|
||||||
internal lateinit var am: AudioManager
|
internal lateinit var am: AudioManager
|
||||||
internal lateinit var imm: InputMethodManager
|
internal lateinit var imm: InputMethodManager
|
||||||
internal lateinit var nm: NotificationManager
|
internal lateinit var nm: NotificationManager
|
||||||
@@ -103,6 +104,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val aor = acc.aor
|
val aor = acc.aor
|
||||||
val ua = uas[position]
|
val ua = uas[position]
|
||||||
Log.i("Baresip", "Setting $aor current")
|
Log.i("Baresip", "Setting $aor current")
|
||||||
|
uag_current_set(uas[position].uap)
|
||||||
val callsOut = Call.uaCalls(calls, ua, "out")
|
val callsOut = Call.uaCalls(calls, ua, "out")
|
||||||
if (callsOut.size == 0) {
|
if (callsOut.size == 0) {
|
||||||
callee.text.clear()
|
callee.text.clear()
|
||||||
@@ -222,12 +224,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
arrayOf(Manifest.permission.RECORD_AUDIO), RECORD_AUDIO_PERMISSION)
|
arrayOf(Manifest.permission.RECORD_AUDIO), RECORD_AUDIO_PERMISSION)
|
||||||
}
|
}
|
||||||
|
|
||||||
EditContactsActivity.updateContactsAndNames(applicationContext.filesDir.absolutePath +
|
ContactsActivity.generateContacts(applicationContext.filesDir.absolutePath +
|
||||||
"/contacts")
|
"/contacts")
|
||||||
|
|
||||||
callee.threshold = 2
|
callee.threshold = 2
|
||||||
callee.setAdapter<ArrayAdapter<String>>(ArrayAdapter(this,
|
calleeAdapter = ArrayAdapter(this,
|
||||||
android.R.layout.select_dialog_item, EditContactsActivity.Names))
|
android.R.layout.select_dialog_item, ContactsActivity.contactNames)
|
||||||
|
callee.setAdapter(calleeAdapter)
|
||||||
|
|
||||||
securityButton.setOnClickListener {
|
securityButton.setOnClickListener {
|
||||||
when (securityButton.tag) {
|
when (securityButton.tag) {
|
||||||
@@ -272,7 +275,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
"Call" -> {
|
"Call" -> {
|
||||||
val calleeText = (findViewById(R.id.callee) as EditText).text.toString()
|
val calleeText = (findViewById(R.id.callee) as EditText).text.toString()
|
||||||
if (calleeText.length > 0) {
|
if (calleeText.length > 0) {
|
||||||
var uri = EditContactsActivity.findContactURI(calleeText)
|
var uri = ContactsActivity.findContactURI(calleeText)
|
||||||
if (!uri.startsWith("sip:")) uri = "sip:$uri"
|
if (!uri.startsWith("sip:")) uri = "sip:$uri"
|
||||||
if (!uri.contains("@")) {
|
if (!uri.contains("@")) {
|
||||||
val host = aor.substring(aor.indexOf("@") + 1)
|
val host = aor.substring(aor.indexOf("@") + 1)
|
||||||
@@ -308,12 +311,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
holdButton.setOnClickListener {
|
holdButton.setOnClickListener {
|
||||||
when (holdButton.tag) {
|
when (holdButton.tag) {
|
||||||
"Hold" -> {
|
"Hold" -> {
|
||||||
Log.i("Baresip", "Holding " + (findViewById(R.id.callee) as EditText).text)
|
holdCallAt(Call.calls(calls, "out")[0], holdButton)
|
||||||
val call = Call.calls(calls, "out")[0]
|
|
||||||
call_hold(call.callp)
|
|
||||||
call.hold = true
|
|
||||||
holdButton.tag= "Resume"
|
|
||||||
holdButton.setImageResource(R.drawable.resume)
|
|
||||||
}
|
}
|
||||||
"Resume" -> {
|
"Resume" -> {
|
||||||
Log.i("Baresip", "Resuming " + (findViewById(R.id.callee) as EditText).text)
|
Log.i("Baresip", "Resuming " + (findViewById(R.id.callee) as EditText).text)
|
||||||
@@ -418,8 +416,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.contacts -> {
|
R.id.contacts -> {
|
||||||
i = Intent(this, EditContactsActivity::class.java)
|
i = Intent(this, ContactsActivity::class.java)
|
||||||
startActivityForResult(i, EDIT_CONTACTS_CODE)
|
startActivityForResult(i, CONTACTS_CODE)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.config -> {
|
R.id.config -> {
|
||||||
@@ -428,6 +426,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.about -> {
|
R.id.about -> {
|
||||||
|
Utils.cmd_exec("audio_debug")
|
||||||
i = Intent(this, AboutActivity::class.java)
|
i = Intent(this, AboutActivity::class.java)
|
||||||
startActivityForResult(i, ABOUT_CODE)
|
startActivityForResult(i, ABOUT_CODE)
|
||||||
return true
|
return true
|
||||||
@@ -470,6 +469,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
updateNotification()
|
updateNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONTACTS_CODE -> {
|
||||||
|
calleeAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
EDIT_CONFIG_CODE -> {
|
EDIT_CONFIG_CODE -> {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Utils.alertView(this, "Notice",
|
Utils.alertView(this, "Notice",
|
||||||
@@ -495,7 +498,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EDIT_CONTACTS_CODE, ABOUT_CODE -> {
|
ABOUT_CODE -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,7 +633,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
when ((v as ImageButton).tag) {
|
when ((v as ImageButton).tag) {
|
||||||
"Answer" -> {
|
"Answer" -> {
|
||||||
Log.i("Baresip", "UA ${ua.uap} accepting incoming call ${call.callp}")
|
Log.i("Baresip", "UA ${ua.uap} accepting incoming call ${call.callp}")
|
||||||
ua_hold_answer(ua.uap, "")
|
ua_answer(ua.uap, call.callp)
|
||||||
if (call.dir == "in") {
|
if (call.dir == "in") {
|
||||||
this@MainActivity.runOnUiThread {
|
this@MainActivity.runOnUiThread {
|
||||||
call.status = "Hangup"
|
call.status = "Hangup"
|
||||||
@@ -679,10 +682,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
ua_hangup(call.ua.uap, call.callp, 486, "Rejected")
|
ua_hangup(call.ua.uap, call.callp, 486, "Rejected")
|
||||||
}
|
}
|
||||||
"Hold" -> {
|
"Hold" -> {
|
||||||
call_hold(call.callp)
|
holdCallAt(call, reject_button)
|
||||||
v.tag = "Resume"
|
|
||||||
reject_button.setImageResource(R.drawable.resume)
|
|
||||||
call.hold = true
|
|
||||||
}
|
}
|
||||||
"Resume" -> {
|
"Resume" -> {
|
||||||
call_unhold(call.callp)
|
call_unhold(call.callp)
|
||||||
@@ -783,6 +783,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
"call incoming" -> {
|
"call incoming" -> {
|
||||||
val peer_uri = call_peeruri(callp)
|
val peer_uri = call_peeruri(callp)
|
||||||
Log.d("Baresip", "Incoming call $uap/$callp/$peer_uri")
|
Log.d("Baresip", "Incoming call $uap/$callp/$peer_uri")
|
||||||
|
if (ONE_CALL_ONLY && (calls.size > 0)) {
|
||||||
|
ua_hangup(uap, callp, 486, "Busy Here")
|
||||||
|
} else {
|
||||||
val new_call = Call(callp, ua, peer_uri, "in", "Answer", null)
|
val new_call = Call(callp, ua, peer_uri, "in", "Answer", null)
|
||||||
this@MainActivity.runOnUiThread {
|
this@MainActivity.runOnUiThread {
|
||||||
calls.add(new_call)
|
calls.add(new_call)
|
||||||
@@ -799,7 +802,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
showNotification(peer_uri)
|
showNotification(peer_uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"call established" -> {
|
"call established" -> {
|
||||||
val call = Call.find(calls, callp)
|
val call = Call.find(calls, callp)
|
||||||
@@ -1045,6 +1048,14 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun holdCallAt(call: Call, button: ImageButton) {
|
||||||
|
Log.i("Baresip", "Holding call with ${call.peerURI} at ${button.id}")
|
||||||
|
call_hold(call.callp)
|
||||||
|
call.hold = true
|
||||||
|
button.tag= "Resume"
|
||||||
|
button.setImageResource(R.drawable.resume)
|
||||||
|
}
|
||||||
|
|
||||||
private fun showNotification(peerUri: String) {
|
private fun showNotification(peerUri: String) {
|
||||||
Log.d("Baresip", "Showing notification")
|
Log.d("Baresip", "Showing notification")
|
||||||
val nb = NotificationCompat.Builder(this)
|
val nb = NotificationCompat.Builder(this)
|
||||||
@@ -1066,14 +1077,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
external fun baresipStart(path: String)
|
external fun baresipStart(path: String)
|
||||||
external fun baresipStop()
|
external fun baresipStop()
|
||||||
external fun ua_connect(ua: String, peer_uri: String): String
|
external fun uag_current(): String
|
||||||
external fun ua_answer(ua: String, call: String)
|
external fun uag_current_set(uap: String)
|
||||||
external fun ua_hold_answer(ua: String, call: String): Int
|
external fun ua_connect(uap: String, peer_uri: String): String
|
||||||
external fun ua_hangup(ua: String, call: String, code: Int, reason: String)
|
external fun ua_answer(uap: String, callp: String)
|
||||||
external fun call_peeruri(call: String): String
|
external fun ua_hold_answer(uap: String, callp: String): Int
|
||||||
external fun call_hold(call: String): Int
|
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
|
||||||
external fun call_unhold(call: String): Int
|
external fun call_peeruri(callp: String): String
|
||||||
external fun call_send_digit(call: String, digit: Char): Int
|
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 reload_config(): Int
|
external fun reload_config(): Int
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -1086,17 +1099,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
var filesPath = ""
|
var filesPath = ""
|
||||||
|
|
||||||
const val ACCOUNTS_CODE = 1
|
const val ACCOUNTS_CODE = 1
|
||||||
const val EDIT_CONTACTS_CODE = 2
|
const val CONTACTS_CODE = 2
|
||||||
const val EDIT_CONFIG_CODE = 3
|
const val EDIT_CONFIG_CODE = 3
|
||||||
const val HISTORY_CODE = 4
|
const val HISTORY_CODE = 4
|
||||||
const val ABOUT_CODE = 5
|
const val ABOUT_CODE = 5
|
||||||
const val ACCOUNT_CODE = 6
|
const val ACCOUNT_CODE = 6
|
||||||
|
const val CONTACT_CODE = 7
|
||||||
|
|
||||||
const val RECORD_AUDIO_PERMISSION = 1
|
const val RECORD_AUDIO_PERMISSION = 1
|
||||||
const val HISTORY_SIZE = 100
|
const val HISTORY_SIZE = 100
|
||||||
const val NOTIFICATION_ID = 10
|
const val NOTIFICATION_ID = 10
|
||||||
const val INCOMING_ID = 11
|
const val INCOMING_ID = 11
|
||||||
|
|
||||||
|
const val ONE_CALL_ONLY = false
|
||||||
|
|
||||||
external fun contacts_remove()
|
external fun contacts_remove()
|
||||||
external fun contact_add(contact: String)
|
external fun contact_add(contact: String)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user